Files
renderdoc/util/test/demos/vk/vk_shader_debug_zoo.cpp
T
Jake Turner 97149601da VK_Shader_Debug_Zoo changes for compute derivative tests
For compute quad derivatives tests use specific derivative i.e. fine or coarse.
It isn't specified which derivative mode is used, drivers differ on behaviour.
2026-05-06 18:33:03 +01:00

5869 lines
212 KiB
C++

/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2020-2026 Baldur Karlsson
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
#include <limits>
#include "3rdparty/fmt/core.h"
#include "vk_test.h"
RD_TEST(VK_Shader_Debug_Zoo, VulkanGraphicsTest)
{
static constexpr const char *Description = "Tests shader debugging on SPIR-V opcodes.";
struct ConstsA2V
{
Vec4f pos;
float zero;
float one;
float negone;
Vec2f uv;
};
struct PushData
{
Vec4i push;
Vec2u bda_uvec2;
uint32_t bda_hi;
uint32_t bda_lo;
uint64_t bda_u64;
};
struct BDA_Data
{
float f32[8];
};
std::string v2f =
R"EOSHADER(
struct flatv2f
{
uint test;
uint intval;
};
struct v2f
{
vec2 zeroVal;
vec2 inpos;
vec2 inposIncreased;
float tinyVal;
float oneVal;
float negoneVal;
};
layout(location = 1) inout_type flat flatv2f flatData;
layout(location = 3) inout_type v2f linearData;
)EOSHADER";
std::string vertex = R"EOSHADER(
#version 430 core
#define inout_type out
)EOSHADER" + v2f + R"EOSHADER(
layout(location = 0) in vec4 pos;
layout(location = 1) in float zero;
layout(location = 2) in float one;
layout(location = 3) in float negone;
void main()
{
int test = gl_InstanceIndex;
gl_Position = vec4(pos.x + pos.z * float(test % 256), pos.y + pos.w * float(test / 256), 0.0, 1.0);
const vec4 verts[4] = vec4[4](vec4(-1.0, -1.0, 0.5, 1.0), vec4(1.0, -1.0, 0.5, 1.0),
vec4(-1.0, 1.0, 0.5, 1.0), vec4(1.0, 1.0, 0.5, 1.0));
const vec2 data[3] = vec2[3](vec2(10.0f, 10.0f), vec2(20.0f, 10.0f), vec2(10.0f, 20.0f));
linearData.zeroVal = zero.xx;
linearData.oneVal = one;
linearData.negoneVal = negone;
linearData.tinyVal = one * 1.0e-30;
linearData.inpos = data[gl_VertexIndex];
linearData.inposIncreased = data[gl_VertexIndex] * 2.75f;
flatData.test = test;
flatData.intval = test + 7;
}
)EOSHADER";
std::string pixel_glsl_header = R"EOSHADER(
#version 460 core
#extension GL_EXT_samplerless_texture_functions : require
#extension GL_EXT_nonuniform_qualifier : require
#define TEST_DESC_INDEXING
layout(set = 0, binding = 10, std140) uniform constsbuf
{
vec4 first;
uint uniformIndex;
vec4 second;
vec4 nan;
vec4 third;
vec4 pad3;
vec4 fourth;
vec4 unorm2PackSource;
vec4 snorm2PackSource;
vec4 unorm4PackSource;
vec4 snorm4PackSource;
vec4 halfPackSource;
uint unormUnpackSource;
uint snormUnpackSource;
uint halfUnpackSource;
uint pad;
} cbuf;
layout(set = 0, binding = 11) uniform sampler pointSampler;
layout(set = 0, binding = 12) uniform sampler linearSampler;
layout(set = 0, binding = 13) uniform texture2D sampledImage;
layout(set = 0, binding = 14) uniform sampler2D linearSampledImage;
struct dummy
{
uvec4 val;
uvec4 val2;
};
layout(set = 0, binding = 15, std430) buffer storebuftype
{
layout(row_major) mat4 a;
layout(column_major) mat4 b;
vec4 x;
dummy y;
vec4 arr[];
} storebuf;
layout(set = 0, binding = 16, rgba32f) uniform coherent image2D storeImage;
layout(set = 0, binding = 17) uniform samplerBuffer texBuffer;
layout(set = 0, binding = 18, rgba32f) uniform coherent imageBuffer storeTexBuffer;
layout(set = 0, binding = 19) uniform sampler shadowSampler;
layout(set = 0, binding = 20) uniform samplerCube cubeSampler;
layout(set = 0, binding = 21, std430) buffer atomicbuftype
{
uvec4 data[];
} atomicbuf;
layout(set = 0, r32ui, binding = 22) uniform uimage2D atomicimg;
layout(set = 0, binding = 30) uniform sampler2DArray queryTest;
layout(set = 0, binding = 31) uniform sampler2DMSArray queryTestMS;
layout(set = 0, binding = 32) uniform texture2D depthImage;
layout(set = 0, binding = 33) uniform samplerBuffer texBuffer1010102unorm;
layout(set = 0, binding = 34, rgb10_a2) uniform imageBuffer storeTexBuffer1010102unorm;
layout(set = 0, binding = 35) uniform usamplerBuffer texBuffer1010102uint;
layout(set = 0, binding = 36, rgb10_a2ui) uniform uimageBuffer storeTexBuffer1010102uint;
#if TEST_DESC_INDEXING
layout(set = 1, binding = 1) uniform sampler pointSamplers[14];
layout(set = 1, binding = 2) uniform sampler linearSamplers[14];
layout(set = 1, binding = 3) uniform texture2D sampledImages[14];
layout(set = 1, binding = 4) uniform sampler2D linearSampledImages[14];
layout(set = 1, binding = 5, std430) buffer storebufstype
{
vec4 x;
dummy y;
vec4 arr[];
} storebufs[14];
layout(set = 1, binding = 6, rgba32f) uniform coherent image2D storeImages[14];
layout(set = 1, binding = 7) uniform samplerBuffer texBuffers[14];
layout(set = 1, binding = 8, rgba32f) uniform coherent imageBuffer storeTexBuffers[14];
layout(set = 1, binding = 9) uniform sampler shadowSamplers[14];
layout(set = 1, binding = 20) uniform sampler2DArray queryTests[14];
layout(set = 1, binding = 21) uniform sampler2DMSArray queryTestsMS[14];
layout(set = 2, binding = 0) uniform sampler1D zoo_1D;
layout(set = 2, binding = 1) uniform sampler2D zoo_2D;
layout(set = 2, binding = 2) uniform sampler3D zoo_3D;
layout(set = 2, binding = 3) uniform samplerCube zoo_Cube;
layout(set = 2, binding = 4) uniform sampler1DArray zoo_1DArray;
layout(set = 2, binding = 5) uniform sampler2DArray zoo_2DArray;
layout(set = 2, binding = 6) uniform samplerCubeArray zoo_CubeArray;
layout(set = 2, binding = 7) uniform sampler2DMS zoo_2DMS;
layout(set = 2, binding = 8) uniform sampler2DMSArray zoo_2DMSArray;
layout(set = 2, binding = 9) uniform samplerBuffer zoo_Buffer;
layout(set = 2, binding = 10) uniform usampler1D zoo_u1D;
layout(set = 2, binding = 11) uniform usampler2D zoo_u2D;
layout(set = 2, binding = 12) uniform usampler3D zoo_u3D;
layout(set = 2, binding = 13) uniform usamplerCube zoo_uCube;
layout(set = 2, binding = 14) uniform usampler1DArray zoo_u1DArray;
layout(set = 2, binding = 15) uniform usampler2DArray zoo_u2DArray;
layout(set = 2, binding = 16) uniform usamplerCubeArray zoo_uCubeArray;
layout(set = 2, binding = 17) uniform usampler2DMS zoo_u2DMS;
layout(set = 2, binding = 18) uniform usampler2DMSArray zoo_u2DMSArray;
layout(set = 2, binding = 19) uniform usamplerBuffer zoo_uBuffer;
layout(set = 2, binding = 20) uniform isampler1D zoo_i1D;
layout(set = 2, binding = 21) uniform isampler2D zoo_i2D;
layout(set = 2, binding = 22) uniform isampler3D zoo_i3D;
layout(set = 2, binding = 23) uniform isamplerCube zoo_iCube;
layout(set = 2, binding = 24) uniform isampler1DArray zoo_i1DArray;
layout(set = 2, binding = 25) uniform isampler2DArray zoo_i2DArray;
layout(set = 2, binding = 26) uniform isamplerCubeArray zoo_iCubeArray;
layout(set = 2, binding = 27) uniform isampler2DMS zoo_i2DMS;
layout(set = 2, binding = 28) uniform isampler2DMSArray zoo_i2DMSArray;
layout(set = 2, binding = 29) uniform isamplerBuffer zoo_iBuffer;
layout(set = 2, rgba32f, binding = 30) uniform image1D storezoo_1D;
layout(set = 2, rgba32f, binding = 31) uniform image2D storezoo_2D;
layout(set = 2, rgba32f, binding = 32) uniform image3D storezoo_3D;
layout(set = 2, rgba32f, binding = 33) uniform imageCube storezoo_Cube;
layout(set = 2, rgba32f, binding = 34) uniform image1DArray storezoo_1DArray;
layout(set = 2, rgba32f, binding = 35) uniform image2DArray storezoo_2DArray;
layout(set = 2, rgba32f, binding = 36) uniform imageCubeArray storezoo_CubeArray;
//layout(set = 2, rgba32f, binding = 37) uniform image2DMS storezoo_2DMS;
//layout(set = 2, rgba32f, binding = 38) uniform image2DMSArray storezoo_2DMSArray;
layout(set = 2, rgba32f, binding = 39) uniform imageBuffer storezoo_Buffer;
layout(set = 2, rgba32ui, binding = 40) uniform uimage1D storezoo_u1D;
layout(set = 2, rgba32ui, binding = 41) uniform uimage2D storezoo_u2D;
layout(set = 2, rgba32ui, binding = 42) uniform uimage3D storezoo_u3D;
layout(set = 2, rgba32ui, binding = 43) uniform uimageCube storezoo_uCube;
layout(set = 2, rgba32ui, binding = 44) uniform uimage1DArray storezoo_u1DArray;
layout(set = 2, rgba32ui, binding = 45) uniform uimage2DArray storezoo_u2DArray;
layout(set = 2, rgba32ui, binding = 46) uniform uimageCubeArray storezoo_uCubeArray;
//layout(set = 2, rgba32ui, binding = 47) uniform uimage2DMS storezoo_u2DMS;
//layout(set = 2, rgba32ui, binding = 48) uniform uimage2DMSArray storezoo_u2DMSArray;
layout(set = 2, rgba32ui, binding = 49) uniform uimageBuffer storezoo_uBuffer;
layout(set = 2, rgba32i, binding = 50) uniform iimage1D storezoo_i1D;
layout(set = 2, rgba32i, binding = 51) uniform iimage2D storezoo_i2D;
layout(set = 2, rgba32i, binding = 52) uniform iimage3D storezoo_i3D;
layout(set = 2, rgba32i, binding = 53) uniform iimageCube storezoo_iCube;
layout(set = 2, rgba32i, binding = 54) uniform iimage1DArray storezoo_i1DArray;
layout(set = 2, rgba32i, binding = 55) uniform iimage2DArray storezoo_i2DArray;
layout(set = 2, rgba32i, binding = 56) uniform iimageCubeArray storezoo_iCubeArray;
//layout(set = 2, rgba32i, binding = 57) uniform iimage2DMS storezoo_i2DMS;
//layout(set = 2, rgba32i, binding = 58) uniform iimage2DMSArray storezoo_i2DMSArray;
layout(set = 2, rgba32i, binding = 59) uniform iimageBuffer storezoo_iBuffer;
#endif
layout(push_constant) uniform PushData {
layout(offset = 16) ivec4 data;
} push;
)EOSHADER";
std::string pixel_glsl1 = pixel_glsl_header + R"EOSHADER(
layout(location = 0, index = 0) out vec4 Color;
#define inout_type in
)EOSHADER" + v2f +
R"EOSHADER(
vec2 inner_func(in vec2 modified)
{
modified.x += modified.y * 2.0f;
vec2 ret = modified;
return ret;
}
struct ScopeTest
{
vec2 modified;
};
vec4 varscope_test(int coord, vec2 inpos_param, vec2 inpos_incr_param, in ScopeTest scopeTest)
{
float never_in_scope;
if(coord < 0)
{
never_in_scope = inpos_param.x;
never_in_scope *= 2.0f;
}
vec4 ret;
// for the first pixel ret comes into scope early
if(coord == 0)
{
ret = vec4(0.5, 0.5, 0.5, 0.0);
}
float long_scope;
{
float short_scope;
short_scope = inpos_param.y;
short_scope = sin(short_scope);
long_scope = short_scope * inpos_incr_param.x;
}
if(coord != 0)
{
ret = vec4(1.0, 1.0, 1.0, 0.0);
}
ret.xy += inner_func(scopeTest.modified);
ret.zw += inner_func(scopeTest.modified);
ret.w += long_scope;
ret *= 1.5f;
return ret;
}
void main()
{
float posinf = linearData.oneVal/linearData.zeroVal.x;
float neginf = linearData.negoneVal/linearData.zeroVal.x;
float nan = linearData.zeroVal.x/linearData.zeroVal.y;
nan *= cbuf.nan.x;
float negone = linearData.negoneVal;
float posone = linearData.oneVal;
float zerof = linearData.zeroVal.x;
float tiny = linearData.tinyVal;
int intval = int(flatData.intval);
uint zerou = flatData.intval - flatData.test - 7u;
int zeroi = int(zerou);
uint test = flatData.test;
vec2 inpos = linearData.inpos;
vec2 inposIncreased = linearData.inposIncreased;
ivec2 localCoord = ivec2(gl_FragCoord) % ivec2(4, 4);
int flatLocalCoord = localCoord.x + localCoord.y * 4;
int flatGlobalCoord = int(gl_FragCoord.x) + int(gl_FragCoord.y) * 1024;
ScopeTest scopeTest;
scopeTest.modified = inposIncreased;
Color = vec4(0,0,0,0);
switch(test)
{
case 0:
{
Color = gl_FragCoord;
break;
}
case 1:
{
Color = dFdx(gl_FragCoord);
break;
}
case 2:
{
Color = dFdy(gl_FragCoord);
break;
}
case 3:
{
Color = dFdxCoarse(gl_FragCoord);
break;
}
case 4:
{
Color = dFdyCoarse(gl_FragCoord);
break;
}
case 5:
{
Color = dFdxFine(gl_FragCoord);
break;
}
case 6:
{
Color = dFdyFine(gl_FragCoord);
break;
}
case 7:
{
Color = dFdx(vec4(inpos, inposIncreased));
break;
}
case 8:
{
Color = dFdy(vec4(inpos, inposIncreased));
break;
}
case 9:
{
Color = dFdxCoarse(vec4(inpos, inposIncreased));
break;
}
case 10:
{
Color = dFdyCoarse(vec4(inpos, inposIncreased));
break;
}
case 11:
{
Color = dFdxFine(vec4(inpos, inposIncreased));
break;
}
case 12:
{
Color = dFdyFine(vec4(inpos, inposIncreased));
break;
}
case 13:
{
Color = vec4(abs(posone*2.5f), abs(negone*2.5f), abs(zerof*2.5f), 1.0f);
break;
}
case 14:
{
Color = vec4(pow(posone*2.5f, posone*1.3f), pow(posone*2.5f, posone*0.45f),
pow(vec2(posone*2.5f, posone*1.3f), vec2(posone*0.9f, posone*8.5f)));
break;
}
case 15:
{
Color = vec4(normalize(posone*2.5f), normalize(posone), normalize(negone), 1.0f);
break;
}
case 16:
{
Color = vec4(normalize(vec2(posone*2.5f, negone*1.8f)), normalize(vec2(posone*8.5f, negone*7.1f)));
break;
}
case 17:
{
Color = vec4(normalize(vec3(posone*2.5f, negone*1.8f, posone*8.5f)), 1.0f);
break;
}
case 18:
{
Color = normalize(vec4(posone*2.5f, negone*1.8f, posone*8.5f, negone*5.2f));
break;
}
case 19:
{
Color = vec4(floor(posone*2.5f), floor(posone*2.4f), floor(posone*2.6f), floor(zerof));
break;
}
case 20:
{
Color = vec4(floor(negone*2.5f), floor(negone*2.4f), floor(negone*2.6f), 1.0f);
break;
}
case 21:
{
Color = vec4(mix(posone*1.1f, posone*3.3f, 0.5f),
mix(posone*1.1f, posone*3.3f, 0.2f),
mix(posone*1.1f, posone*3.3f, 0.8f),
1.0f);
break;
}
case 22:
{
Color = vec4(mix(posone*1.1f, posone*3.3f, 1.5f),
mix(posone*1.1f, posone*3.3f, -0.3f),
0.0f,
1.0f);
break;
}
case 23:
{
Color = vec4(mix(posone*3.3f, posone*1.1f, 0.5f),
mix(posone*3.3f, posone*1.1f, 0.2f),
mix(posone*3.3f, posone*1.1f, 0.8f),
1.0f);
break;
}
case 24:
{
vec3 a = vec3(posone*2.5f, negone*1.8f, posone*8.5f);
vec3 b = vec3(negone*6.3f, posone*3.2f, negone*0.4f);
Color = vec4(cross(a, b), 1.0f);
break;
}
case 25:
{
vec4 a = vec4(posone*2.5f, negone*1.8f, posone*8.5f, posone*3.9f);
vec4 b = vec4(negone*6.3f, posone*3.2f, negone*0.4f, zerof);
Color = vec4(dot(a.xyz, b.xyz), dot(a.w, b.w), dot(a, b), dot(a.wz, b.ww));
break;
}
case 26:
{
Color = cbuf.first;
break;
}
case 27:
{
Color = cbuf.second;
break;
}
case 28:
{
Color = cbuf.third;
break;
}
case 29:
{
Color = cbuf.fourth;
break;
}
case 30:
{
Color = cbuf.first + cbuf.second + cbuf.third + cbuf.fourth +
cbuf.pad3;
break;
}
case 31:
{
ivec2 coord = ivec2(zeroi + 20, zeroi + 20);
Color = texelFetch(sampledImage, coord, 0);
break;
}
case 32:
{
vec2 coord = vec2(zerof + 0.5, zerof + 0.145);
Color = textureLod(sampler2D(sampledImage, pointSampler), coord, 0.0);
break;
}
case 33:
{
vec2 coord = vec2(zerof + 0.5, zerof + 0.145);
Color = textureLod(sampler2D(sampledImage, linearSampler), coord, 0.0);
break;
}
case 34:
{
Color = texture(linearSampledImage, inpos);
break;
}
case 35:
{
Color = vec4(max(posone*3.3f, posone*4.4f),
max(posone*4.4f, posone*3.3f),
max(posone, posinf),
max(posone, neginf));
break;
}
case 36:
{
Color = vec4(max(negone*3.3f, negone*4.4f),
max(negone*4.4f, negone*3.3f),
max(negone, posinf),
max(negone, neginf));
break;
}
case 37:
{
Color = vec4(min(posone*3.3f, posone*4.4f),
min(posone*4.4f, posone*3.3f),
min(posone, posinf),
min(posone, neginf));
break;
}
case 38:
{
Color = vec4(min(negone*3.3f, negone*4.4f),
min(negone*4.4f, negone*3.3f),
min(negone, posinf),
min(negone, neginf));
break;
}
case 39:
{
Color = vec4(float(max(zeroi+5, zeroi+8)),
float(max(zeroi+8, zeroi+5)),
float(max(zeroi-8, zeroi-5)),
float(max(zeroi-5, zeroi-8)));
break;
}
case 40:
{
Color = vec4(float(min(zeroi+5, zeroi+8)),
float(min(zeroi+8, zeroi+5)),
float(min(zeroi-8, zeroi-5)),
float(min(zeroi-5, zeroi-8)));
break;
}
case 41:
{
Color = vec4(float(max(zerou+5, zerou+8)),
float(max(zerou+8, zerou+5)),
float(min(zerou+8, zerou+5)),
float(min(zerou+5, zerou+8)));
break;
}
case 42:
{
Color = vec4(clamp(posone*3.3f, posone, posone*5.0f),
clamp(posone*0.3f, posone, posone*5.0f),
clamp(posone*8.3f, posone, posone*5.0f),
1.0f);
break;
}
case 43:
{
uint x = uint(posone);
Color = vec4(float(clamp(x*4, zerou+2, zerou+50)),
float(clamp(x, zerou+2, zerou+50)),
float(clamp(x*400, zerou+2, zerou+50)),
1.0f);
break;
}
case 44:
{
int x = int(posone);
Color = vec4(float(clamp(x*4, zeroi+2, zeroi+50)),
float(clamp(x, zeroi+2, zeroi+50)),
float(clamp(x*400, zeroi+2, zeroi+50)),
1.0f);
break;
}
case 45:
{
Color = vec4(float(abs(zeroi+2)),
float(abs(zeroi)),
float(abs(zeroi-5)),
1.0f);
break;
}
case 46:
{
Color = fwidth(gl_FragCoord);
break;
}
case 47:
{
Color = fwidthCoarse(gl_FragCoord);
break;
}
case 48:
{
Color = fwidthFine(gl_FragCoord);
break;
}
case 49:
{
Color = fwidth(vec4(inpos, inposIncreased));
break;
}
case 50:
{
Color = fwidthCoarse(vec4(inpos, inposIncreased));
break;
}
)EOSHADER"
R"EOSHADER(
case 51:
{
Color = fwidthFine(vec4(inpos, inposIncreased));
break;
}
case 52:
{
Color = vec4(isinf(posone) ? 1.0f : 0.0f, isinf(zerof) ? 1.0f : 0.0f, isinf(negone) ? 1.0f : 0.0f, 1.0f);
break;
}
case 53:
{
Color = vec4(isnan(posone) ? 1.0f : 0.0f, isnan(zerof) ? 1.0f : 0.0f, isnan(negone) ? 1.0f : 0.0f, 1.0f);
break;
}
case 54:
{
Color = vec4(isinf(posinf) ? 1.0f : 0.0f, isinf(neginf) ? 1.0f : 0.0f, isinf(nan) ? 1.0f : 0.0f, 1.0f);
break;
}
case 55:
{
Color = vec4(isnan(posinf) ? 1.0f : 0.0f, isnan(neginf) ? 1.0f : 0.0f, isnan(nan) ? 1.0f : 0.0f, 1.0f);
break;
}
case 56:
{
Color = vec4(push.data);
break;
}
case 57:
{
Color = vec4(roundEven(posone*2.5f), roundEven(posone*3.5f), roundEven(posone*4.5f), roundEven(posone*5.1f));
break;
}
case 58:
{
Color = vec4(roundEven(negone*2.5f), roundEven(negone*3.5f), roundEven(negone*4.5f), roundEven(negone*5.1f));
break;
}
case 59:
{
// avoid implementation-defined behaviour at half-way points
Color = vec4(round(posone*2.4f), round(posone*3.6f), round(posone*4.6f), round(posone*5.1f));
break;
}
case 60:
{
Color = vec4(round(negone*2.6f), round(negone*3.6f), round(negone*4.6f), round(posone*5.1f));
break;
}
case 61:
{
Color = vec4(trunc(posone*2.4f), trunc(posone*2.5f), trunc(posone*2.6f), trunc(posone*5.1f));
break;
}
case 62:
{
Color = vec4(trunc(negone*2.4f), trunc(negone*2.5f), trunc(negone*2.6f), trunc(negone*3.1f));
break;
}
case 63:
{
Color = vec4(fract(posone*2.4f), fract(posone*2.5f), fract(posone*2.6f), fract(posone*3.1f));
break;
}
case 64:
{
Color = vec4(fract(negone*2.4f), fract(negone*2.5f), fract(negone*2.6f), fract(negone*3.1f));
break;
}
case 65:
{
Color = vec4(ceil(posone*2.4f), ceil(posone*2.5f), ceil(posone*2.6f), ceil(posone*3.1f));
break;
}
case 66:
{
Color = vec4(ceil(negone*2.4f), ceil(negone*2.5f), ceil(negone*2.6f), ceil(negone*3.1f));
break;
}
case 67:
{
Color = vec4(sign(negone*2.4f), sign(posone*2.4f), sign(posinf), sign(neginf));
break;
}
case 68:
{
int onei = zeroi+1;
int negi = zeroi-1;
Color = vec4(float(sign(onei*2)), float(sign(negi*2)), float(sign(0)), 1.0f);
break;
}
case 69:
{
Color = vec4(degrees(negone*2.4f), degrees(posone*2.4f), degrees(zerof), degrees(posone*34.56f));
break;
}
case 70:
{
Color = vec4(radians(negone*164.2f), radians(posone*164.2f), radians(zerof), radians(posone*3456.78f));
break;
}
case 71:
{
vec4 a = vec4(posone*2.4f, posone*2.5f, posone*2.6f, posone*2.7f);
vec4 b = vec4(zerof+2.5f, zerof+2.5f, zerof+2.5f, zerof+2.5f);
Color = vec4(float(a.x < b.x), float(a.x <= b.x), float(a.x > b.x), float(a.x >= b.x));
break;
}
case 72:
{
vec4 a = vec4(posone*2.4f, posone*2.5f, posone*2.6f, posone*2.7f);
vec4 b = vec4(zerof+2.5f, zerof+2.5f, zerof+2.5f, zerof+2.5f);
bvec4 c = lessThanEqual(a, b);
Color = vec4(float(a.x == b.x), float(a.x != b.x), 0.0f, 1.0f);
break;
}
case 73:
{
ivec4 a = ivec4(zeroi+2, zeroi+3, zeroi+4, zeroi+5);
ivec4 b = ivec4(zeroi+4, zeroi+4, zeroi+4, zeroi+4);
Color = vec4(float(a.x < b.x), float(a.x <= b.x), float(a.x > b.x), float(a.x >= b.x));
break;
}
case 74:
{
ivec4 a = ivec4(zeroi+2, zeroi+3, zeroi+4, zeroi+5);
ivec4 b = ivec4(zeroi+4, zeroi+4, zeroi+4, zeroi+4);
Color = vec4(float(a.x == b.x), float(a.x != b.x), 0.0f, 1.0f);
break;
}
case 75:
{
uvec4 a = uvec4(zerou+2, zerou+3, zerou+4, zerou+5);
uvec4 b = uvec4(zerou+4, zerou+4, zerou+4, zerou+4);
Color = vec4(float(a.x < b.x), float(a.x <= b.x), float(a.x > b.x), float(a.x >= b.x));
break;
}
case 76:
{
uvec4 a = uvec4(zerou+2, zerou+3, zerou+4, zerou+5);
uvec4 b = uvec4(zerou+4, zerou+4, zerou+4, zerou+4);
Color = vec4(float(a.x == b.x), float(a.x != b.x), 0.0f, 1.0f);
break;
}
case 77:
{
vec4 a = vec4(posone*2.4f, posone*2.5f, posone*2.6f, posone*2.7f);
vec4 b = vec4(zerof+2.5f, zerof+2.5f, zerof+2.5f, zerof+2.5f);
bvec4 c = lessThanEqual(a, b);
Color = vec4(float(any(c)), float(all(c)), float(c.x == c.z), float(c.x != c.w));
break;
}
case 78:
{
vec4 a = vec4(posone*2.4f, posone*2.5f, posone*2.6f, posone*2.7f);
vec4 b = vec4(zerof+2.5f, zerof+2.5f, zerof+2.5f, zerof+2.5f);
bvec4 c = lessThanEqual(a, b);
Color = vec4(float(c.x || c.y), float(c.x && c.y), float(!c.x), 1.0f);
break;
}
case 79:
{
vec4 a = vec4(posone*2.4f, posone*2.5f, posone*2.6f, posone*2.7f);
vec4 b = vec4(zerof+2.5f, zerof+2.5f, zerof+2.5f, zerof+2.5f);
bvec4 c = lessThanEqual(a, b);
Color = mix(vec4(posone*9.0f, posone*8.0f, posone*7.0f, posone*6.0f),
vec4(posone*1.0f, posone*2.0f, posone*3.0f, posone*4.0f), c);
break;
}
case 80:
{
discard;
}
case 81:
{
Color = vec4(sin(posone*2.4f), cos(posone*2.4f), asin(posone*2.4f), acos(posone*2.4f));
break;
}
case 82:
{
Color = vec4(sinh(posone*2.4f), cosh(posone*2.4f), asinh(posone*2.4f), acosh(posone*2.4f));
break;
}
case 83:
{
Color = vec4(tan(posone*2.4f), tanh(posone*2.4f), atan(posone*2.4f), atanh(posone*2.4f));
break;
}
case 84:
{
Color = vec4(atan(posone*2.4f, posone*5.7f), sqrt(posone*2.4f), inversesqrt(posone*2.4f), 1.0f);
break;
}
case 85:
{
Color = vec4(log(posone*2.4f), log2(posone*2.4f), exp(posone*2.4f), exp2(posone*2.4f));
break;
}
case 86:
{
vec4 a = vec4(posone*2.4f, posone*2.5f, posone*2.6f, posone*2.7f);
vec4 b = vec4(zerof+2.5f, zerof+2.5f, zerof+2.5f, zerof+2.5f);
Color = vec4(length(a), length(b), distance(a, b), 1.0f);
break;
}
case 87:
{
vec4 a = vec4(posone*2.4f, posone*2.5f, posone*2.6f, posone*2.7f);
Color = normalize(a);
break;
}
case 88:
{
vec4 a = vec4(posone*2.4f, posone*2.5f, posone*2.6f, posone*2.7f);
vec4 b = vec4(zerof+2.5f, zerof+2.5f, zerof+2.5f, zerof+2.5f);
Color = refract(a, b, zerof+3.1f);
break;
}
case 89:
{
Color = vec4(fma(zerof+2.4f, posone*0.1f, posone*8.3f),
fma(zerof+2.4f, posone*0.0f, posone*8.3f),
fma(zerof+3.675f, posone*9.703f, posone*1.45f),
((zerof+3.675f) * (posone*9.703f)) + posone*1.45f);
break;
}
case 90:
{
Color = vec4(step(posone*2.6f, zerof+2.4f),
step(posone*2.6f, zerof+2.5f),
step(posone*2.6f, zerof+2.6f),
step(posone*2.6f, zerof+2.7f));
break;
}
case 91:
{
Color = vec4(smoothstep(posone*2.0f, posone*2.6f, zerof+1.9f),
smoothstep(posone*2.0f, posone*2.6f, zerof+2.0f),
smoothstep(posone*2.0f, posone*2.6f, zerof+2.1f),
smoothstep(posone*2.0f, posone*2.6f, zerof+2.3f));
break;
}
case 92:
{
Color = vec4(smoothstep(posone*2.0f, posone*2.6f, zerof+2.4f),
smoothstep(posone*2.0f, posone*2.6f, zerof+2.5f),
smoothstep(posone*2.0f, posone*2.6f, zerof+2.6f),
smoothstep(posone*2.0f, posone*2.6f, zerof+2.8f));
break;
}
case 93:
{
vec4 N = vec4(posone*1.4f, posone*2.8f, posone*5.6f, posone*4.4f);
vec4 I = vec4(posone*3.7f, posone*2.2f, posone*6.1f, posone*9.5f);
vec4 Nref = vec4(posone*6.4f, posone*7.5f, posone*8.3f, posone*0.9f);
Color = faceforward(N, I, Nref);
break;
}
case 94:
{
vec4 N = vec4(posone*1.4f, posone*2.8f, posone*5.6f, posone*4.4f);
vec4 I = vec4(posone*3.7f, posone*2.2f, posone*6.1f, posone*9.5f);
Color = reflect(N, I);
break;
}
case 95:
{
Color = vec4(ldexp(posone*1.4f, zeroi-3),
ldexp(posone*2.8f, zeroi+0),
ldexp(posone*5.6f, zeroi+3),
ldexp(posone*4.4f, zeroi+7));
break;
}
case 96:
{
uint a = zerou + 0xb0b0b0b0;
uint b = zerou + 0x12345678;
// add and sub with no carry/borrow
uint y;
uint x = uaddCarry(a, b, y);
uint w;
uint z = usubBorrow(a, b, w);
Color = vec4(float(x), float(y), float(z), float(w));
break;
}
case 97:
{
uint a = zerou + 0xb0b0b0b0;
uint b = zerou + 0xdeadbeef;
// add and sub with carry/borrow
uint y;
uint x = uaddCarry(a, b, y);
uint w;
uint z = usubBorrow(a, b, w);
Color = vec4(float(x), float(y), float(z), float(w));
break;
}
case 98:
{
uint a = zerou + 0xb0b0b0b0;
uint b = zerou + 0xdeadbeef;
// add and sub with carry/borrow
uint y;
uint x = uaddCarry(a, b, y);
uint w;
uint z = usubBorrow(a, b, w);
Color = vec4(float(x), float(y), float(z), float(w));
break;
}
case 99:
{
uint a = zerou + 0x1234;
uint b = zerou + 0x5678;
int c = zeroi + 0x1234;
int d = zeroi + 0x5678;
// positive mul with no overflow
uint x, y;
umulExtended(a, b, y, x);
int z, w;
imulExtended(c, d, w, z);
Color = vec4(float(x), float(y), float(z), float(w));
break;
}
case 100:
{
uint a = zerou + 0x123456;
uint b = zerou + 0x78abcd;
int c = zeroi + 0x123456;
int d = zeroi + 0x78abcd;
// positive mul with overflow
uint x, y;
umulExtended(a, b, y, x);
int z, w;
imulExtended(c, d, w, z);
Color = vec4(float(x), float(y), float(z), float(w));
break;
}
case 101:
{
int a = zeroi - 0x1234;
int b = zeroi - 0x5678;
int c = zeroi - 0x123456;
int d = zeroi - 0x78abcd;
// negative mul with and without overflow
int x, y;
imulExtended(a, b, y, x);
int z, w;
imulExtended(c, d, w, z);
Color = vec4(float(x), float(y), float(z), float(w));
break;
}
)EOSHADER"
R"EOSHADER(
case 102:
{
uint a = zerou + 0x0dadbeef;
int b = zeroi + 0x0dadbeef;
Color = vec4(float(findLSB(a)), float(findLSB(b)), float(findMSB(a)), float(findMSB(b)));
break;
}
case 103:
{
int a = zeroi - 0x0dadbeef;
Color = vec4(float(findLSB(a)), float(findLSB(zeroi)), float(findMSB(a)), float(findMSB(zeroi)));
break;
}
case 104:
{
uint a = zerou + 0x44b82a24;
int b = zeroi + 0x44b82a24;
Color = vec4(float(bitCount(a)), float(bitCount(b)), uintBitsToFloat(bitfieldReverse(a)), intBitsToFloat(bitfieldReverse(b)));
break;
}
case 105:
{
uint a = zerou + 0x44b82a24;
int b = zeroi + 0x44b82a24;
uint af = zerou+0xffffffff;
int bf = zeroi-1;
Color = vec4(float(bitfieldExtract(a, 4, 5)), float(bitfieldExtract(b, 4, 5)),
uintBitsToFloat(bitfieldInsert(a, af, 4, 5)), intBitsToFloat(bitfieldInsert(b, bf, 4, 5)));
break;
}
case 106:
{
Color = vec4(float(textureQueryLevels(queryTest)), float(textureSamples(queryTestMS)), 0.0f, 1.0f);
break;
}
case 107:
{
Color = vec4(vec3(textureSize(queryTest, 0)), 1.0f);
break;
}
case 108:
{
Color = vec4(vec3(textureSize(queryTest, 1)), 1.0f);
break;
}
case 109:
{
Color = vec4(vec3(textureSize(queryTestMS)), 1.0f);
break;
}
case 110:
{
Color = vec4(vec3(textureSize(queryTestMS)), 1.0f);
break;
}
case 111:
{
Color = texelFetch(texBuffer, int(zeroi+2));
break;
}
case 112:
{
float x = texture(sampler2DShadow(depthImage, shadowSampler), vec3(inpos, 0.1f));
float y = texture(sampler2DShadow(depthImage, shadowSampler), vec3(inpos, 0.3f));
float z = texture(sampler2DShadow(depthImage, shadowSampler), vec3(inpos, 0.7f));
float w = texture(sampler2DShadow(depthImage, shadowSampler), vec3(inpos, 0.9f));
Color = vec4(x, y, z, w);
break;
}
case 113:
{
vec2 coord = vec2(zerof + 0.6, zerof + 0.43);
Color = textureGather(linearSampledImage, coord, 0);
break;
}
case 114:
{
vec2 coord = vec2(zerof + 0.6, zerof + 0.43);
Color = textureGather(linearSampledImage, coord, 1);
break;
}
case 115:
{
vec2 coord = vec2(zerof + 0.6, zerof + 0.43);
Color = textureGather(linearSampledImage, coord, 2);
break;
}
case 116:
{
vec2 coord = vec2(zerof + 0.6, zerof + 0.43);
Color = textureGather(sampler2DShadow(depthImage, shadowSampler), coord, 0.8f);
break;
}
case 117:
{
uint packed = packHalf2x16(cbuf.halfPackSource.xy);
Color = vec4(float((packed & 0xff000000) >> 24),
float((packed & 0x00ff0000) >> 16),
float((packed & 0x0000ff00) >> 8),
float((packed & 0x000000ff) >> 0));
break;
}
case 118:
{
vec2 unpacked = unpackHalf2x16(cbuf.halfUnpackSource);
Color = unpacked.xyxy;
break;
}
case 119:
{
uint packed = packUnorm2x16(cbuf.unorm2PackSource.xy);
Color = vec4(float((packed & 0xff000000) >> 24),
float((packed & 0x00ff0000) >> 16),
float((packed & 0x0000ff00) >> 8),
float((packed & 0x000000ff) >> 0));
break;
}
case 120:
{
uint packed = packUnorm4x8(cbuf.unorm4PackSource);
Color = vec4(float((packed & 0xff000000) >> 24),
float((packed & 0x00ff0000) >> 16),
float((packed & 0x0000ff00) >> 8),
float((packed & 0x000000ff) >> 0));
break;
}
case 121:
{
uint packed = packSnorm2x16(cbuf.snorm2PackSource.xy);
Color = vec4(float((packed & 0xff000000) >> 24),
float((packed & 0x00ff0000) >> 16),
float((packed & 0x0000ff00) >> 8),
float((packed & 0x000000ff) >> 0));
break;
}
case 122:
{
uint packed = packSnorm4x8(cbuf.snorm4PackSource);
Color = vec4(float((packed & 0xff000000) >> 24),
float((packed & 0x00ff0000) >> 16),
float((packed & 0x0000ff00) >> 8),
float((packed & 0x000000ff) >> 0));
break;
}
case 123:
{
vec2 unpacked = unpackUnorm2x16(cbuf.unormUnpackSource);
Color = unpacked.xyxy;
break;
}
case 124:
{
vec4 unpacked = unpackUnorm4x8(cbuf.unormUnpackSource);
Color = unpacked;
break;
}
case 125:
{
vec2 unpacked = unpackSnorm2x16(cbuf.snormUnpackSource);
Color = unpacked.xyxy;
break;
}
case 126:
{
vec4 unpacked = unpackSnorm4x8(cbuf.snormUnpackSource);
Color = unpacked;
break;
}
case 127:
{
uint len = storebuf.arr.length();
Color = vec4(float(len), float(len), float(len), float(len));
break;
}
case 128:
{
// test storage buffer write here, we'll read from it in GLSL test 2
storebuf.x = vec4(3.1f, 4.1f, 5.9f, 2.6f);
storebuf.y.val = uvec4(31, 41, 59, 26);
storebuf.arr[flatData.intval - flatData.test] = vec4(inpos, inposIncreased);
Color = storebuf.x;
break;
}
case 129:
{
Color = textureProj(linearSampledImage, vec3(inpos, 0.5f));
break;
}
case 130:
{
Color.xy = textureQueryLod(linearSampledImage, inpos);
Color.zw = textureQueryLod(linearSampledImage, vec2(1.0f, 1.0f)/inpos);
break;
}
case 131:
{
Color = vec4(vec2(imageSize(storeImage)), 0.0f, 1.0f);
break;
}
case 132:
{
Color = vec4(float(imageSize(storeTexBuffer)), 0.0f, 0.0f, 1.0f);
break;
}
case 133:
{
imageStore(storeImage, ivec2(zeroi+1,zeroi+3), vec4(3.1f, 4.1f, 5.9f, 2.6f));
Color = imageLoad(storeImage, ivec2(zeroi+1,zeroi+3));
break;
}
#if TEST_DESC_INDEXING
case 134:
{
ivec2 coord = ivec2(zeroi + 20, zeroi + 20);
Color = texelFetch(sampledImages[1], coord, 0);
break;
}
case 135:
{
vec2 coord = vec2(zerof + 0.5, zerof + 0.145);
Color = textureLod(sampler2D(sampledImages[2], pointSamplers[3]), coord, 0.0);
break;
}
case 136:
{
vec2 coord = vec2(zerof + 0.5, zerof + 0.145);
Color = textureLod(sampler2D(sampledImages[2], linearSamplers[3]), coord, 0.0);
break;
}
case 137:
{
Color = texture(linearSampledImages[4], inpos.xy);
break;
}
case 138:
{
ivec2 coord = ivec2(zeroi + 20, zeroi + 20);
Color = texelFetch(sampledImages[cbuf.uniformIndex+1], coord, 0);
break;
}
case 139:
{
vec2 coord = vec2(zerof + 0.5, zerof + 0.145);
Color = textureLod(sampler2D(sampledImages[cbuf.uniformIndex+2], pointSamplers[cbuf.uniformIndex+3]), coord, 0.0);
break;
}
case 140:
{
vec2 coord = vec2(zerof + 0.5, zerof + 0.145);
Color = textureLod(sampler2D(sampledImages[cbuf.uniformIndex+2], linearSamplers[cbuf.uniformIndex+3]), coord, 0.0);
break;
}
case 141:
{
Color = texture(linearSampledImages[cbuf.uniformIndex+4], inpos.xy);
break;
}
case 142:
{
ivec2 coord = ivec2(zeroi + 20, zeroi + 20);
Color = texelFetch(sampledImages[nonuniformEXT(zeroi)+9], coord, 0);
break;
}
case 143:
{
vec2 coord = vec2(zerof + 0.5, zerof + 0.145);
Color = textureLod(sampler2D(sampledImages[nonuniformEXT(zeroi)+10], pointSamplers[nonuniformEXT(zeroi)+11]), coord, 0.0);
break;
}
case 144:
{
vec2 coord = vec2(zerof + 0.5, zerof + 0.145);
Color = textureLod(sampler2D(sampledImages[nonuniformEXT(zeroi)+10], linearSamplers[nonuniformEXT(zeroi)+11]), coord, 0.0);
break;
}
case 145:
{
Color = texture(linearSampledImages[nonuniformEXT(zeroi)+12], inpos.xy);
break;
}
case 146:
{
Color = vec4(float(textureQueryLevels(queryTests[0])), float(textureSamples(queryTestsMS[0])), 0.0f, 1.0f);
break;
}
case 147:
{
Color = vec4(float(textureQueryLevels(queryTests[zeroi+3])), float(textureSamples(queryTestsMS[zeroi+3])), 0.0f, 1.0f);
break;
}
case 148:
{
Color = vec4(float(textureQueryLevels(queryTests[nonuniformEXT(zeroi)+5])), float(textureSamples(queryTestsMS[nonuniformEXT(zeroi)+5])), 0.0f, 1.0f);
break;
}
case 149:
{
uint len = storebufs[zeroi+7].arr.length();
Color = vec4(float(len), float(len), float(len), float(len));
break;
}
case 150:
{
// test storage buffer write here, we'll read from it in GLSL test 2
storebufs[zeroi+7].x = vec4(3.1f, 4.1f, 5.9f, 2.6f);
storebufs[zeroi+7].y.val = uvec4(31, 41, 59, 26);
storebufs[zeroi+7].arr[flatData.intval - flatData.test] = vec4(inpos, inposIncreased);
Color = storebufs[zeroi+7].x;
break;
}
case 151:
{
imageStore(storeImages[zeroi+7], ivec2(zeroi+1,zeroi+3), vec4(3.1f, 4.1f, 5.9f, 2.6f));
Color = imageLoad(storeImages[zeroi+7], ivec2(zeroi+1,zeroi+3));
break;
}
case 152:
{
float x = texture(sampler2DShadow(sampledImages[zeroi+5], shadowSamplers[zeroi+8]), vec3(inpos, 0.1f));
float y = texture(sampler2DShadow(sampledImages[zeroi+5], shadowSamplers[zeroi+8]), vec3(inpos, 0.3f));
float z = texture(sampler2DShadow(sampledImages[zeroi+5], shadowSamplers[zeroi+8]), vec3(inpos, 0.7f));
float w = texture(sampler2DShadow(sampledImages[zeroi+5], shadowSamplers[zeroi+8]), vec3(inpos, 0.9f));
Color = vec4(x, y, z, w);
break;
}
#endif
)EOSHADER"
R"EOSHADER(
case 153:
{
vec3 cubeCoord = vec3(1.0f, -0.3f, 0.9f);
Color = textureLod(cubeSampler, cubeCoord, 0.0f);
break;
}
case 154:
{
vec3 cubeCoord = vec3(-1.0f, -0.3f, 0.9f);
Color = textureLod(cubeSampler, cubeCoord, 0.0f);
break;
}
case 155:
{
vec3 cubeCoord = vec3(-1.0f, 0.3f, 0.9f);
Color = textureLod(cubeSampler, cubeCoord, 0.0f);
break;
}
case 156:
{
vec3 cubeCoord = vec3(-1.0f, 0.3f, -0.9f);
Color = textureLod(cubeSampler, cubeCoord, 0.0f);
break;
}
case 157:
{
uint old = atomicAdd(atomicbuf.data[flatGlobalCoord].x, flatGlobalCoord);
Color = vec4(float(old & 0xfffff), float(atomicbuf.data[flatGlobalCoord].x & 0xfffff), 0.0f, 0.0f);
break;
}
case 158:
{
uint old = atomicOr(atomicbuf.data[flatGlobalCoord].x, 0x55555555U);
Color = vec4(float(old & 0xfffff), float(atomicbuf.data[flatGlobalCoord].x & 0xfffff), 0.0f, 0.0f);
break;
}
case 159:
{
uint old = atomicXor(atomicbuf.data[flatGlobalCoord].x, 0x55555555U);
Color = vec4(float(old & 0xfffff), float(atomicbuf.data[flatGlobalCoord].x & 0xfffff), 0.0f, 0.0f);
break;
}
case 160:
{
uint old = atomicMax(atomicbuf.data[flatGlobalCoord].x, 0x55555555U);
uint old2 = atomicMax(atomicbuf.data[flatGlobalCoord].y, 0x38383838U);
Color = vec4(float(old & 0xfffff), float(atomicbuf.data[flatGlobalCoord].x & 0xfffff),
float(old2 & 0xfffff), float(atomicbuf.data[flatGlobalCoord].y & 0xfffff));
break;
}
case 161:
{
uint old = atomicMin(atomicbuf.data[flatGlobalCoord].x, 0x55555555U);
uint old2 = atomicMin(atomicbuf.data[flatGlobalCoord].y, 0x38383838U);
Color = vec4(float(old & 0xfffff), float(atomicbuf.data[flatGlobalCoord].x & 0xfffff),
float(old2 & 0xfffff), float(atomicbuf.data[flatGlobalCoord].y & 0xfffff));
break;
}
case 162:
{
uint old = atomicExchange(atomicbuf.data[flatGlobalCoord].x, 0x12345678U);
Color = vec4(float(old & 0xfffff), float(atomicbuf.data[flatGlobalCoord].x & 0xfffff), 0.0f, 0.0f);
break;
}
case 163:
{
uint old = atomicCompSwap(atomicbuf.data[flatGlobalCoord].x, 0x55555555U, 0x12345678U);
uint old2 = atomicCompSwap(atomicbuf.data[flatGlobalCoord].y, 0x42424242U, 0x12345678U);
Color = vec4(float(old & 0xfffff), float(atomicbuf.data[flatGlobalCoord].x & 0xfffff),
float(old2 & 0xfffff), float(atomicbuf.data[flatGlobalCoord].y & 0xfffff));
break;
}
case 164:
{
uint old = imageAtomicAdd(atomicimg, ivec2(gl_FragCoord), flatGlobalCoord);
Color = vec4(float(old & 0xfffff), float(imageLoad(atomicimg, ivec2(gl_FragCoord)).x & 0xfffff), 0.0f, 0.0f);
break;
}
case 165:
{
uint old = imageAtomicOr(atomicimg, ivec2(gl_FragCoord), 0x55555555U);
Color = vec4(float(old & 0xfffff), float(imageLoad(atomicimg, ivec2(gl_FragCoord)).x & 0xfffff), 0.0f, 0.0f);
break;
}
case 166:
{
uint old = imageAtomicXor(atomicimg, ivec2(gl_FragCoord), 0x55555555U);
Color = vec4(float(old & 0xfffff), float(imageLoad(atomicimg, ivec2(gl_FragCoord)).x & 0xfffff), 0.0f, 0.0f);
break;
}
case 167:
{
uint old = imageAtomicMax(atomicimg, ivec2(gl_FragCoord), 0x55555555U);
Color = vec4(float(old & 0xfffff), float(imageLoad(atomicimg, ivec2(gl_FragCoord)).x & 0xfffff), 0.0f, 0.0f);
break;
}
case 168:
{
uint old = imageAtomicMin(atomicimg, ivec2(gl_FragCoord), 0x55555555U);
Color = vec4(float(old & 0xfffff), float(imageLoad(atomicimg, ivec2(gl_FragCoord)).x & 0xfffff), 0.0f, 0.0f);
break;
}
case 169:
{
uint old = imageAtomicExchange(atomicimg, ivec2(gl_FragCoord), 0x12345678U);
Color = vec4(float(old & 0xfffff), float(imageLoad(atomicimg, ivec2(gl_FragCoord)).x & 0xfffff), 0.0f, 0.0f);
break;
}
case 170:
{
uint old = imageAtomicCompSwap(atomicimg, ivec2(gl_FragCoord), 0x55555555U, 0x12345678U);
Color = vec4(float(old & 0xfffff), float(imageLoad(atomicimg, ivec2(gl_FragCoord)).x & 0xfffff), 0.0f, 0.0f);
break;
}
case 171:
{
vec4 ret = vec4(0,0,0,0);
// test loop continues
for(int i=0; i < flatLocalCoord + 5; i++)
{
ret.x += 0.1f;
if(i == 2)
{
ret.y += 0.2f;
continue;
}
ret.z += 0.1f;
if(i == 4)
{
continue;
}
ret.w += 0.1f;
}
Color = ret;
break;
}
case 172:
{
vec4 ret = vec4(0,0,0,0);
// test loop breaks
for(int i=0; i < flatLocalCoord + 5; i++)
{
ret.x += 0.1f;
if(i == 2)
{
break;
}
ret.y += 0.2f;
}
Color = ret;
break;
}
// test fall through
case 173:
Color += vec4(0.5, 0.5, 0.5, 0.5);
case 174:
{
Color += vec4(1.0, 1.0, 1.0, 1.0);
break;
}
case 175:
{
// this isn't really intended as a true test but more a convenience for manual testing.
Color = varscope_test(flatLocalCoord, inpos, inposIncreased, scopeTest);
break;
}
case 176:
{
ivec2 coord = ivec2(zeroi + 20, zeroi + 20);
Color = texelFetch(sampledImages[cbuf.uniformIndex+1], coord, 0);
mat4 mat;
// force out of bounds matrix lookup to make sure it doesn't crash
float temp = mat[int(Color.r)+70][int(Color.g)+80];
if (int(temp/(temp+10000.0)) == 1)
{
Color.r = Color.r;
}
Color += vec4(1.0, 1.0, 1.0, 1.0);
break;
}
case 177:
{
Color = imageLoad(storeTexBuffer, 1) + imageLoad(storeTexBuffer, 4);
break;
}
case 178:
{
imageStore(storeTexBuffer, 5, vec4(3.1f, 4.1f, 5.9f, 2.6f));
Color = imageLoad(storeTexBuffer, 5);
break;
}
case 179:
{
Color = texelFetch(texBuffer1010102unorm, int(1));
break;
}
case 180:
{
Color = vec4(texelFetch(texBuffer1010102uint, int(1)));
break;
}
case 181:
{
Color = imageLoad(storeTexBuffer1010102unorm, int(1)) + imageLoad(storeTexBuffer1010102unorm, int(4));
break;
}
case 182:
{
Color = vec4(imageLoad(storeTexBuffer1010102uint, int(1))) + vec4(imageLoad(storeTexBuffer1010102uint, int(4)));
break;
}
case 183:
{
imageStore(storeTexBuffer1010102unorm, 5, vec4(200.1f/1023.0f, 400.1f/1023.0f, 800.1f/1023.0f, 1.0f));
Color = imageLoad(storeTexBuffer1010102unorm, int(1)) + imageLoad(storeTexBuffer1010102unorm, int(5));
break;
}
case 184:
{
imageStore(storeTexBuffer1010102uint, 5, uvec4(20, 40, 80, 1));
Color = vec4(imageLoad(storeTexBuffer1010102uint, int(1))) + vec4(imageLoad(storeTexBuffer1010102uint, int(5)));
break;
}
case 185:
{
// this is intended to test triggering a mixture of GPU math and GPU sample ops
vec2 coord = vec2(zerof + 0.5, zerof + 0.15);
if (localCoord.x % 2 == 0)
{
Color = textureLod(sampler2D(sampledImage, pointSampler), coord, 0.0);
for (int i = 0; i < 100; i++)
{
Color += textureLod(sampler2D(sampledImage, pointSampler), coord, float(i));
}
}
else
{
Color = vec4(pow(posone*2.5f, posone*1.3f), pow(posone*2.5f, posone*0.45f),
pow(vec2(posone*2.5f, posone*1.3f), vec2(posone*0.9f, posone*8.5f)));
for (int i = 0; i < 100; i++)
{
vec4 value = vec4(pow(posone*2.5f+float(i), posone*1.3f), pow(posone*2.5f, posone*0.45f),
pow(vec2(posone*2.5f, posone*1.3f), vec2(posone*0.9f, posone*8.5f)));
Color += value / 100.0;
}
}
break;
}
case 186:
{
float x = textureProj(sampler2DShadow(depthImage, shadowSampler), vec4(inpos, 0.1f, 0.5f));
float y = textureProj(sampler2DShadow(depthImage, shadowSampler), vec4(inpos, 0.3f, 0.5f));
float z = textureProj(sampler2DShadow(depthImage, shadowSampler), vec4(inpos, 0.7f, 0.5f));
float w = textureProj(sampler2DShadow(depthImage, shadowSampler), vec4(inpos, 0.9f, 0.5f));
Color = vec4(x, y, z, w);
break;
}
case 187:
{
uint a = zerou + 0x44b82a80;
int b = zeroi + 0x44b82a80;
Color = vec4(float(bitfieldExtract(a, 0, 32)), float(bitfieldExtract(b, 0, 32)),
float(bitfieldExtract(a, 32, 0)), float(bitfieldExtract(b, 32, 0)));
break;
}
default: break;
}
}
)EOSHADER";
std::string vertex2 = R"EOSHADER(
#version 460 core
layout(location = 0) in vec4 pos;
layout(location = 1) in float zero;
layout(location = 2) in float one;
layout(location = 3) in float negone;
layout(location = 4) in vec2 texcoord;
layout(location = 0, component = 0) flat out uint test;
layout(location = 0, component = 1) flat out int zeroi;
layout(location = 0, component = 2) flat out uint intval;
layout(location = 1, component = 1) out vec3 uv;
struct nested
{
float c; // location 4
vec2 d; // location 5
};
struct iostruct
{
float a; // location 2
float b; // location 3
nested n;
};
layout(location = 2) out iostruct str;
layout(location = 6) out mat3 matrix;
layout(location = 9) out vec3 arr[3];
void main()
{
test = gl_InstanceIndex;
gl_Position = vec4(pos.x + pos.z * float(test % 256), pos.y + pos.w * float(test / 256), 0.0, 1.0);
zeroi = 0;
intval = test + 7u;
uv = vec3(texcoord.xy, pos.x);
vec4 test = vec4(uv.x + 1.0f, uv.y + 2.0f, uv.x + 3.0f, uv.y + 4.0f);
str.a = test.x;
str.b = test.y;
str.n.c = test.z;
str.n.d = vec2(test.w, 3.141592f);
test *= 1.5f;
matrix = mat3((test * 2.0f).xyz, (test * 3.0f).xyz, (test * 4.0f).xyz);
arr[0] = (test * 5.0f).yzw;
arr[1] = (test * 6.0f).yzw;
arr[2] = (test * 7.0f).yzw;
}
)EOSHADER";
std::string pixel_glsl2 = pixel_glsl_header + R"EOSHADER(
layout(location = 0, component = 0) flat in uint test;
layout(location = 0, component = 1) flat in int zeroi;
layout(location = 0, component = 2) flat in uint intval;
layout(location = 1, component = 1) in vec3 uv;
struct nested
{
float c; // location 4
vec2 d; // location 5
};
struct iostruct
{
float a; // location 2
float b; // location 3
nested n;
};
layout(location = 2) in iostruct str;
layout(location = 6) in mat3 matrix;
layout(location = 9) in vec3 arr[3];
layout(location = 0) out vec4 Color;
void main()
{
float zerof = float(zeroi);
Color = vec4(0,0,0,0);
switch(test)
{
case 0:
{
// test loading from the storage buffer (after a nice big barrier)
Color = storebuf.x;
break;
}
case 1:
{
// test loading from the storage buffer (after a nice big barrier)
Color = vec4(storebuf.y.val);
break;
}
case 2:
{
// test loading from the storage buffer (after a nice big barrier)
Color = storebuf.arr[intval - test];
break;
}
case 3:
{
Color = imageLoad(storeImage, ivec2(zeroi+1,zeroi+3));
break;
}
case 4:
{
Color = vec4(test, zeroi, intval, 1.0f);
break;
}
case 5:
{
Color = vec4(uv.xyz, 1.0f);
break;
}
case 6:
{
Color = vec4(str.a, str.b, str.n.c, length(str.n.d));
break;
}
case 7:
{
Color = matrix[0].xyzx;
break;
}
case 8:
{
Color = matrix[1].xyzx;
break;
}
case 9:
{
Color = matrix[2].xyzx;
break;
}
case 10:
{
Color = arr[0].xyzx;
break;
}
case 11:
{
Color = arr[1].xyzx;
break;
}
case 12:
{
Color = arr[2].xyzx;
break;
}
case 13:
{
Color = vec4(0,0,0,0);
uint loopCount = uint(intval - test);
loopCount -= (uint(gl_FragCoord.x) % 2u);
loopCount -= (uint(gl_FragCoord.y) % 2u) * 2u;
vec2 val = uv.xy;
for(uint i=0; i < loopCount; i++)
{
val += vec2(0.01f, 0.01f);
}
Color = dFdxFine(val).xyxy;
break;
}
case 14:
{
Color = vec4(0,0,0,0);
uint loopCount = uint(intval - test);
loopCount += (uint(gl_FragCoord.x) % 2u);
loopCount += (uint(gl_FragCoord.y) % 2u) * 2u;
vec2 val = uv.xy;
for(uint i=0; i < loopCount; i++)
{
val += vec2(0.01f, 0.01f);
}
Color = dFdxFine(val).xyxy;
break;
}
#if TEST_DESC_INDEXING
case 15:
{
// test loading from the storage buffer (after a nice big barrier)
Color = storebufs[zeroi+7].x;
break;
}
case 16:
{
// test loading from the storage buffer (after a nice big barrier)
Color = vec4(storebufs[zeroi+7].y.val);
break;
}
case 17:
{
// test loading from the storage buffer (after a nice big barrier)
Color = storebufs[zeroi+7].arr[intval - test];
break;
}
case 18:
{
Color = imageLoad(storeImages[zeroi+7], ivec2(zeroi+1,zeroi+3));
break;
}
#endif
case 19:
{
Color = gl_FrontFacing ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
break;
}
case 20:
{
Color = imageLoad(storeTexBuffer, 1)+imageLoad(storeTexBuffer, 5);
break;
}
case 21:
{
Color = imageLoad(storeTexBuffer1010102unorm, int(1)) + imageLoad(storeTexBuffer1010102unorm, int(5));
}
case 22:
{
Color = vec4(imageLoad(storeTexBuffer1010102uint, int(1))) + vec4(imageLoad(storeTexBuffer1010102uint, int(5)));
}
default: break;
}
}
)EOSHADER";
std::string computeShaderDerivs = R"EOSHADER(
#version 460 core
#extension GL_NV_compute_shader_derivatives : require
#if SUBGROUP_SUPPORT
#extension GL_KHR_shader_subgroup_basic : require
#extension GL_KHR_shader_subgroup_ballot : require
#extension GL_KHR_shader_subgroup_vote : require
#extension GL_KHR_shader_subgroup_arithmetic : require
#endif // #if SUBGROUP_SUPPORT
layout(push_constant) uniform PushData
{
uint test;
} push;
struct Output
{
vec4 vals[1024];
};
layout(binding = 0, std430) buffer outbuftype {
Output data[COMP_TESTS];
} outbuf;
layout(set = 0, binding = 14) uniform sampler2D linearSampledImage;
layout(set = 0, binding = 19) uniform sampler shadowSampler;
layout(set = 0, binding = 32) uniform texture2D depthImage;
uint GetTest() { return push.test; }
#define IsTest(x) (GetTest() == x)
layout(local_size_x = GROUP_SIZE_X, local_size_y = GROUP_SIZE_Y, local_size_z = GROUP_SIZE_Z) in;
layout(QUAD_LAYOUT) in;
uvec3 tid;
uvec3 gid;
uint flatId;
#if WORKGROUP_SUPPORT
shared uvec4 gsmUint4[1024];
#endif // #if WORKGROUP_SUPPORT
void SetOutput(vec4 val)
{
outbuf.data[push.test].vals[flatId] = val;
}
void Init(vec4 val)
{
flatId = gid.z * gl_WorkGroupSize.x * gl_WorkGroupSize.y + gid.y * gl_WorkGroupSize.x + gid.x;
SetOutput(val);
}
void main()
{
// Only want the workgroup (1,0,0) to output results
if ((gl_WorkGroupID.x != 1) || (gl_WorkGroupID.y != 0) || (gl_WorkGroupID.z != 0))
return;
vec4 testResult = vec4(0);
gid = gl_LocalInvocationID;
tid = gl_GlobalInvocationID;
Init(testResult);
uint id = flatId;
uint ZERO = id / 10000;
vec2 inpos;
inpos.xy = gid.xy / 8.0;
#if WORKGROUP_SUPPORT
gsmUint4[flatId].xyz = tid;
#endif // #if WORKGROUP_SUPPORT
#if SUBGROUP_SUPPORT
id += gl_SubgroupInvocationID;
testResult.w = id * ZERO;
#endif // #if SUBGROUP_SUPPORT
if(IsTest(0))
{
vec4 test0;
test0.x = dFdx(0.5f);
test0.y = dFdy(0.5f);
test0.z = dFdxFine(0.5f);
test0.w = dFdyFine(0.5f);
testResult = test0;
}
if(IsTest(1))
{
vec3 test1 = gid;
testResult.xyz = test1;
}
if(IsTest(2))
{
vec3 test2 = tid;
testResult.xyz = test2;
}
if(IsTest(3))
{
vec3 test3 = dFdxFine(gid*gid*gid);
testResult.xyz = test3;
}
if(IsTest(4))
{
vec3 test4 = dFdyFine(gid*gid*gid);
testResult.xyz = test4;
}
if(IsTest(5))
{
vec3 test5 = dFdxCoarse(gid*gid);
testResult.xyz = test5;
}
if(IsTest(6))
{
vec3 test6 = dFdyCoarse(gid*gid);
testResult.xyz = test6;
}
if(IsTest(7))
{
// OpImageQueryLod
vec2 test7 = textureQueryLod(linearSampledImage, inpos);
testResult.xy = test7;
}
if(IsTest(8))
{
// OpImageSampleProjImplicitLod
vec4 test8 = textureProj(linearSampledImage, vec3(inpos, 0.5f));
testResult = test8;
}
if(IsTest(9))
{
// OpImageSampleImplicitLod
vec4 test9 = texture(linearSampledImage, inpos);
testResult = test9;
}
if(IsTest(10))
{
// OpImageSampleDrefImplicitLod
vec4 test10;
test10.x = texture(sampler2DShadow(depthImage, shadowSampler), vec3(inpos, 0.1f));
test10.y = texture(sampler2DShadow(depthImage, shadowSampler), vec3(inpos, 0.3f));
test10.z = texture(sampler2DShadow(depthImage, shadowSampler), vec3(inpos, 0.7f));
test10.w = texture(sampler2DShadow(depthImage, shadowSampler), vec3(inpos, 0.9f));
testResult = test10;
}
if(IsTest(11))
{
// OpImageSampleProjDrefImplicitLod
vec4 test11;
test11.x = textureProj(sampler2DShadow(depthImage, shadowSampler), vec4(inpos, 0.1f, 0.5f));
test11.y = textureProj(sampler2DShadow(depthImage, shadowSampler), vec4(inpos, 0.3f, 0.5f));
test11.z = textureProj(sampler2DShadow(depthImage, shadowSampler), vec4(inpos, 0.7f, 0.5f));
test11.w = textureProj(sampler2DShadow(depthImage, shadowSampler), vec4(inpos, 0.9f, 0.5f));
testResult = test11;
}
SetOutput(testResult);
}
)EOSHADER";
std::string capabilities = "OpCapability Shader\n";
std::string spv_extensions;
std::string extinstimport =
R"EOSHADER(
%glsl450 = OpExtInstImport "GLSL.std.450"
)EOSHADER";
std::string executionmodes =
R"EOSHADER(
OpExecutionMode %main OriginUpperLeft
)EOSHADER";
std::string spv_debug =
R"EOSHADER(
%filename = OpString "file.foo"
)EOSHADER";
std::string decorations = R"EOSHADER(
OpDecorate %flatData Flat
OpDecorate %flatData Location 1
OpDecorate %linearData Location 3
OpDecorate %Color Index 0
OpDecorate %Color Location 0
OpDecorate %gl_FragCoord BuiltIn FragCoord
OpDecorate %rtarray_float4 ArrayStride 16
OpMemberDecorate %dummy 0 Offset 0
OpMemberDecorate %dummy 1 Offset 16
OpMemberDecorate %buftype 0 Offset 0
OpMemberDecorate %buftype 1 Offset 64
OpMemberDecorate %buftype 2 Offset 128
OpMemberDecorate %buftype 3 Offset 144
OpMemberDecorate %buftype 4 Offset 176
OpMemberDecorate %buftype 0 MatrixStride 16
OpMemberDecorate %buftype 0 RowMajor
OpMemberDecorate %buftype 1 MatrixStride 16
OpMemberDecorate %buftype 1 ColMajor
OpDecorate %buftype BufferBlock
OpDecorate %buffer DescriptorSet 0
OpDecorate %buffer Binding 15
)EOSHADER";
std::string typesConstants = R"EOSHADER(
%void = OpTypeVoid
%bool = OpTypeBool
%float = OpTypeFloat 32
%uint = OpTypeInt 32 0
%int = OpTypeInt 32 1
%float2 = OpTypeVector %float 2
%float3 = OpTypeVector %float 3
%float4 = OpTypeVector %float 4
%int2 = OpTypeVector %int 2
%int3 = OpTypeVector %int 3
%int4 = OpTypeVector %int 4
%uint2 = OpTypeVector %uint 2
%uint3 = OpTypeVector %uint 3
%uint4 = OpTypeVector %uint 4
%float2x2 = OpTypeMatrix %float2 2
%float3x3 = OpTypeMatrix %float3 3
%float2x4 = OpTypeMatrix %float2 4
%float4x2 = OpTypeMatrix %float4 2
%float4x4 = OpTypeMatrix %float4 4
%mainfunc = OpTypeFunction %void
%doublerfunc = OpTypeFunction %float %float
%rtarray_float4 = OpTypeRuntimeArray %float4
%v2f = OpTypeStruct %float2 %float2 %float2 %float %float %float
%flatv2f = OpTypeStruct %uint %uint
%child = OpTypeStruct %float4 %float3 %float
%parent = OpTypeStruct %float4 %child %float4x4
%f32f32 = OpTypeStruct %float %float
%f32i32 = OpTypeStruct %float %int
%dummy = OpTypeStruct %uint4 %uint4
%buftype = OpTypeStruct %float4x4 %float4x4 %float4 %dummy %rtarray_float4
%ptr_Input_v2f = OpTypePointer Input %v2f
%ptr_Input_flatv2f = OpTypePointer Input %flatv2f
%ptr_Input_uint = OpTypePointer Input %uint
%ptr_Input_int = OpTypePointer Input %int
%ptr_Input_float = OpTypePointer Input %float
%ptr_Input_float2 = OpTypePointer Input %float2
%ptr_Input_float4 = OpTypePointer Input %float4
%ptr_Output_float4 = OpTypePointer Output %float4
%ptr_Private_int = OpTypePointer Private %int
%ptr_Private_float = OpTypePointer Private %float
%ptr_Private_float4 = OpTypePointer Private %float4
%ptr_Private_float4x4 = OpTypePointer Private %float4x4
%ptr_Function_float = OpTypePointer Function %float
%ptr_Uniform_float = OpTypePointer Uniform %float
%ptr_Uniform_float2 = OpTypePointer Uniform %float2
%ptr_Uniform_float3 = OpTypePointer Uniform %float3
%ptr_Uniform_float4 = OpTypePointer Uniform %float4
%ptr_Uniform_uint = OpTypePointer Uniform %uint
%ptr_Uniform_uint2 = OpTypePointer Uniform %uint2
%ptr_Uniform_uint3 = OpTypePointer Uniform %uint3
%ptr_Uniform_uint4 = OpTypePointer Uniform %uint4
%ptr_Uniform_int = OpTypePointer Uniform %int
%ptr_Uniform_int2 = OpTypePointer Uniform %int2
%ptr_Uniform_int3 = OpTypePointer Uniform %int3
%ptr_Uniform_int4 = OpTypePointer Uniform %int4
%ptr_Uniform_float4x4 = OpTypePointer Uniform %float4x4
%ptr_Uniform_dummy = OpTypePointer Uniform %dummy
%ptr_Uniform_buftype = OpTypePointer Uniform %buftype
%linearData = OpVariable %ptr_Input_v2f Input
%flatData = OpVariable %ptr_Input_flatv2f Input
%gl_FragCoord = OpVariable %ptr_Input_float4 Input
%Color = OpVariable %ptr_Output_float4 Output
%priv_int = OpVariable %ptr_Private_int Private
%priv_float = OpVariable %ptr_Private_float Private
%priv_float4 = OpVariable %ptr_Private_float4 Private
%priv_float4x4 = OpVariable %ptr_Private_float4x4 Private
%buffer = OpVariable %ptr_Uniform_buftype Uniform
%flatv2f_test_idx = OpConstant %int 0
%flatv2f_intval_idx = OpConstant %int 1
%v2f_zeroVal_idx = OpConstant %int 0
%v2f_inpos_idx = OpConstant %int 1
%v2f_inposIncreased_idx = OpConstant %int 2
%v2f_tinyVal_idx = OpConstant %int 3
%v2f_oneVal_idx = OpConstant %int 4
%v2f_negoneVal_idx = OpConstant %int 5
)EOSHADER";
std::string functions = R"EOSHADER(
%doubler = OpFunction %float None %doublerfunc
OpLine %filename 123 456
OpNoLine
OpLine %filename 111 222
%doubler_in = OpFunctionParameter %float
OpNoLine
OpLine %filename 99 55
OpLine %filename 199 155
%doubler_begin = OpLabel
OpLine %filename 299 255
%doubler_tmp = OpVariable %ptr_Function_float Function
OpLine %filename 399 355
%doubler_ret = OpFMul %float %float_2_0 %doubler_in
OpLine %filename 499 455
OpStore %doubler_tmp %doubler_ret
OpLine %filename 599 555
%doubler_ret2 = OpLoad %float %doubler_tmp
OpLine %filename 699 655
OpReturnValue %doubler_ret2
OpLine %filename 799 755
OpFunctionEnd
)EOSHADER";
std::vector<std::string> asm_tests;
void append_tests(const std::initializer_list<std::string> &tests)
{
asm_tests.insert(asm_tests.end(), tests.begin(), tests.end());
}
void make_asm_tests()
{
std::vector<std::string> ret;
// test binary float maths operations
for(const std::string &op : {"OpFAdd", "OpFSub", "OpFMul", "OpFDiv", "OpFMod", "OpFRem"})
{
bool div = (op == "OpFDiv" || op == "OpFMod" || op == "OpFRem");
bool mod = (op == "OpFMod" || op == "OpFRem");
for(const std::string &a : {"15_75", "4_5"})
{
for(const std::string &b : {"15_75", "4_5"})
{
// don't test A mod A
if(mod && a == b)
continue;
// test A op B and B op A, with neg/pos and dyn/const
append_tests({
fmt::format("%_x = {0} %float %float_{1} %float_{2}\n"
"%_y = {0} %float %float_neg{1} %float_{2}\n"
"%_z = {0} %float %float_{2} %float_{1}\n"
"%_w = {0} %float %float_neg{2} %float_{1}\n"
"%_out_float4 = OpCompositeConstruct %float4 %_x %_y %_z %_w\n",
op, a, b),
fmt::format("%_x = {0} %float %float_dyn_{1} %float_dyn_{2}\n"
"%_y = {0} %float %float_dyn_neg{1} %float_dyn_{2}\n"
"%_z = {0} %float %float_dyn_{2} %float_dyn_{1}\n"
"%_w = {0} %float %float_dyn_neg{2} %float_dyn_{1}\n"
"%_out_float4 = OpCompositeConstruct %float4 %_x %_y %_z %_w\n",
op, a, b),
});
if(features.shaderFloat64)
{
append_tests({
fmt::format("%_x = {0} %double %double_{1} %double_{2}\n"
"%_y = {0} %double %double_neg{1} %double_{2}\n"
"%_z = {0} %double %double_{2} %double_{1}\n"
"%_w = {0} %double %double_neg{2} %double_{1}\n"
"%_out_double4 = OpCompositeConstruct %double4 %_x %_y %_z %_w\n",
op, a, b),
fmt::format("%_x = {0} %double %double_dyn_{1} %double_dyn_{2}\n"
"%_y = {0} %double %double_dyn_neg{1} %double_dyn_{2}\n"
"%_z = {0} %double %double_dyn_{2} %double_dyn_{1}\n"
"%_w = {0} %double %double_dyn_neg{2} %double_dyn_{1}\n"
"%_out_double4 = OpCompositeConstruct %double4 %_x %_y %_z %_w\n",
op, a, b),
});
}
// also test 0 op A/B
append_tests({
fmt::format("%_x = {0} %float %float_0_0 %float_{1}\n"
"%_y = {0} %float %float_0_0 %float_{2}\n"
"%_z = {0} %float %float_0_0 %float_{3}{1}\n"
"%_w = {0} %float %float_0_0 %float_{3}{2}\n"
"%_out_float4 = OpCompositeConstruct %float4 %_x %_y %_z %_w\n",
op, a, b, mod ? "" : "neg"),
fmt::format("%_x = {0} %float %float_dyn_0_0 %float_dyn_{1}\n"
"%_y = {0} %float %float_dyn_0_0 %float_dyn_{2}\n"
"%_z = {0} %float %float_dyn_0_0 %float_dyn_{3}{1}\n"
"%_w = {0} %float %float_dyn_0_0 %float_dyn_{3}{2}\n"
"%_out_float4 = OpCompositeConstruct %float4 %_x %_y %_z %_w\n",
op, a, b, mod ? "" : "neg"),
});
// if this isn't a divide, test A/B op 0
if(!div)
{
append_tests({
fmt::format("%_x = {0} %float %float_{1} %float_0_0\n"
"%_y = {0} %float %float_neg{1} %float_0_0\n"
"%_z = {0} %float %float_{2} %float_0_0\n"
"%_w = {0} %float %float_neg{2} %float_0_0\n"
"%_out_float4 = OpCompositeConstruct %float4 %_x %_y %_z %_w\n",
op, a, b),
fmt::format("%_x = {0} %float %float_dyn_{1} %float_dyn_0_0\n"
"%_y = {0} %float %float_dyn_neg{1} %float_dyn_0_0\n"
"%_z = {0} %float %float_dyn_{2} %float_dyn_0_0\n"
"%_w = {0} %float %float_dyn_neg{2} %float_dyn_0_0\n"
"%_out_float4 = OpCompositeConstruct %float4 %_x %_y %_z %_w\n",
op, a, b),
});
}
}
}
}
// test binary int maths operations
for(const std::string &op :
{"OpIAdd", "OpISub", "OpIMul", "OpSDiv", "OpSMod", "OpSRem", "OpUDiv", "OpUMod"})
{
bool div =
(op == "OpSDiv" || op == "OpSMod" || op == "OpSRem" || op == "OpUDiv" || op == "OpUMod");
bool mod = (op == "OpSMod" || op == "OpSRem" || op == "OpUMod");
bool sign = op.find('U') == std::string::npos;
for(uint32_t a : {15, 4})
{
for(uint32_t b : {15, 4})
{
// don't test A mod A
if(mod && a == b)
continue;
// test A op B for uint and int (positive)
append_tests({
fmt::format("%_x = {0} %uint %uint_{1} %uint_{2}\n"
"%_y = {0} %uint %uint_dyn_{1} %uint_{2}\n"
"%_z = {0} %uint %uint_{2} %uint_{1}\n"
"%_w = {0} %uint %uint_dyn_{2} %uint_{1}\n"
"%_out_uint4 = OpCompositeConstruct %uint4 %_x %_y %_z %_w\n",
op, a, b),
fmt::format("%_x = {0} %uint %uint_0 %uint_{1}\n"
"%_y = {0} %uint %uint_0 %uint_dyn_{1}\n"
"%_z = {0} %uint %uint_0 %uint_{2}\n"
"%_w = {0} %uint %uint_0 %uint_dyn_{2}\n"
"%_out_uint4 = OpCompositeConstruct %uint4 %_x %_y %_z %_w\n",
op, a, b),
});
// if this is a signed op, test negative values too
if(sign && !mod)
{
append_tests({
fmt::format("%_x = {0} %int %int_{1} %int_{2}\n"
"%_y = {0} %int %int_dyn_{1} %int_{2}\n"
"%_z = {0} %int %int_{2} %int_{1}\n"
"%_w = {0} %int %int_dyn_{2} %int_{1}\n"
"%_out_int4 = OpCompositeConstruct %int4 %_x %_y %_z %_w\n",
op, a, b),
fmt::format("%_x = {0} %int %int_0 %int_{1}\n"
"%_y = {0} %int %int_0 %int_dyn_{1}\n"
"%_z = {0} %int %int_0 %int_{2}\n"
"%_w = {0} %int %int_0 %int_dyn_{2}\n"
"%_out_int4 = OpCompositeConstruct %int4 %_x %_y %_z %_w\n",
op, a, b),
fmt::format("%_x = {0} %int %int_neg{1} %int_{2}\n"
"%_y = {0} %int %int_dyn_neg{1} %int_{2}\n"
"%_z = {0} %int %int_neg{2} %int_{1}\n"
"%_w = {0} %int %int_dyn_neg{2} %int_{1}\n"
"%_out_int4 = OpCompositeConstruct %int4 %_x %_y %_z %_w\n",
op, a, b),
fmt::format("%_x = {0} %int %int_0 %int_neg{1}\n"
"%_y = {0} %int %int_0 %int_dyn_neg{1}\n"
"%_z = {0} %int %int_0 %int_neg{2}\n"
"%_w = {0} %int %int_0 %int_dyn_neg{2}\n"
"%_out_int4 = OpCompositeConstruct %int4 %_x %_y %_z %_w\n",
op, a, b),
});
}
// if it's not a divide op, test A/B op 0
if(!div)
{
append_tests({
fmt::format("%_x = {0} %uint %uint_{1} %uint_0\n"
"%_y = {0} %uint %uint_{2} %uint_0\n"
"%_z = {0} %uint %uint_dyn_{1} %uint_dyn_0\n"
"%_w = {0} %uint %uint_dyn_{2} %uint_dyn_0\n"
"%_out_uint4 = OpCompositeConstruct %uint4 %_x %_y %_z %_w\n",
op, a, b),
});
// and if it's a signed non-divide op, test -A / -B op 0
if(sign)
{
append_tests({
fmt::format("%_x = {0} %int %int_neg{1} %int_0\n"
"%_y = {0} %int %int_neg{2} %int_0\n"
"%_z = {0} %int %int_dyn_neg{1} %int_dyn_0\n"
"%_w = {0} %int %int_dyn_neg{2} %int_dyn_0\n"
"%_out_int4 = OpCompositeConstruct %int4 %_x %_y %_z %_w\n",
op, a, b),
});
}
}
}
}
}
// test unary operations
append_tests({
"%_x = OpFNegate %float %float_10_0\n"
"%_y = OpFNegate %float %float_neg10_0\n"
"%_z = OpFNegate %float %float_dyn_10_0\n"
"%_w = OpFNegate %float %float_dyn_neg10_0\n"
"%_out_float4 = OpCompositeConstruct %float4 %_x %_y %_z %_w\n",
"%_x = OpFNegate %float %float_0_0\n"
"%_y = OpFNegate %float %float_neg0_0\n"
"%_z = OpFNegate %float %float_dyn_0_0\n"
"%_w = OpFNegate %float %float_dyn_neg0_0\n"
"%_out_float4 = OpCompositeConstruct %float4 %_x %_y %_z %_w\n",
"%_x = OpSNegate %int %int_10\n"
"%_y = OpSNegate %int %int_neg10\n"
"%_z = OpSNegate %int %int_dyn_10\n"
"%_w = OpSNegate %int %int_dyn_neg10\n"
"%_out_int4 = OpCompositeConstruct %int4 %_x %_y %_z %_w\n",
"%_x = OpSNegate %int %int_0\n"
"%_y = OpSNegate %int %int_neg0\n"
"%_z = OpSNegate %int %int_dyn_0\n"
"%_w = OpSNegate %int %int_dyn_neg0\n"
"%_out_int4 = OpCompositeConstruct %int4 %_x %_y %_z %_w\n",
});
// test bitwise operations
append_tests({
"%_x = OpBitwiseOr %uint %uint_0x1234 %uint_0xb9c5\n"
"%_y = OpBitwiseXor %uint %uint_0x1234 %uint_0xb9c5\n"
"%_z = OpBitwiseAnd %uint %uint_0x1234 %uint_0xb9c5\n"
"%_w = OpNot %uint %uint_0x1234 \n"
"%_out_uint4 = OpCompositeConstruct %uint4 %_x %_y %_z %_w\n",
"%_x = OpBitwiseOr %uint %uint_dyn_0x1234 %uint_dyn_0xb9c5\n"
"%_y = OpBitwiseXor %uint %uint_dyn_0x1234 %uint_dyn_0xb9c5\n"
"%_z = OpBitwiseAnd %uint %uint_dyn_0x1234 %uint_dyn_0xb9c5\n"
"%_w = OpNot %uint %uint_dyn_0xb9c5\n"
"%_out_uint4 = OpCompositeConstruct %uint4 %_x %_y %_z %_w\n",
"%_x = OpBitwiseOr %uint %uint_dyn_0x1234 %uint_0\n"
"%_y = OpBitwiseXor %uint %uint_dyn_0x1234 %uint_0\n"
"%_z = OpBitwiseAnd %uint %uint_dyn_0x1234 %uint_0\n"
"%_w = OpNot %uint %uint_0\n"
"%_out_uint4 = OpCompositeConstruct %uint4 %_x %_y %_z %_w\n",
"%_x = OpBitwiseOr %uint %uint_0 %uint_dyn_0xb9c5\n"
"%_y = OpBitwiseXor %uint %uint_0 %uint_dyn_0xb9c5\n"
"%_z = OpBitwiseAnd %uint %uint_0 %uint_dyn_0xb9c5\n"
"%_w = OpNot %uint %uint_dyn_0xb9c5\n"
"%_out_uint4 = OpCompositeConstruct %uint4 %_x %_y %_z %_w\n",
});
// test shifts
for(const std::string &op :
{"OpShiftLeftLogical", "OpShiftRightLogical", "OpShiftRightArithmetic"})
{
for(const std::string &dyn : {"", "_dyn"})
{
for(const std::string &intType : {"int", "uint"})
{
append_tests({
fmt::format("%_x = {0} %{1} %{1}{2}_0x1234 %uint_0\n"
"%_y = {0} %{1} %{1}{2}_0x1234 %uint_1\n"
"%_z = {0} %{1} %{1}{2}_0x1234 %uint_2\n"
"%_out_{1}3 = OpCompositeConstruct %{1}3 %_x %_y %_z\n",
op, intType, dyn),
fmt::format("%_x = {0} %{1} %{1}_0x1234 %uint{2}_0\n"
"%_y = {0} %{1} %{1}_0x1234 %uint{2}_1\n"
"%_z = {0} %{1} %{1}_0x1234 %uint{2}_2\n"
"%_out_{1}3 = OpCompositeConstruct %{1}3 %_x %_y %_z\n",
op, intType, dyn),
fmt::format("%_x = {0} %{1} %{1}{2}_0x1234 %uint{2}_0\n"
"%_y = {0} %{1} %{1}{2}_0x1234 %uint{2}_1\n"
"%_z = {0} %{1} %{1}{2}_0x1234 %uint{2}_2\n"
"%_out_{1}3 = OpCompositeConstruct %{1}3 %_x %_y %_z\n",
op, intType, dyn),
});
}
}
}
// test square 2x2 matrix multiplies
append_tests({
R"EOTEST(
%_cola = OpCompositeConstruct %float2 %randf_0 %randf_1
%_colb = OpCompositeConstruct %float2 %randf_2 %randf_3
%_mat = OpCompositeConstruct %float2x2 %_cola %_colb
%_vec = OpCompositeConstruct %float2 %randf_4 %randf_5
%_out_float2 = OpMatrixTimesVector %float2 %_mat %_vec
)EOTEST",
R"EOTEST(
%_cola = OpCompositeConstruct %float2 %randf_0 %randf_1
%_colb = OpCompositeConstruct %float2 %randf_2 %randf_3
%_mat = OpCompositeConstruct %float2x2 %_cola %_colb
%_vec = OpCompositeConstruct %float2 %randf_4 %randf_5
%_out_float2 = OpVectorTimesMatrix %float2 %_vec %_mat
)EOTEST",
R"EOTEST(
%_cola = OpCompositeConstruct %float2 %randf_0 %randf_1
%_colb = OpCompositeConstruct %float2 %randf_2 %randf_3
%_mat1 = OpCompositeConstruct %float2x2 %_cola %_colb
%_vec = OpCompositeConstruct %float2 %randf_4 %randf_5
%_mat2 = OpMatrixTimesScalar %float2x2 %_mat1 %randf_6
%_out_float2 = OpVectorTimesMatrix %float2 %_vec %_mat2
)EOTEST",
R"EOTEST(
%_cola = OpCompositeConstruct %float2 %randf_0 %randf_1
%_colb = OpCompositeConstruct %float2 %randf_2 %randf_3
%_mat1 = OpCompositeConstruct %float2x2 %_cola %_colb
%_vec = OpCompositeConstruct %float2 %randf_4 %randf_5
%_colc = OpCompositeConstruct %float2 %randf_6 %randf_7
%_cold = OpCompositeConstruct %float2 %randf_8 %randf_9
%_mat2 = OpCompositeConstruct %float2x2 %_colc %_cold
%_mat3 = OpMatrixTimesMatrix %float2x2 %_mat1 %_mat2
%_out_float2 = OpVectorTimesMatrix %float2 %_vec %_mat3
)EOTEST",
R"EOTEST(
%_cola = OpCompositeConstruct %float2 %randf_0 %randf_1
%_colb = OpCompositeConstruct %float2 %randf_2 %randf_3
%_mat1 = OpCompositeConstruct %float2x2 %_cola %_colb
%_vec = OpCompositeConstruct %float2 %randf_4 %randf_5
%_colc = OpCompositeConstruct %float2 %randf_6 %randf_7
%_cold = OpCompositeConstruct %float2 %randf_8 %randf_9
%_mat2 = OpCompositeConstruct %float2x2 %_colc %_cold
%_mat3 = OpMatrixTimesMatrix %float2x2 %_mat2 %_mat1
%_out_float2 = OpVectorTimesMatrix %float2 %_vec %_mat3
)EOTEST",
});
// test rectangular 2x4 / 4x2 matrix multiplies
append_tests({
R"EOTEST(
%_cola = OpCompositeConstruct %float4 %randf_0 %randf_1 %randf_2 %randf_3
%_colb = OpCompositeConstruct %float4 %randf_4 %randf_5 %randf_6 %randf_7
%_mat = OpCompositeConstruct %float4x2 %_cola %_colb
%_vec = OpCompositeConstruct %float4 %randf_16 %randf_17 %randf_18 %randf_19
%_out_float2 = OpVectorTimesMatrix %float2 %_vec %_mat
)EOTEST",
R"EOTEST(
%_colc = OpCompositeConstruct %float2 %randf_8 %randf_9
%_cold = OpCompositeConstruct %float2 %randf_10 %randf_11
%_cole = OpCompositeConstruct %float2 %randf_12 %randf_13
%_colf = OpCompositeConstruct %float2 %randf_14 %randf_15
%_mat = OpCompositeConstruct %float2x4 %_colc %_cold %_cole %_colf
%_vec = OpCompositeConstruct %float4 %randf_16 %randf_17 %randf_18 %randf_19
%_out_float2 = OpMatrixTimesVector %float2 %_mat %_vec
)EOTEST",
R"EOTEST(
%_cola = OpCompositeConstruct %float4 %randf_0 %randf_1 %randf_2 %randf_3
%_colb = OpCompositeConstruct %float4 %randf_4 %randf_5 %randf_6 %randf_7
%_mat = OpCompositeConstruct %float4x2 %_cola %_colb
%_vec = OpCompositeConstruct %float2 %randf_16 %randf_17
%_out_float4 = OpMatrixTimesVector %float4 %_mat %_vec
)EOTEST",
R"EOTEST(
%_colc = OpCompositeConstruct %float2 %randf_8 %randf_9
%_cold = OpCompositeConstruct %float2 %randf_10 %randf_11
%_cole = OpCompositeConstruct %float2 %randf_12 %randf_13
%_colf = OpCompositeConstruct %float2 %randf_14 %randf_15
%_mat = OpCompositeConstruct %float2x4 %_colc %_cold %_cole %_colf
%_vec = OpCompositeConstruct %float2 %randf_16 %randf_17
%_out_float4 = OpVectorTimesMatrix %float4 %_vec %_mat
)EOTEST",
R"EOTEST(
%_cola = OpCompositeConstruct %float4 %randf_0 %randf_1 %randf_2 %randf_3
%_colb = OpCompositeConstruct %float4 %randf_4 %randf_5 %randf_6 %randf_7
%_mat1 = OpCompositeConstruct %float4x2 %_cola %_colb
%_colc = OpCompositeConstruct %float2 %randf_8 %randf_9
%_cold = OpCompositeConstruct %float2 %randf_10 %randf_11
%_cole = OpCompositeConstruct %float2 %randf_12 %randf_13
%_colf = OpCompositeConstruct %float2 %randf_14 %randf_15
%_mat2 = OpCompositeConstruct %float2x4 %_colc %_cold %_cole %_colf
%_mat = OpMatrixTimesMatrix %float4x4 %_mat1 %_mat2
%_vec = OpCompositeConstruct %float4 %randf_16 %randf_17 %randf_18 %randf_19
%_out_float4 = OpMatrixTimesVector %float4 %_mat %_vec
)EOTEST",
R"EOTEST(
%_cola = OpCompositeConstruct %float4 %randf_0 %randf_1 %randf_2 %randf_3
%_colb = OpCompositeConstruct %float4 %randf_4 %randf_5 %randf_6 %randf_7
%_mat1 = OpCompositeConstruct %float4x2 %_cola %_colb
%_colc = OpCompositeConstruct %float4 %randf_8 %randf_9 %randf_10 %randf_11
%_cold = OpCompositeConstruct %float4 %randf_12 %randf_13 %randf_14 %randf_15
%_mat2 = OpCompositeConstruct %float4x2 %_colc %_cold
%_mat2t = OpTranspose %float2x4 %_mat2
%_mat = OpMatrixTimesMatrix %float4x4 %_mat1 %_mat2t
%_vec = OpCompositeConstruct %float4 %randf_16 %randf_17 %randf_18 %randf_19
%_out_float4 = OpMatrixTimesVector %float4 %_mat %_vec
)EOTEST",
R"EOTEST(
%_cola = OpCompositeConstruct %float4 %randf_0 %randf_1 %randf_2 %randf_3
%_colb = OpCompositeConstruct %float4 %randf_4 %randf_5 %randf_6 %randf_7
%_mat = OpOuterProduct %float4x4 %_cola %_colb
%_vec = OpCompositeConstruct %float4 %randf_16 %randf_17 %randf_18 %randf_19
%_out_float4 = OpMatrixTimesVector %float4 %_mat %_vec
)EOTEST",
R"EOTEST(
%_vec = OpCompositeConstruct %float4 %randf_0 %randf_1 %randf_2 %randf_3
%_out_float4 = OpVectorTimesScalar %float4 %_vec %randf_4
)EOTEST",
R"EOTEST(
%_cola = OpCompositeConstruct %float2 %randf_0 %randf_1
%_colb = OpCompositeConstruct %float2 %randf_4 %randf_5
%_colc = OpCompositeConstruct %float2 %randf_8 %randf_9
%_cold = OpCompositeConstruct %float2 %randf_12 %randf_13
%_mat1 = OpCompositeConstruct %float2x2 %_cola %_colb
%_out_float = OpExtInst %float %glsl450 Determinant %_mat1
)EOTEST",
R"EOTEST(
%_cola = OpCompositeConstruct %float3 %randf_0 %randf_1 %randf_2
%_colb = OpCompositeConstruct %float3 %randf_4 %randf_5 %randf_6
%_colc = OpCompositeConstruct %float3 %randf_8 %randf_9 %randf_10
%_mat1 = OpCompositeConstruct %float3x3 %_cola %_colb %_colc
%_out_float = OpExtInst %float %glsl450 Determinant %_mat1
)EOTEST",
R"EOTEST(
%_cola = OpCompositeConstruct %float4 %randf_0 %randf_1 %randf_2 %randf_3
%_colb = OpCompositeConstruct %float4 %randf_4 %randf_5 %randf_6 %randf_7
%_colc = OpCompositeConstruct %float4 %randf_8 %randf_9 %randf_10 %randf_11
%_cold = OpCompositeConstruct %float4 %randf_12 %randf_13 %randf_14 %randf_15
%_mat1 = OpCompositeConstruct %float4x4 %_cola %_colb %_colc %_cold
%_out_float = OpExtInst %float %glsl450 Determinant %_mat1
)EOTEST",
});
// test matrix inverse, but round the result to avoid needing to lower our global precision
// epsilon
for(int dim = 2; dim <= 4; dim++)
{
std::string test = fmt::format(R"EOTEST(
%_cola = OpCompositeConstruct %float{0} %randf_0 %randf_1 {1} %randf_2 {2} %randf_3
%_colb = OpCompositeConstruct %float{0} %randf_4 %randf_5 {1} %randf_6 {2} %randf_7
%_colc = OpCompositeConstruct %float{0} %randf_8 %randf_9 {1} %randf_10 {2} %randf_11
%_cold = OpCompositeConstruct %float{0} %randf_12 %randf_13 {1} %randf_14 {2} %randf_15
%_mat = OpCompositeConstruct %float{0}x{0} %_cola %_colb {1} %_colc {2} %_cold
%_vec = OpCompositeConstruct %float{0} %randf_16 %randf_17 {1} %randf_18 {2} %randf_19
%_mat0 = OpExtInst %float{0}x{0} %glsl450 MatrixInverse %_mat
)EOTEST",
dim, dim < 3 ? ";" : "", dim < 4 ? ";" : "");
int i = 0;
for(int col = 0; col < dim; col++)
{
for(int row = 0; row < dim; row++)
{
test += fmt::format(R"EOTEST(
%_mat{0}{1}a = OpCompositeExtract %float %_mat{2} {0} {1}
%_mat{0}{1}b = OpFMul %float %_mat{0}{1}a %float_500_0
%_mat{0}{1}c = OpExtInst %float %glsl450 RoundEven %_mat{0}{1}b
%_mat{0}{1}d = OpFDiv %float %_mat{0}{1}c %float_500_0
%_mat{3} = OpCompositeInsert %float{4}x{4} %_mat{0}{1}d %_mat{2} {0} {1}
)EOTEST",
col, row, i, i + 1, dim);
i++;
}
}
test += fmt::format("%_out_float{0} = OpMatrixTimesVector %float{0} %_mat{1} %_vec\n", dim, i);
asm_tests.push_back(test);
}
// test OpVectorShuffle
append_tests({
"%_out_float4 = OpVectorShuffle %float4 %float4_0000 %float4_1234 7 6 0 1",
"%_out_float4 = OpVectorShuffle %float4 %float4_0000 %float4_dyn_1234 7 6 0 1",
"%_out_float4 = OpVectorShuffle %float4 %float4_dyn_0000 %float4_1234 7 6 0 1",
"%_out_float4 = OpVectorShuffle %float4 %float4_dyn_0000 %float4_dyn_1234 7 6 0 1",
"%_out_float3 = OpVectorShuffle %float3 %float3_000 %float3_123 3 4 5",
"%_out_float2 = OpVectorShuffle %float2 %float2_00 %float2_12 2 3",
// test 0xffffffff component inputs
"%_tmp = OpVectorShuffle %float4 %float4_0000 %float4_1234 5 4 4294967295 4294967295\n"
"%_out_float4 = OpVectorShuffle %float4 %_tmp %float4_dyn_1234 0 1 4 5",
});
// test OpVectorExtractDynamic
append_tests({
"%_x = OpVectorExtractDynamic %float %float4_dyn_1234 %uint_dyn_1\n"
"%_y = OpVectorExtractDynamic %float %float4_dyn_1234 %uint_dyn_3\n"
"%_z = OpVectorExtractDynamic %float %float4_dyn_1234 %uint_dyn_2\n"
"%_w = OpVectorExtractDynamic %float %float4_dyn_0000 %uint_dyn_2\n"
"%_out_float4 = OpCompositeConstruct %float4 %_x %_y %_z %_w\n",
});
// test OpVectorInsertDynamic
append_tests({
"%_out_float4 = OpVectorInsertDynamic %float4 %float4_dyn_1234 %float_dyn_8_8 %uint_dyn_1",
"%_out_float4 = OpVectorInsertDynamic %float4 %float4_dyn_1234 %float_dyn_8_8 %uint_dyn_2",
"%_out_float4 = OpVectorInsertDynamic %float4 %float4_dyn_1234 %float_dyn_8_8 %uint_dyn_0",
});
// test OpCompositeInsert on vectors
append_tests({
" %_b = OpCompositeInsert %float4 %float_15_0 %float4_0000 2\n"
" %_c = OpCompositeInsert %float4 %float_8_8 %_b 1\n"
" %_d = OpCompositeInsert %float4 %float_6_1 %_c 3\n"
"%_out_float4 = OpCompositeInsert %float4 %float_2_222 %_d 0\n",
" %_b = OpCompositeInsert %float4 %float_dyn_15_0 %float4_dyn_0000 2\n"
" %_c = OpCompositeInsert %float4 %float_dyn_8_8 %_b 1\n"
" %_d = OpCompositeInsert %float4 %float_dyn_6_1 %_c 3\n"
"%_out_float4 = OpCompositeInsert %float4 %float_dyn_2_222 %_d 0\n",
});
// test OpCompositeExtract on vectors
append_tests({
"%_out_float = OpCompositeExtract %float %float4_dyn_1234 0",
"%_out_float = OpCompositeExtract %float %float4_dyn_1234 1",
"%_out_float = OpCompositeExtract %float %float4_dyn_1234 3",
});
// test OpCompositeInsert on structs
asm_tests.push_back(R"EOTEST(
%_a = OpCompositeConstruct %float4 %float_dyn_4_2 %float_dyn_1_0 %float_dyn_9_5 %float_dyn_0_01
%_b = OpCompositeConstruct %float3 %float_dyn_3_5 %float_dyn_5_3 %float_dyn_6_2
%_c = OpVectorShuffle %float4 %_a %_a 3 2 0 1
%_d = OpVectorShuffle %float4 %_a %_a 0 1 3 2
%_e = OpVectorShuffle %float4 %_a %_a 2 0 1 3
%_f = OpVectorShuffle %float4 %_a %_a 3 1 2 0
%_g = OpVectorShuffle %float4 %_a %_a 1 3 0 2
%_parent1 = OpCompositeInsert %parent %_a %null_parent 0
%_parent2 = OpCompositeInsert %parent %_a %_parent1 1 0
%_parent3 = OpCompositeInsert %parent %_b %_parent2 1 1
%_parent4 = OpCompositeInsert %parent %float_dyn_9_9 %_parent3 1 2
%_parent5 = OpCompositeInsert %parent %_c %_parent4 2 0
%_parent6 = OpCompositeInsert %parent %_d %_parent5 2 1
%_parent7 = OpCompositeInsert %parent %_e %_parent6 2 2
%_parent8 = OpCompositeInsert %parent %_g %_parent7 2 3
%_x = OpCompositeExtract %float %_parent8 0 2
%_y = OpCompositeExtract %float %_parent8 2 1 3
%_z = OpCompositeExtract %float %_parent8 1 1 1
%_w = OpCompositeExtract %float %_parent8 1 0 2
%_out_float4 = OpCompositeConstruct %float4 %_x %_y %_z %_w
)EOTEST");
// test OpBitCast
append_tests({
"%_a = OpBitcast %uint %float_dyn_15_0\n"
"%_neg = OpBitwiseOr %uint %_a %uint_dyn_0x80000000\n"
"%_out_float = OpBitcast %float %_neg\n",
"%_result = OpBitwiseOr %uint %uint_dyn_0x4200004d %uint_dyn_0xa28b00\n"
"%_out_float = OpBitcast %float %_result\n",
});
// Bitcast vector <-> scalar
if(float16Int8Features.shaderInt8 && features.shaderInt16)
{
append_tests({
// u8[2] -> u16
"%_result = OpCompositeConstruct %u8v2 %u8_8 %u8_9\n"
"%_out_u16 = OpBitcast %u16 %_result\n",
// u8[4] -> u32
"%_result = OpCompositeConstruct %u8v4 %u8_4 %u8_5 %u8_6 %u8_7\n"
"%_out_uint = OpBitcast %uint %_result\n",
// u16[2] -> u32
"%_result = OpCompositeConstruct %u16v2 %u16_4 %u16_5\n"
"%_out_uint = OpBitcast %uint %_result\n",
// u16 -> u8[2]
"%_out_u8v2 = OpBitcast %u8v2 %u16_1234\n ",
// u32 -> u8[4]
"%_out_u8v4 = OpBitcast %u8v4 %uint_1234\n ",
// u32 -> u16[2]
"%_out_u16v2 = OpBitcast %u16v2 %uint_12345\n",
});
}
if(features.shaderInt16 && features.shaderInt64)
{
append_tests({
// u16[4] -> u64
"%_result = OpCompositeConstruct %u16v4 %u16_0 %u16_1 %u16_2 %u16_3\n"
"%_out_u64 = OpBitcast %u64 %_result\n",
// u64 -> u16[4]
"%_out_u16v4 = OpBitcast %u16v4 %u64_1234\n",
});
}
if(features.shaderInt64)
{
append_tests({
// u32[2] -> u64
"%_result = OpCompositeConstruct %uint2 %uint_0 %uint_1\n"
"%_out_u64 = OpBitcast %u64 %_result\n",
// u64 -> u32[2]
"%_out_uint2 = OpBitcast %uint2 %u64_1234\n",
});
}
if(float16Int8Features.shaderFloat16)
{
append_tests({
// f16[2] -> f32
"%_result = OpCompositeConstruct %half2 %half_0_25 %half_0_5\n"
"%_out_float = OpBitcast %float %_result\n",
// f32 -> f16[2]
"%_out_half2 = OpBitcast %half2 %float_1_1125\n",
});
}
if(features.shaderFloat64)
{
append_tests({
// f32[2] -> f64
"%_result = OpCompositeConstruct %float2 %float_0_5 %float_0_25\n"
"%_out_double = OpBitcast %double %_result\n",
// f64 -> f32[2]
"%_out_float2 = OpBitcast %float2 %double_1024_25\n",
});
}
// test ExtInst NMin/NMax/NClamp
append_tests({
"%_x = OpExtInst %float %glsl450 NMin %nan %oneVal\n"
"%_y = OpExtInst %float %glsl450 NMin %oneVal %nan\n"
"%_z = OpExtInst %float %glsl450 NMin %nan %nan\n"
"%_w = OpExtInst %float %glsl450 NMin %nan %neginf\n"
"%_out_float4 = OpCompositeConstruct %float4 %_x %_y %_z %_w\n",
"%_x = OpExtInst %float %glsl450 NMax %nan %oneVal\n"
"%_y = OpExtInst %float %glsl450 NMax %oneVal %nan\n"
"%_z = OpExtInst %float %glsl450 NMax %nan %nan\n"
"%_w = OpExtInst %float %glsl450 NMax %nan %neginf\n"
"%_out_float4 = OpCompositeConstruct %float4 %_x %_y %_z %_w\n",
"%_out_float = OpExtInst %float %glsl450 NClamp %nan %zerof %oneVal",
});
// test ExtInst Modf/ModfStruct and Frexp/FrexpStruct
append_tests({
"%_x = OpExtInst %float %glsl450 Modf %float_dyn_123_456 %priv_float\n"
"%_y = OpLoad %float %priv_float\n"
"%_tmp = OpExtInst %f32f32 %glsl450 ModfStruct %float_dyn_789_012\n"
"%_z = OpCompositeExtract %float %_tmp 0\n"
"%_w = OpCompositeExtract %float %_tmp 1\n"
"%_out_float4 = OpCompositeConstruct %float4 %_x %_y %_z %_w\n",
"%_x = OpExtInst %float %glsl450 Frexp %float_dyn_123_456 %priv_int\n"
"%_yi = OpLoad %int %priv_int\n"
"%_y = OpConvertSToF %float %_yi\n"
"%_tmp = OpExtInst %f32i32 %glsl450 FrexpStruct %float_dyn_789_012\n"
"%_z = OpCompositeExtract %float %_tmp 0\n"
"%_wi = OpCompositeExtract %int %_tmp 1\n"
"%_w = OpConvertSToF %float %_wi\n"
"%_out_float4 = OpCompositeConstruct %float4 %_x %_y %_z %_w\n",
});
// test float <-> int conversions
append_tests({
"%_x = OpConvertUToF %float %uint_dyn_1234\n"
"%_y = OpConvertSToF %float %int_dyn_1234\n"
"%_z = OpConvertSToF %float %int_dyn_neg1234\n"
"%_w = OpConvertUToF %float %uint_dyn_0\n"
"%_out_float4 = OpCompositeConstruct %float4 %_x %_y %_z %_w\n",
"%_x = OpConvertFToU %uint %float_dyn_1_0\n"
"%_y = OpConvertFToU %uint %float_dyn_0_0\n"
"%_z = OpConvertFToU %uint %float_dyn_1_1\n"
"%_w = OpConvertFToU %uint %float_dyn_1_3\n"
"%_out_uint4 = OpCompositeConstruct %uint4 %_x %_y %_z %_w\n",
"%_x = OpConvertFToU %uint %float_dyn_1_0\n"
"%_y = OpConvertFToU %uint %float_dyn_1_5\n"
"%_z = OpConvertFToU %uint %float_dyn_0_5\n"
"%_w = OpConvertFToU %uint %float_dyn_1_7\n"
"%_out_uint4 = OpCompositeConstruct %uint4 %_x %_y %_z %_w\n",
"%_x = OpConvertFToS %int %float_dyn_1_0\n"
"%_y = OpConvertFToS %int %float_dyn_0_0\n"
"%_z = OpConvertFToS %int %float_dyn_neg1_0\n"
"%_w = OpConvertFToS %int %float_dyn_1_3\n"
"%_out_int4 = OpCompositeConstruct %int4 %_x %_y %_z %_w\n",
"%_x = OpConvertFToS %int %float_dyn_1_0\n"
"%_y = OpConvertFToS %int %float_dyn_1_5\n"
"%_z = OpConvertFToS %int %float_dyn_0_5\n"
"%_w = OpConvertFToS %int %float_dyn_neg1_5\n"
"%_out_int4 = OpCompositeConstruct %int4 %_x %_y %_z %_w\n",
});
// test copies
append_tests({
"OpCopyMemory %Color %gl_FragCoord\n"
"; no_out\n",
"%_src = OpAccessChain %ptr_Uniform_float4 %buffer %uint_2\n"
"%_dst = OpAccessChain %ptr_Uniform_float4 %buffer %uint_4 %uint_3\n"
"OpCopyMemory %_dst %_src\n"
"OpCopyMemory %Color %_src\n"
"; no_out\n",
"%frag = OpLoad %float4 %gl_FragCoord\n"
"%_out_float4 = OpCopyObject %float4 %frag\n",
});
// test SSBO pointers
append_tests({
"%_y = OpAccessChain %ptr_Uniform_dummy %buffer %uint_3\n"
"%_src = OpAccessChain %ptr_Uniform_uint4 %_y %uint_0\n"
"%_dst = OpAccessChain %ptr_Uniform_uint4 %_y %uint_1\n"
"%_tmp = OpLoad %uint4 %_src\n"
"OpStore %_dst %_tmp\n"
"%_out_uint4 = OpLoad %uint4 %_dst\n",
});
// disabled while shaderc has a bug that doesn't respect the target environment
/*
if(vk_version >= 0x12)
{
append_tests({
"%frag = OpLoad %float4 %gl_FragCoord\n"
"%_out_float4 = OpCopyLogical %float4 %frag\n",
});
}
*/
if(features.shaderFloat64)
{
// test pack/unpack from double
append_tests({
"%_ptr = OpAccessChain %ptr_Uniform_uint2 %cbuffer %uint_16\n"
"%_double_pack_source = OpLoad %uint2 %_ptr\n"
"%_out_double = OpExtInst %double %glsl450 PackDouble2x32 %_double_pack_source\n",
"%_ptr = OpAccessChain %ptr_Uniform_double %cbuffer %uint_17\n"
"%_double_unpack_source = OpLoad %double %_ptr\n"
"%_out_uint2 = OpExtInst %uint2 %glsl450 UnpackDouble2x32 %_double_unpack_source\n",
"%_ptr = OpAccessChain %ptr_Uniform_double %cbuffer %uint_17\n"
"%_pi = OpLoad %double %_ptr\n"
"%_two = OpFConvert %double %float_2_0\n"
"%_out_double = OpFMul %double %_pi %_two\n",
});
}
// test pointers into columns of matrices
append_tests({
R"EOTEST(
%_cola = OpCompositeConstruct %float4 %randf_0 %randf_1 %randf_2 %randf_3
%_colb = OpCompositeConstruct %float4 %randf_4 %randf_5 %randf_6 %randf_7
%_colc = OpCompositeConstruct %float4 %randf_8 %randf_9 %randf_10 %randf_11
%_cold = OpCompositeConstruct %float4 %randf_12 %randf_13 %randf_14 %randf_15
%_ptra = OpAccessChain %ptr_Private_float4 %priv_float4x4 %uint_0
%_ptrb = OpAccessChain %ptr_Private_float4 %priv_float4x4 %uint_1
%_ptrc = OpAccessChain %ptr_Private_float4 %priv_float4x4 %uint_2
%_ptrd = OpAccessChain %ptr_Private_float4 %priv_float4x4 %uint_3
OpStore %_ptra %_cola
OpStore %_ptrb %_colb
OpStore %_ptrc %_colc
OpStore %_ptrd %_cold
%_vec = OpCompositeConstruct %float4 %randf_16 %randf_17 %randf_18 %randf_19
%_mat = OpLoad %float4x4 %priv_float4x4
%_out_float4 = OpMatrixTimesVector %float4 %_mat %_vec
)EOTEST",
R"EOTEST(
%_cola = OpCompositeConstruct %float4 %randf_0 %randf_1 %randf_2 %randf_3
%_colb = OpCompositeConstruct %float4 %randf_4 %randf_5 %randf_6 %randf_7
%_colc = OpCompositeConstruct %float4 %randf_8 %randf_9 %randf_10 %randf_11
%_cold = OpCompositeConstruct %float4 %randf_12 %randf_13 %randf_14 %randf_15
%_ptra = OpAccessChain %ptr_Uniform_float4 %buffer %uint_0 %uint_0
%_ptrb = OpAccessChain %ptr_Uniform_float4 %buffer %uint_0 %uint_1
%_ptrc = OpAccessChain %ptr_Uniform_float4 %buffer %uint_0 %uint_2
%_ptrd = OpAccessChain %ptr_Uniform_float4 %buffer %uint_0 %uint_3
OpStore %_ptra %_cola
OpStore %_ptrb %_colb
OpStore %_ptrc %_colc
OpStore %_ptrd %_cold
%_vec = OpCompositeConstruct %float4 %randf_16 %randf_17 %randf_18 %randf_19
%_ptrmat = OpAccessChain %ptr_Uniform_float4x4 %buffer %uint_0
%_mat = OpLoad %float4x4 %_ptrmat
%_out_float4 = OpMatrixTimesVector %float4 %_mat %_vec
)EOTEST",
R"EOTEST(
%_cola = OpCompositeConstruct %float4 %randf_0 %randf_1 %randf_2 %randf_3
%_colb = OpCompositeConstruct %float4 %randf_4 %randf_5 %randf_6 %randf_7
%_colc = OpCompositeConstruct %float4 %randf_8 %randf_9 %randf_10 %randf_11
%_cold = OpCompositeConstruct %float4 %randf_12 %randf_13 %randf_14 %randf_15
%_ptra = OpAccessChain %ptr_Uniform_float4 %buffer %uint_1 %uint_0
%_ptrb = OpAccessChain %ptr_Uniform_float4 %buffer %uint_1 %uint_1
%_ptrc = OpAccessChain %ptr_Uniform_float4 %buffer %uint_1 %uint_2
%_ptrd = OpAccessChain %ptr_Uniform_float4 %buffer %uint_1 %uint_3
OpStore %_ptra %_cola
OpStore %_ptrb %_colb
OpStore %_ptrc %_colc
OpStore %_ptrd %_cold
%_vec = OpCompositeConstruct %float4 %randf_16 %randf_17 %randf_18 %randf_19
%_ptrmat = OpAccessChain %ptr_Uniform_float4x4 %buffer %uint_1
%_mat = OpLoad %float4x4 %_ptrmat
%_out_float4 = OpMatrixTimesVector %float4 %_mat %_vec
)EOTEST",
});
// test variables with initialisers
append_tests({
R"EOTEST(
; this has a constant initialiser, so should already be ready
%_out_float4 = OpLoad %float4 %priv_float4_init
)EOTEST",
R"EOTEST(
; this is uninitialised, but unforuntately that means we can't test our debugging
; against the real thing when it's undefined. But we can at least expose it so that
; when manually checking we see the uninitialised values
%_uninit = OpLoad %float4 %priv_float4
%_x = OpExtInst %float4 %glsl450 NClamp %_uninit %float4_0000 %float4_0000
%_out_float4 = OpFAdd %float4 %_x %float4_1234
)EOTEST",
R"EOTEST(
; this is uninitialised, but unforuntately that means we can't test our debugging
; against the real thing when it's undefined. But we can at least expose it so that
; when manually checking we see the uninitialised values
%_uninit = OpLoad %float4 %Color
%_x = OpExtInst %float4 %glsl450 NClamp %_uninit %float4_0000 %float4_0000
%_out_float4 = OpFAdd %float4 %_x %float4_1234
)EOTEST",
});
// test naming structs. Since we can't easily name auto-generated IDs we use a guid to give the
// ID a unique name
append_tests({
R"EOTEST(
%_a = OpCompositeConstruct %float4 %float_dyn_4_2 %float_dyn_1_0 %float_dyn_9_5 %float_dyn_0_01
%C14FA880_4F83_4982_BEAD_CE9103446C76 = OpCompositeInsert %parent %_a %null_parent 0
%_out_float4 = OpCompositeExtract %float4 %C14FA880_4F83_4982_BEAD_CE9103446C76 0
)EOTEST",
});
spv_debug +=
"OpName %C14FA880_4F83_4982_BEAD_CE9103446C76 \"C14FA880_4F83_4982_BEAD_CE9103446C76\"\n";
// test OpPhi
append_tests({
// basic simple test
R"EOTEST(
OpBranch %_toplabel
%_toplabel = OpLabel
%_val = OpDot %float %inpos %float2_12
%_cond = OpFOrdGreaterThan %bool %_val %float_37_0
%_parent1 = OpFMul %float %float_2_0 %float_0_5
OpSelectionMerge %_merge None
OpBranchConditional %_cond %_merge %_branchlabel
%_branchlabel = OpLabel
%_parent2 = OpFMul %float %float_2_0 %float_0_25
OpBranch %_merge
%_merge = OpLabel
; choose either parent1 or parent2, depending on if we branched
%_out_float = OpPhi %float %_parent1 %_toplabel %_parent2 %_branchlabel
OpBranch %_bottomlabel
%_bottomlabel = OpLabel
)EOTEST",
// test with a function call in each branch to ensure we still track the last block
// accurately
R"EOTEST(
OpBranch %_toplabel
%_toplabel = OpLabel
%_val = OpDot %float %inpos %float2_12
%_cond = OpFOrdGreaterThan %bool %_val %float_37_0
%_parent1 = OpFunctionCall %float %doubler %float_0_5
OpSelectionMerge %_merge None
OpBranchConditional %_cond %_merge %_branchlabel
%_branchlabel = OpLabel
%_parent2 = OpFunctionCall %float %doubler %float_0_25
OpBranch %_merge
%_merge = OpLabel
; choose either parent1 or parent2, depending on if we branched
%_out_float = OpPhi %float %_parent1 %_toplabel %_parent2 %_branchlabel
OpBranch %_bottomlabel
%_bottomlabel = OpLabel
)EOTEST",
});
// test switch for different integer types
std::vector<std::string> intTypes = {"int", "uint"};
std::vector<std::string> caseLiterals = {"0x12345678", "0xF2345678"};
if(features.shaderInt64)
{
intTypes.push_back("i64");
intTypes.push_back("u64");
caseLiterals.push_back("0x1234567812345678");
caseLiterals.push_back("0xF234567812345678");
}
for(size_t i = 0; i < intTypes.size(); ++i)
{
append_tests({fmt::format(
"%_test_switch_{0} = OpIAdd %{0} %{0}_0 %{0}_{1}\n"
"OpSelectionMerge %_break_{0} None\n"
"OpSwitch %_test_switch_{0} %_default_{0} 2 %_case_{0}_2 {1} %_case_{0}_{1}\n"
"%_case_{0}_2 = OpLabel\n"
"OpUnreachable\n"
"%_case_{0}_{1} = OpLabel\n"
"%_out_{0} = OpIAdd %{0} %{0}_0 %{0}_7\n"
"OpBranch %_break_{0}\n"
"%_default_{0} = OpLabel\n"
"OpUnreachable\n"
"%_break_{0} = OpLabel\n",
intTypes[i], caseLiterals[i])});
}
// test buffer device address
if(bdaFeatures.bufferDeviceAddress)
{
// bitcast uint2 address to pointer
append_tests({
R"EOTEST(
%_ptr_addr_bda_data_struct = OpAccessChain %ptr_PushConstant_uint2 %push_data %int_1
%_addr_bda_data_struct = OpLoad %uint2 %_ptr_addr_bda_data_struct
%_ptr_bda_data_struct = OpBitcast %ptr_PhysicalStorageBuffer_bda_data_struct %_addr_bda_data_struct
%_ptr_first = OpAccessChain %ptr_PhysicalStorageBuffer_bda_data_struct_first %_ptr_bda_data_struct %int_0
%_out_float4 = OpLoad %float4 %_ptr_first Aligned 16
)EOTEST",
// OpPtrAccessChain : float[] : ArrayStride 4
R"EOTEST(
%_ptr_addr_bda_data_struct = OpAccessChain %ptr_PushConstant_uint2 %push_data %int_1
%_addr_bda_data_struct = OpLoad %uint2 %_ptr_addr_bda_data_struct
%_ptr_bda_data_struct = OpBitcast %ptr_PhysicalStorageBuffer_bda_data_struct_f32_4 %_addr_bda_data_struct
%_ptr_f32 = OpPtrAccessChain %ptr_PhysicalStorageBuffer_f32 %_ptr_bda_data_struct %int_dyn_1
%_out_float = OpLoad %float %_ptr_f32 Aligned 16
)EOTEST",
// OpPtrAccessChain : float[] : ArrayStride 8
R"EOTEST(
%_ptr_addr_bda_data_struct = OpAccessChain %ptr_PushConstant_uint2 %push_data %int_1
%_addr_bda_data_struct = OpLoad %uint2 %_ptr_addr_bda_data_struct
%_ptr_bda_data_struct = OpBitcast %ptr_PhysicalStorageBuffer_bda_data_struct_f32_8 %_addr_bda_data_struct
%_ptr_f32 = OpPtrAccessChain %ptr_PhysicalStorageBuffer_f32 %_ptr_bda_data_struct %int_dyn_1
%_out_float = OpLoad %float %_ptr_f32 Aligned 16
)EOTEST",
// OpPtrAccessChain : float[] : ArrayStride 12
R"EOTEST(
%_ptr_addr_bda_data_struct = OpAccessChain %ptr_PushConstant_uint2 %push_data %int_1
%_addr_bda_data_struct = OpLoad %uint2 %_ptr_addr_bda_data_struct
%_ptr_bda_data_struct = OpBitcast %ptr_PhysicalStorageBuffer_bda_data_struct_f32_12 %_addr_bda_data_struct
%_ptr_f32 = OpPtrAccessChain %ptr_PhysicalStorageBuffer_f32 %_ptr_bda_data_struct %int_dyn_1
%_out_float = OpLoad %float %_ptr_f32 Aligned 16
)EOTEST",
});
if(features.shaderInt64)
{
append_tests({
// Convert u64 address to pointer
R"EOTEST(
%_ptr_addr_bda_data_struct = OpAccessChain %ptr_PushConstant_u64 %push_data %int_4
%_addr_bda_data_struct = OpLoad %u64 %_ptr_addr_bda_data_struct
%_ptr_bda_data_struct = OpConvertUToPtr %ptr_PhysicalStorageBuffer_bda_data_struct %_addr_bda_data_struct
%_ptr_first = OpAccessChain %ptr_PhysicalStorageBuffer_bda_data_struct_first %_ptr_bda_data_struct %int_1
%_out_float4 = OpLoad %float4 %_ptr_first Aligned 16
)EOTEST",
// Convert u64 address to pointer back to u64 address
R"EOTEST(
%_ptr_addr_bda_data_struct = OpAccessChain %ptr_PushConstant_u64 %push_data %int_4
%_addr = OpLoad %u64 %_ptr_addr_bda_data_struct
%_addr_bda_data_struct = OpIAdd %u64 %_addr %u64_dyn_8
%_ptr_bda_data_struct = OpConvertUToPtr %ptr_PhysicalStorageBuffer_bda_data_struct %_addr_bda_data_struct
%_out_u64 = OpConvertPtrToU %u64 %_ptr_bda_data_struct
)EOTEST",
// arithmetic on u64 address then convert u64 address to pointer
R"EOTEST(
%_ptr_addr_bda_data_struct = OpAccessChain %ptr_PushConstant_u64 %push_data %int_4
%_addr = OpLoad %u64 %_ptr_addr_bda_data_struct
%_addr2 = OpIAdd %u64 %_addr %u64_dyn_1023
%_addr3 = OpISub %u64 %_addr2 %u64_dyn_1023
%_addr_bda_data_struct = OpIAdd %u64 %_addr3 %u64_dyn_16
%_ptr_bda_data_struct = OpConvertUToPtr %ptr_PhysicalStorageBuffer_bda_data_struct %_addr_bda_data_struct
%_ptr_first = OpInBoundsAccessChain %ptr_PhysicalStorageBuffer_bda_data_struct_first %_ptr_bda_data_struct %int_0
%_out_float4 = OpLoad %float4 %_ptr_first Aligned 16
)EOTEST",
// form u64 address by arithmetic from two u32 values
R"EOTEST(
%_ptr_addr_bda_data_struct_hi = OpAccessChain %ptr_PushConstant_uint %push_data %int_2
%_addr_bda_data_struct_hi = OpLoad %uint %_ptr_addr_bda_data_struct_hi
%_ptr_addr_bda_data_struct_lo = OpAccessChain %ptr_PushConstant_uint %push_data %int_3
%_addr_bda_data_struct_lo = OpLoad %uint %_ptr_addr_bda_data_struct_lo
%_addr_u64_hi = OpUConvert %u64 %_addr_bda_data_struct_hi
%_addr_u64_lo = OpUConvert %u64 %_addr_bda_data_struct_lo
%_addr_u64 = OpShiftLeftLogical %u64 %_addr_u64_hi %uint_32
%_addr_bda_data_struct = OpIAdd %u64 %_addr_u64 %_addr_u64_lo
%_ptr_bda_data_struct = OpConvertUToPtr %ptr_PhysicalStorageBuffer_bda_data_struct %_addr_bda_data_struct
%_ptr_first = OpAccessChain %ptr_PhysicalStorageBuffer_bda_data_struct_first %_ptr_bda_data_struct %int_0
%_out_float4 = OpLoad %float4 %_ptr_first Aligned 16
)EOTEST",
});
}
}
// test integer dot product
if(intDotProdFeatures.shaderIntegerDotProduct)
{
std::vector<std::string> sTypes = {"int"};
std::vector<std::string> uTypes = {"uint"};
std::vector<std::string> sVecTypes = {"int4"};
std::vector<std::string> uVecTypes = {"uint4"};
if(float16Int8Features.shaderInt8)
{
sTypes.push_back("i8");
sVecTypes.push_back("i8v4");
uTypes.push_back("u8");
uVecTypes.push_back("u8v4");
}
if(features.shaderInt16)
{
sTypes.push_back("i16");
sVecTypes.push_back("i16v4");
uTypes.push_back("u16");
uVecTypes.push_back("u16v4");
}
if(features.shaderInt64)
{
sTypes.push_back("i64");
sVecTypes.push_back("i64v4");
uTypes.push_back("u64");
uVecTypes.push_back("u64v4");
}
// OpSDotKHR
// OpUDotKHR,
// OpSUDotKHR
// OpSDotAccSatKHR
// OpUDotAccSatKHR
// OpSUDotAccSatKHR
const char *prefixes[] = {"S", "U", "SU"};
for(size_t i = 0; i < sTypes.size(); ++i)
{
std::string signedTest;
std::string unsignedTest;
for(size_t j = 0; j < 3; ++j)
{
const char *prefix = prefixes[j];
const bool leftUnsigned = (j == 1);
const bool rightUnsigned = (j >= 1);
const std::string lhsType = leftUnsigned ? uTypes[i] : sTypes[i];
const std::string lhsVecType = leftUnsigned ? uVecTypes[i] : sVecTypes[i];
const std::string rhsType = rightUnsigned ? uTypes[i] : sTypes[i];
const std::string rhsVecType = rightUnsigned ? uVecTypes[i] : sVecTypes[i];
const std::string retType = lhsType;
std::string test;
test += fmt::format(
"%_lhs1_{6} = OpCompositeConstruct %{1} %{2}_1 %{2}_2 %{2}_3 %{2}_4\n"
"%_rhs1_{6} = OpCompositeConstruct %{3} %{4}_5 %{4}_6 %{4}_7 %{4}_8\n"
"%_res1_{6} = Op{5}DotKHR %{0} %_lhs1_{6} %_rhs1_{6}\n",
retType, lhsVecType, lhsType, rhsVecType, rhsType, prefix, j);
test += fmt::format(
"%_lhs2_{6} = OpCompositeConstruct %{1} %{2}_1 %{2}_2 %{2}_3 %{2}_4\n"
"%_rhs2_{6} = OpCompositeConstruct %{3} %{4}_9 %{4}_10 %{4}_11 %{4}_13\n"
"%_res2_{6} = Op{5}DotAccSatKHR %{0} %_lhs2_{6} %_rhs2_{6} %{0}_123\n",
retType, lhsVecType, lhsType, rhsVecType, rhsType, prefix, j);
if(leftUnsigned)
unsignedTest += test;
else
signedTest += test;
}
signedTest +=
fmt::format("%_out_{0} = OpCompositeConstruct %{0} %_res1_0 %_res2_0 %_res1_2 %_res2_2",
sVecTypes[i]);
unsignedTest +=
fmt::format("%_out_{0} = OpCompositeConstruct %{0} %_res1_1 %_res2_1 %_res1_1 %_res2_1",
uVecTypes[i]);
append_tests({signedTest, unsignedTest});
}
// Packed 4x8-bit
append_tests({
R"EOTEST(
%_x = OpSDotKHR %int %int_dyn_0x01020304 %int_dyn_0x05060708 PackedVectorFormat4x8BitKHR
%_y = OpSUDotKHR %int %int_dyn_0x090A0B0C %uint_dyn_0x0D0E0F10 PackedVectorFormat4x8BitKHR
%_z = OpSDotAccSatKHR %int %int_dyn_0x01020304 %int_dyn_0x05060708 %int_191 PackedVectorFormat4x8BitKHR
%_w = OpSUDotAccSatKHR %int %int_dyn_0x090A0B0C %uint_dyn_0x0D0E0F10 %int_neg237 PackedVectorFormat4x8BitKHR
%_out_int4 = OpCompositeConstruct %int4 %_x %_y %_z %_w
)EOTEST",
R"EOTEST(
%_x = OpUDotKHR %uint %uint_dyn_0x01020304 %uint_dyn_0x05060708 PackedVectorFormat4x8BitKHR
%_y = OpUDotAccSatKHR %uint %uint_dyn_0x090A0B0C0D %uint_dyn_0x0E0F1011 %uint_73 PackedVectorFormat4x8BitKHR
%_out_uint4 = OpCompositeConstruct %uint4 %_x %_y %_x %_y
)EOTEST",
});
}
}
std::string make_pixel_asm()
{
std::string switch_str = R"EOSHADER(
OpSelectionMerge %break None
OpSwitch %test
%default
)EOSHADER";
std::set<std::string> null_constants;
std::set<float> float_constants = {0.0f, 1.0f, 2.0f, 3.0f, 4.0f};
std::set<int32_t> int_constants = {7};
std::set<uint32_t> uint_constants;
std::set<int64_t> i64_constants;
std::set<uint64_t> u64_constants;
std::set<int8_t> i8_constants;
std::set<uint8_t> u8_constants;
std::set<int16_t> i16_constants;
std::set<uint16_t> u16_constants;
std::string cases;
for(size_t i = 0; i < asm_tests.size(); i++)
{
std::string &test = asm_tests[i];
// append a newline just so that searching for whitespace always finds it even if the last
// thing in the test is a %_foo
test += "\n";
// add the test's case
switch_str += fmt::format("{0} %test_{0}\n", i);
cases += fmt::format("%test_{} = OpLabel\n", i);
std::string test_suffix = fmt::format("_{}", i);
// find any identifiers with the prefix %_ in the test, and append _testindex
size_t offs = test.find("%_");
while(offs != std::string::npos)
{
offs = test.find_first_of("\n\t ", offs);
test.insert(offs, test_suffix);
offs = test.find("%_", offs);
}
// find any null constants referenced
offs = test.find("%null_");
while(offs != std::string::npos)
{
offs += 6; // past %null_
size_t begin = offs;
offs = test.find_first_of("\n\t ", offs);
null_constants.insert(test.substr(begin, offs - begin));
offs = test.find("%null_", offs);
}
// find any float constants referenced
for(std::string prefix : {"%float_", "%double_", "%half_"})
{
offs = test.find(prefix);
while(offs != std::string::npos)
{
offs += prefix.size();
// we generate dynamic and negative versions of all constants, skip to the first digit
offs = test.find_first_of("0123456789", offs);
size_t begin = offs;
offs = test.find_first_of("\n\t ", offs);
std::string val = test.substr(begin, offs - begin);
// convert any _ to a .
for(char &c : val)
if(c == '_')
c = '.';
float_constants.insert(std::strtof(val.c_str(), NULL));
offs = test.find(prefix, offs);
}
}
// find any i8 constants referenced
offs = test.find("%i8_");
while(offs != std::string::npos)
{
offs += 4; // past %i8_
// we generate dynamic and negative versions of all constants, skip to the first digit
offs = test.find_first_of("0123456789", offs);
// handle hex prefix
int base = 10;
if(test[offs] == '0' && test[offs + 1] == 'x')
{
base = 16;
offs += 2;
}
int8_t val = (int8_t)std::strtol(&test[offs], NULL, base);
i8_constants.insert(val);
// if it's a hex constant we'll name it in decimal, rename
if(base == 16)
{
size_t end = test.find_first_of("\n\t ", offs);
test.replace(offs - 2, end - offs + 2, fmt::format("{}", val));
}
offs = test.find("%i8_", offs);
}
// find any u8 constants referenced
offs = test.find("%u8_");
while(offs != std::string::npos)
{
offs += 4; // past %u8_
// we generate dynamic and negative versions of all constants, skip to the first digit
offs = test.find_first_of("0123456789", offs);
// handle hex prefix
int base = 10;
if(test[offs] == '0' && test[offs + 1] == 'x')
{
base = 16;
offs += 2;
}
uint8_t val = (uint8_t)std::strtoul(&test[offs], NULL, base);
u8_constants.insert(val);
// if it's a hex constant we'll name it in decimal, rename
if(base == 16)
{
size_t end = test.find_first_of("\n\t ", offs);
test.replace(offs - 2, end - offs + 2, fmt::format("{}", val));
}
offs = test.find("%u8_", offs);
}
// find any i16 constants referenced
offs = test.find("%i16_");
while(offs != std::string::npos)
{
offs += 5; // past %i16_
// we generate dynamic and negative versions of all constants, skip to the first digit
offs = test.find_first_of("0123456789", offs);
// handle hex prefix
int base = 10;
if(test[offs] == '0' && test[offs + 1] == 'x')
{
base = 16;
offs += 2;
}
int16_t val = (int16_t)std::strtoul(&test[offs], NULL, base);
i16_constants.insert(val);
// if it's a hex constant we'll name it in decimal, rename
if(base == 16)
{
size_t end = test.find_first_of("\n\t ", offs);
test.replace(offs - 2, end - offs + 2, fmt::format("{}", val));
}
offs = test.find("%i16_", offs);
}
// find any u16 constants referenced
offs = test.find("%u16_");
while(offs != std::string::npos)
{
offs += 5; // past %u16_
// we generate dynamic and negative versions of all constants, skip to the first digit
offs = test.find_first_of("0123456789", offs);
// handle hex prefix
int base = 10;
if(test[offs] == '0' && test[offs + 1] == 'x')
{
base = 16;
offs += 2;
}
uint16_t val = (uint16_t)std::strtoul(&test[offs], NULL, base);
u16_constants.insert(val);
// if it's a hex constant we'll name it in decimal, rename
if(base == 16)
{
size_t end = test.find_first_of("\n\t ", offs);
test.replace(offs - 2, end - offs + 2, fmt::format("{}", val));
}
offs = test.find("%u16_", offs);
}
// find any int constants referenced
offs = test.find("%int_");
while(offs != std::string::npos)
{
offs += 5; // past %int_
// we generate dynamic and negative versions of all constants, skip to the first digit
offs = test.find_first_of("0123456789", offs);
// handle hex prefix
int base = 10;
if(test[offs] == '0' && test[offs + 1] == 'x')
{
base = 16;
offs += 2;
}
int32_t val = (int32_t)std::strtol(&test[offs], NULL, base);
int_constants.insert(val);
// if it's a hex constant we'll name it in decimal, rename
if(base == 16)
{
size_t end = test.find_first_of("\n\t ", offs);
test.replace(offs - 2, end - offs + 2, fmt::format("{}", val));
}
offs = test.find("%int_", offs);
}
// find any uint constants referenced
offs = test.find("%uint_");
while(offs != std::string::npos)
{
offs += 6; // past %uint_
// we generate dynamic and negative versions of all constants, skip to the first digit
offs = test.find_first_of("0123456789", offs);
// handle hex prefix
int base = 10;
if(test[offs] == '0' && test[offs + 1] == 'x')
{
base = 16;
offs += 2;
}
uint32_t val = (uint32_t)std::strtoul(&test[offs], NULL, base);
uint_constants.insert(val);
// if it's a hex constant we'll name it in decimal, rename
if(base == 16)
{
size_t end = test.find_first_of("\n\t ", offs);
test.replace(offs - 2, end - offs + 2, fmt::format("{}", val));
}
offs = test.find("%uint_", offs);
}
// find any i64 constants referenced
offs = test.find("%i64_");
while(offs != std::string::npos)
{
offs += 5; // past %i64_
// we generate dynamic and negative versions of all constants, skip to the first digit
offs = test.find_first_of("0123456789", offs);
// handle hex prefix
int base = 10;
if(test[offs] == '0' && test[offs + 1] == 'x')
{
base = 16;
offs += 2;
}
int64_t val = std::strtoll(&test[offs], NULL, base);
i64_constants.insert(val);
// if it's a hex constant we'll name it in decimal, rename
if(base == 16)
{
size_t end = test.find_first_of("\n\t ", offs);
test.replace(offs - 2, end - offs + 2, fmt::format("{}", val));
}
offs = test.find("%i64_", offs);
}
// find any u64 constants referenced
offs = test.find("%u64_");
while(offs != std::string::npos)
{
offs += 5; // past %u64_
// we generate dynamic and negative versions of all constants, skip to the first digit
offs = test.find_first_of("0123456789", offs);
// handle hex prefix
int base = 10;
if(test[offs] == '0' && test[offs + 1] == 'x')
{
base = 16;
offs += 2;
}
uint64_t val = std::strtoull(&test[offs], NULL, base);
u64_constants.insert(val);
// if it's a hex constant we'll name it in decimal, rename
if(base == 16)
{
size_t end = test.find_first_of("\n\t ", offs);
test.replace(offs - 2, end - offs + 2, fmt::format("{}", val));
}
offs = test.find("%u64_", offs);
}
// add the test itself now
cases += "\n";
cases += test;
cases += "\n";
bool store_out = true;
if(test.find("%_out_float4") != std::string::npos)
{
// if the test outputted a float4, we can dump it directly
cases += fmt::format("OpStore %Color %_out_float4_{}\n", i);
}
else
{
// otherwise convert and up-swizzle to float4 as needed
if(test.find("%_out_float_") != std::string::npos)
{
cases += fmt::format(
"%Color_{0} = OpCompositeConstruct %float4 "
" %_out_float_{0} %_out_float_{0} %_out_float_{0} %_out_float_{0}\n",
i);
}
else if(test.find("%_out_float2_") != std::string::npos)
{
cases += fmt::format(
"%Color_{0} = OpVectorShuffle %float4 %_out_float2_{0} %_out_float2_{0} 0 1 0 1\n", i);
}
else if(test.find("%_out_float3_") != std::string::npos)
{
cases += fmt::format(
"%Color_{0} = OpVectorShuffle %float4 %_out_float3_{0} %_out_float3_{0} 0 1 2 0\n", i);
}
else if(test.find("%_out_double_") != std::string::npos)
{
cases += fmt::format(
"%_out_float_{0} = OpFConvert %float %_out_double_{0}\n"
"%Color_{0} = OpCompositeConstruct %float4 "
" %_out_float_{0} %_out_float_{0} %_out_float_{0} %_out_float_{0}\n",
i);
}
else if(test.find("%_out_double2_") != std::string::npos)
{
cases += fmt::format(
"%_out_float2_{0} = OpFConvert %float2 %_out_double2_{0}\n"
"%Color_{0} = OpVectorShuffle %float4 %_out_float2_{0} %_out_float2_{0} 0 1 0 1\n",
i);
}
else if(test.find("%_out_double3_") != std::string::npos)
{
cases += fmt::format(
"%_out_float3_{0} = OpFConvert %float3 %_out_double3_{0}\n"
"%Color_{0} = OpVectorShuffle %float4 %_out_float3_{0} %_out_float3_{0} 0 1 2 0\n",
i);
}
else if(test.find("%_out_double4_") != std::string::npos)
{
cases += fmt::format("%Color_{0} = OpFConvert %float4 %_out_double4_{0}\n", i);
}
else if(test.find("%_out_int_") != std::string::npos)
{
cases += fmt::format(
"%_f_{0} = OpConvertSToF %float %_out_int_{0}\n"
"%Color_{0} = OpCompositeConstruct %float4 %_f_{0} %_f_{0} %_f_{0} %_f_{0}\n",
i);
}
else if(test.find("%_out_int2_") != std::string::npos)
{
cases += fmt::format(
"%_f_{0} = OpConvertSToF %float2 %_out_int2_{0}\n"
"%Color_{0} = OpVectorShuffle %float4 %_f_{0} %_f_{0} 0 1 0 1\n",
i);
}
else if(test.find("%_out_int3_") != std::string::npos)
{
cases += fmt::format(
"%_f_{0} = OpConvertSToF %float3 %_out_int3_{0}\n"
"%Color_{0} = OpVectorShuffle %float4 %_f_{0} %_f_{0} 0 1 2 0\n",
i);
}
else if(test.find("%_out_int4_") != std::string::npos)
{
cases += fmt::format("%Color_{0} = OpConvertSToF %float4 %_out_int4_{0}\n", i);
}
else if(test.find("%_out_uint_") != std::string::npos)
{
cases += fmt::format(
"%_f_{0} = OpConvertUToF %float %_out_uint_{0}\n"
"%Color_{0} = OpCompositeConstruct %float4 %_f_{0} %_f_{0} %_f_{0} %_f_{0}\n",
i);
}
else if(test.find("%_out_uint2_") != std::string::npos)
{
cases += fmt::format(
"%_f_{0} = OpConvertUToF %float2 %_out_uint2_{0}\n"
"%Color_{0} = OpVectorShuffle %float4 %_f_{0} %_f_{0} 0 1 0 1\n",
i);
}
else if(test.find("%_out_uint3_") != std::string::npos)
{
cases += fmt::format(
"%_f_{0} = OpConvertUToF %float3 %_out_uint3_{0}\n"
"%Color_{0} = OpVectorShuffle %float4 %_f_{0} %_f_{0} 0 1 2 0\n",
i);
}
else if(test.find("%_out_uint4_") != std::string::npos)
{
cases += fmt::format("%Color_{0} = OpConvertUToF %float4 %_out_uint4_{0}\n", i);
}
else if(test.find("%_out_i64_") != std::string::npos)
{
cases += fmt::format(
"%_f_{0} = OpConvertSToF %float %_out_i64_{0}\n"
"%Color_{0} = OpCompositeConstruct %float4 %_f_{0} %_f_{0} %_f_{0} "
"%_f_{0}\n",
i);
}
else if(test.find("%_out_i64v4_") != std::string::npos)
{
cases += fmt::format("%Color_{0} = OpConvertSToF %float4 %_out_i64v4_{0}\n", i);
}
else if(test.find("%_out_u64_") != std::string::npos)
{
cases += fmt::format(
"%_f_{0} = OpConvertUToF %float %_out_u64_{0}\n"
"%Color_{0} = OpCompositeConstruct %float4 %_f_{0} %_f_{0} %_f_{0} "
"%_f_{0}\n",
i);
}
else if(test.find("%_out_u64v4_") != std::string::npos)
{
cases += fmt::format("%Color_{0} = OpConvertUToF %float4 %_out_u64v4_{0}\n", i);
}
else if(test.find("%_out_i8_") != std::string::npos)
{
cases += fmt::format(
"%_f_{0} = OpConvertSToF %float %_out_i8_{0}\n"
"%Color_{0} = OpCompositeConstruct %float4 %_f_{0} %_f_{0} %_f_{0} %_f_{0}\n",
i);
}
else if(test.find("%_out_i8v4_") != std::string::npos)
{
cases += fmt::format("%Color_{0} = OpConvertSToF %float4 %_out_i8v4_{0}\n", i);
}
else if(test.find("%_out_u8_") != std::string::npos)
{
cases += fmt::format(
"%_f_{0} = OpConvertUToF %float %_out_u8_{0}\n"
"%Color_{0} = OpCompositeConstruct %float4 %_f_{0} %_f_{0} %_f_{0} %_f_{0}\n",
i);
}
else if(test.find("%_out_u8v2_") != std::string::npos)
{
cases += fmt::format(
"%_f_{0} = OpConvertUToF %float2 %_out_u8v2_{0}\n"
"%Color_{0} = OpVectorShuffle %float4 %_f_{0} %_f_{0} 0 1 0 1\n",
i);
}
else if(test.find("%_out_u8v4_") != std::string::npos)
{
cases += fmt::format("%Color_{0} = OpConvertUToF %float4 %_out_u8v4_{0}\n", i);
}
else if(test.find("%_out_i16_") != std::string::npos)
{
cases += fmt::format(
"%_f_{0} = OpConvertSToF %float %_out_i16_{0}\n"
"%Color_{0} = OpCompositeConstruct %float4 %_f_{0} %_f_{0} %_f_{0} %_f_{0}\n",
i);
}
else if(test.find("%_out_i16v4_") != std::string::npos)
{
cases += fmt::format("%Color_{0} = OpConvertSToF %float4 %_out_i16v4_{0}\n", i);
}
else if(test.find("%_out_u16_") != std::string::npos)
{
cases += fmt::format(
"%_f_{0} = OpConvertUToF %float %_out_u16_{0}\n"
"%Color_{0} = OpCompositeConstruct %float4 %_f_{0} %_f_{0} %_f_{0} %_f_{0}\n",
i);
}
else if(test.find("%_out_u16v2_") != std::string::npos)
{
cases += fmt::format(
"%_f_{0} = OpConvertUToF %float2 %_out_u16v2_{0}\n"
"%Color_{0} = OpVectorShuffle %float4 %_f_{0} %_f_{0} 0 1 0 1\n",
i);
}
else if(test.find("%_out_u16v4_") != std::string::npos)
{
cases += fmt::format("%Color_{0} = OpConvertUToF %float4 %_out_u16v4_{0}\n", i);
}
else if(test.find("%_out_half2_") != std::string::npos)
{
cases += fmt::format(
"%_f_{0} = OpFConvert %float2 %_out_half2_{0}\n"
"%Color_{0} = OpVectorShuffle %float4 %_f_{0} %_f_{0} 0 1 0 1\n",
i);
}
else if(test.find("; no_out") != std::string::npos)
{
store_out = false;
}
else
{
TEST_FATAL("Test with no recognised output");
}
if(store_out)
cases += fmt::format("OpStore %Color %Color_{}\n", i);
}
cases += "OpBranch %break\n";
}
if(features.shaderFloat64)
{
typesConstants +=
"%double = OpTypeFloat 64\n"
"%double2 = OpTypeVector %double 2\n"
"%double3 = OpTypeVector %double 3\n"
"%double4 = OpTypeVector %double 4\n"
"%double2x2 = OpTypeMatrix %double2 2\n"
"%double3x3 = OpTypeMatrix %double3 3\n"
"%double2x4 = OpTypeMatrix %double2 4\n"
"%double4x2 = OpTypeMatrix %double4 2\n"
"%double4x4 = OpTypeMatrix %double4 4\n";
typesConstants += "%ptr_Uniform_double = OpTypePointer Uniform %double\n";
capabilities += "OpCapability Float64\n";
}
if(float16Int8Features.shaderFloat16)
{
typesConstants +=
"%half = OpTypeFloat 16\n"
"%half2 = OpTypeVector %half 2\n";
capabilities += "OpCapability Float16\n";
}
if(float16Int8Features.shaderInt8 || storage8Features.storageBuffer8BitAccess ||
storage8Features.uniformAndStorageBuffer8BitAccess || storage8Features.storagePushConstant8)
{
typesConstants +=
"%i8 = OpTypeInt 8 1\n"
"%i8v4 = OpTypeVector %i8 4\n"
"%u8 = OpTypeInt 8 0\n"
"%u8v2 = OpTypeVector %u8 2\n"
"%u8v4 = OpTypeVector %u8 4\n";
capabilities += "OpCapability Int8\n";
}
if(features.shaderInt64)
{
typesConstants +=
"%i64 = OpTypeInt 64 1\n"
"%i64v4 = OpTypeVector %i64 4\n"
"%u64 = OpTypeInt 64 0\n"
"%u64v4 = OpTypeVector %u64 4\n";
capabilities += "OpCapability Int64\n";
}
if(features.shaderInt16 || storage16Features.storageBuffer16BitAccess ||
storage16Features.uniformAndStorageBuffer16BitAccess ||
storage16Features.storagePushConstant16 || storage16Features.storageInputOutput16)
{
typesConstants +=
"%i16 = OpTypeInt 16 1\n"
"%i16v4 = OpTypeVector %i16 4\n"
"%u16 = OpTypeInt 16 0\n"
"%u16v2 = OpTypeVector %u16 2\n"
"%u16v4 = OpTypeVector %u16 4\n";
capabilities += "OpCapability Int16\n";
}
if(bdaFeatures.bufferDeviceAddress)
{
capabilities += "OpCapability PhysicalStorageBufferAddresses\n";
spv_extensions += R"EOSHADER(
OpExtension "SPV_KHR_physical_storage_buffer"
)EOSHADER";
typesConstants += "%pushdata_struct = OpTypeStruct %int4 %uint2 %uint %uint";
if(features.shaderInt64)
typesConstants += " %u64\n";
else
typesConstants += " %uint2\n";
typesConstants += R"EOSHADER(
%ptr_PushConstant_pushdata_struct = OpTypePointer PushConstant %pushdata_struct
%push_data = OpVariable %ptr_PushConstant_pushdata_struct PushConstant
%ptr_PushConstant_uint = OpTypePointer PushConstant %uint
%ptr_PushConstant_uint2 = OpTypePointer PushConstant %uint2
)EOSHADER";
if(features.shaderInt64)
typesConstants += "%ptr_PushConstant_u64 = OpTypePointer PushConstant %u64\n";
typesConstants += "%bda_data_struct = OpTypeStruct %float4 %float4";
typesConstants += R"EOSHADER(
%ptr_PhysicalStorageBuffer_bda_data_struct = OpTypePointer PhysicalStorageBuffer %bda_data_struct
%ptr_PhysicalStorageBuffer_bda_data_struct_first = OpTypePointer PhysicalStorageBuffer %float4
%ptr_PhysicalStorageBuffer_bda_data_struct_f32_4 = OpTypePointer PhysicalStorageBuffer %float
%ptr_PhysicalStorageBuffer_bda_data_struct_f32_8 = OpTypePointer PhysicalStorageBuffer %float
%ptr_PhysicalStorageBuffer_bda_data_struct_f32_12 = OpTypePointer PhysicalStorageBuffer %float
%ptr_PhysicalStorageBuffer_f32 = OpTypePointer PhysicalStorageBuffer %float
)EOSHADER";
decorations += R"EOSHADER(
OpDecorate %ptr_PhysicalStorageBuffer_bda_data_struct_f32_4 ArrayStride 4
OpDecorate %ptr_PhysicalStorageBuffer_bda_data_struct_f32_8 ArrayStride 8
OpDecorate %ptr_PhysicalStorageBuffer_bda_data_struct_f32_12 ArrayStride 12
OpDecorate %pushdata_struct Block
OpMemberDecorate %pushdata_struct 0 Offset 16 ; int4 data
OpMemberDecorate %pushdata_struct 1 Offset 32 ; uint2 bda_uvec2
OpMemberDecorate %pushdata_struct 2 Offset 40 ; uint bda_hi
OpMemberDecorate %pushdata_struct 3 Offset 44 ; uint bda_lo
OpMemberDecorate %pushdata_struct 4 Offset 48 ; uint64_t bda_u64
OpDecorate %bda_data_struct Block
OpMemberDecorate %bda_data_struct 0 Offset 0 ; float f32[0..3]
OpMemberDecorate %bda_data_struct 1 Offset 16 ; float f32[4..7]
)EOSHADER";
}
if(intDotProdFeatures.shaderIntegerDotProduct)
{
capabilities += "OpCapability DotProductKHR\n";
capabilities += "OpCapability DotProductInputAllKHR\n";
// Requires Int8 support
if(float16Int8Features.shaderInt8)
capabilities += "OpCapability DotProductInput4x8BitKHR\n";
capabilities += "OpCapability DotProductInput4x8BitPackedKHR\n";
spv_extensions += R"EOSHADER(
OpExtension "SPV_KHR_integer_dot_product"
)EOSHADER";
}
std::string cbuffer =
"%cbuffer_struct = OpTypeStruct %float4 %float4 %float4 %float4 %float4 %float4 %float4 "
" %float4 %float4 %float4 %float4 %float4 %uint %uint %uint "
" %uint %uint2";
if(features.shaderFloat64)
cbuffer += " %double";
else
cbuffer += " %uint2";
cbuffer += "\n";
typesConstants += cbuffer;
decorations += R"EOSHADER(
OpDecorate %cbuffer_struct Block
OpDecorate %cbuffer DescriptorSet 0
OpDecorate %cbuffer Binding 10
OpMemberDecorate %cbuffer_struct 0 Offset 0 ; vec4 first
OpMemberDecorate %cbuffer_struct 1 Offset 16 ; vec4 pad1
OpMemberDecorate %cbuffer_struct 2 Offset 32 ; vec4 second
OpMemberDecorate %cbuffer_struct 3 Offset 48 ; vec4 nan
OpMemberDecorate %cbuffer_struct 4 Offset 64 ; vec4 third
OpMemberDecorate %cbuffer_struct 5 Offset 80 ; vec4 pad3
OpMemberDecorate %cbuffer_struct 6 Offset 96 ; vec4 fourth
OpMemberDecorate %cbuffer_struct 7 Offset 112 ; vec4 unorm2PackSource
OpMemberDecorate %cbuffer_struct 8 Offset 128 ; vec4 snorm2PackSource
OpMemberDecorate %cbuffer_struct 9 Offset 144 ; vec4 unorm4PackSource
OpMemberDecorate %cbuffer_struct 10 Offset 160 ; vec4 snorm4PackSource
OpMemberDecorate %cbuffer_struct 11 Offset 176 ; vec4 halfPackSource
OpMemberDecorate %cbuffer_struct 12 Offset 192 ; uint unormUnpackSource
OpMemberDecorate %cbuffer_struct 13 Offset 196 ; uint snormUnpackSource
OpMemberDecorate %cbuffer_struct 14 Offset 200 ; uint halfUnpackSource
OpMemberDecorate %cbuffer_struct 15 Offset 204 ; uint pad
OpMemberDecorate %cbuffer_struct 16 Offset 208 ; uint2 doubleUnpackSource
OpMemberDecorate %cbuffer_struct 17 Offset 216 ; double doublePackSource
)EOSHADER";
typesConstants +=
"%ptr_Uniform_cbuffer_struct = OpTypePointer Uniform %cbuffer_struct\n"
"%cbuffer = OpVariable %ptr_Uniform_cbuffer_struct Uniform\n";
// now generate all the constants
for(const std::string &n : null_constants)
typesConstants += fmt::format("%null_{0} = OpConstantNull %{0}\n", n);
typesConstants += "\n";
for(float f : float_constants)
{
std::string name = fmt::format("{}", f);
for(char &c : name)
if(c == '.')
c = '_';
typesConstants += fmt::format("%float_{} = OpConstant %float {}\n", name, f);
typesConstants += fmt::format("%float_neg{} = OpConstant %float -{}\n", name, f);
if(float16Int8Features.shaderFloat16)
{
typesConstants += fmt::format("%half_{} = OpConstant %half {}\n", name, f);
typesConstants += fmt::format("%half_neg{} = OpConstant %half -{}\n", name, f);
}
if(features.shaderFloat64)
{
typesConstants += fmt::format("%double_{} = OpConstant %double {}\n", name, f);
typesConstants += fmt::format("%double_neg{} = OpConstant %double -{}\n", name, f);
}
}
typesConstants += "\n";
if(float16Int8Features.shaderInt8)
{
for(int8_t i : i8_constants)
typesConstants += fmt::format("%i8_{0} = OpConstant %i8 {0}\n", i);
typesConstants += "\n";
for(uint8_t u : u8_constants)
typesConstants += fmt::format("%u8_{0} = OpConstant %u8 {0}\n", u);
typesConstants += "\n";
}
if(features.shaderInt16)
{
for(int16_t i : i16_constants)
typesConstants += fmt::format("%i16_{0} = OpConstant %i16 {0}\n", i);
typesConstants += "\n";
for(uint16_t u : u16_constants)
typesConstants += fmt::format("%u16_{0} = OpConstant %u16 {0}\n", u);
typesConstants += "\n";
}
for(int32_t i : int_constants)
{
typesConstants += fmt::format("%int_{0} = OpConstant %int {0}\n", i);
typesConstants += fmt::format("%int_neg{0} = OpConstant %int -{0}\n", i);
}
typesConstants += "\n";
for(uint32_t u : uint_constants)
typesConstants += fmt::format("%uint_{0} = OpConstant %uint {0}\n", u);
typesConstants += "\n";
if(features.shaderInt64)
{
for(int64_t i : i64_constants)
{
typesConstants += fmt::format("%i64_{0} = OpConstant %i64 {0}\n", i);
typesConstants += fmt::format("%i64_neg{0} = OpConstant %i64 -{0}\n", i);
}
typesConstants += "\n";
for(uint64_t u : u64_constants)
{
typesConstants += fmt::format("%u64_{0} = OpConstant %u64 {0}\n", u);
}
typesConstants += "\n";
}
else
{
if(!i64_constants.empty())
TEST_FATAL("Test using i64 constants without shaderInt64 capability");
if(!u64_constants.empty())
TEST_FATAL("Test using u64 constants without shaderInt64 capability");
}
for(size_t i = 0; i < 32; i++)
typesConstants += fmt::format("%randf_{} = OpConstant %float {:.3}\n", i, RANDF(0.0f, 1.0f));
typesConstants += "\n";
// vector constants here manually, as we can't pull these out easily
typesConstants += R"EOSHADER(
%float4_0000 = OpConstantComposite %float4 %float_0_0 %float_0_0 %float_0_0 %float_0_0
%float4_1234 = OpConstantComposite %float4 %float_1_0 %float_2_0 %float_3_0 %float_4_0
%float3_000 = OpConstantComposite %float3 %float_0_0 %float_0_0 %float_0_0
%float3_123 = OpConstantComposite %float3 %float_1_0 %float_2_0 %float_3_0
%float2_00 = OpConstantComposite %float2 %float_0_0 %float_0_0
%float2_12 = OpConstantComposite %float2 %float_1_0 %float_2_0
%priv_float4_init = OpVariable %ptr_Private_float4 Private %float4_1234
)EOSHADER";
std::string memory_model =
(bdaFeatures.bufferDeviceAddress) ? "PhysicalStorageBuffer64" : "Logical";
std::string ret = capabilities + spv_extensions + extinstimport +
R"EOSHADER(
OpMemoryModel )EOSHADER" +
memory_model + " GLSL450\n" +
R"EOSHADER(
OpEntryPoint Fragment %main "main" %flatData %linearData %Color %gl_FragCoord
)EOSHADER" + executionmodes +
spv_debug + decorations + typesConstants + functions +
R"EOSHADER(
%main = OpFunction %void None %mainfunc
%main_begin = OpLabel
%test_ptr = OpAccessChain %ptr_Input_uint %flatData %flatv2f_test_idx
%test = OpLoad %uint %test_ptr
%zeroVal_ptr = OpAccessChain %ptr_Input_float2 %linearData %v2f_zeroVal_idx
%zeroVal = OpLoad %float2 %zeroVal_ptr
%zeroVal_x = OpCompositeExtract %float %zeroVal 0
%zeroVal_y = OpCompositeExtract %float %zeroVal 1
%zerof = OpCompositeExtract %float %zeroVal 0
%inpos_ptr = OpAccessChain %ptr_Input_float2 %linearData %v2f_inpos_idx
%inpos = OpLoad %float2 %inpos_ptr
%inposIncreased_ptr = OpAccessChain %ptr_Input_float2 %linearData %v2f_inposIncreased_idx
%inposIncreased = OpLoad %float2 %inposIncreased_ptr
%tinyVal_ptr = OpAccessChain %ptr_Input_float %linearData %v2f_tinyVal_idx
%tinyVal = OpLoad %float %tinyVal_ptr
%oneVal_ptr = OpAccessChain %ptr_Input_float %linearData %v2f_oneVal_idx
%oneVal = OpLoad %float %oneVal_ptr
%negoneVal_ptr = OpAccessChain %ptr_Input_float %linearData %v2f_negoneVal_idx
%negoneVal = OpLoad %float %negoneVal_ptr
%posinf = OpFDiv %float %oneVal %zerof
%neginf = OpFDiv %float %negoneVal %zerof
; NaN generation is hard and we want to avoid compilers compiling it out, so generate
; it in shader and multiply by one from a UBO so we get NaN either way
; (since NaN * anything = NaN)
%nan_shad = OpFDiv %float %zerof %zerof
%nan_ptr = OpAccessChain %ptr_Uniform_float4 %cbuffer %uint_3
%nan_ubo = OpLoad %float4 %nan_ptr
%nan_ubo_x = OpCompositeExtract %float %nan_ubo 0
%nan = OpFMul %float %nan_shad %nan_ubo_x
%intval_ptr = OpAccessChain %ptr_Input_uint %flatData %flatv2f_intval_idx
%intval = OpLoad %uint %intval_ptr
%tmp = OpISub %uint %intval %test
%zerou = OpISub %uint %tmp %int_7
%zeroi = OpBitcast %int %zerou
)EOSHADER";
if(features.shaderFloat64)
ret += "%zerof64 = OpFConvert %double %zerof\n";
if(features.shaderInt64)
{
ret +=
"%_temp = OpCompositeConstruct %uint2 %zerou %zerou\n"
"%zerou64 = OpBitcast %u64 %_temp\n";
}
// generate dynamic versions of the constants
for(float f : float_constants)
{
std::string name = fmt::format("{}", f);
for(char &c : name)
if(c == '.')
c = '_';
ret += fmt::format("%float_dyn_{0} = OpFAdd %float %zerof %float_{0}\n", name);
ret += fmt::format("%float_dyn_neg{0} = OpFAdd %float %zerof %float_neg{0}\n", name);
if(features.shaderFloat64)
{
ret += fmt::format("%double_dyn_{0} = OpFAdd %double %zerof64 %double_{0}\n", name);
ret += fmt::format("%double_dyn_neg{0} = OpFAdd %double %zerof64 %double_neg{0}\n", name);
}
}
ret += "\n";
for(int32_t i : int_constants)
{
ret += fmt::format("%int_dyn_{0} = OpIAdd %int %zeroi %int_{0}\n", i);
ret += fmt::format("%int_dyn_neg{0} = OpIAdd %int %zeroi %int_neg{0}\n", i);
}
ret += "\n";
for(uint32_t u : uint_constants)
ret += fmt::format("%uint_dyn_{0} = OpIAdd %uint %zerou %uint_{0}\n", u);
for(uint64_t u : u64_constants)
ret += fmt::format("%u64_dyn_{0} = OpIAdd %u64 %zerou64 %u64_{0}\n", u);
ret += "\n";
for(size_t i = 0; i < 32; i++)
ret += fmt::format("%randf_dyn_{0} = OpFAdd %float %zerof %randf_{0}\n", i);
ret += "\n";
ret += R"EOSHADER(
%float4_dyn_0000 = OpCompositeConstruct %float4 %float_dyn_0_0 %float_dyn_0_0 %float_dyn_0_0 %float_dyn_0_0
%float4_dyn_1234 = OpCompositeConstruct %float4 %float_dyn_1_0 %float_dyn_2_0 %float_dyn_3_0 %float_dyn_4_0
%float3_dyn_000 = OpCompositeConstruct %float3 %float_dyn_0_0 %float_dyn_0_0 %float_dyn_0_0
%float3_dyn_123 = OpCompositeConstruct %float3 %float_dyn_1_0 %float_dyn_2_0 %float_dyn_3_0
%float2_dyn_00 = OpCompositeConstruct %float2 %float_dyn_0_0 %float_dyn_0_0
%float2_dyn_12 = OpCompositeConstruct %float2 %float_dyn_1_0 %float_dyn_2_0
)EOSHADER";
ret += switch_str;
ret += cases;
ret += R"EOSHADER(
%default = OpLabel
OpStore %Color %float4_0000
OpBranch %break
%break = OpLabel
OpReturn
OpFunctionEnd
)EOSHADER";
return ret;
}
uint32_t vk_version = 0x10;
VkPhysicalDevice16BitStorageFeaturesKHR storage16Features = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR,
};
VkPhysicalDevice8BitStorageFeaturesKHR storage8Features = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR,
};
VkPhysicalDeviceFloat16Int8FeaturesKHR float16Int8Features = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR,
};
VkPhysicalDeviceBufferDeviceAddressFeaturesEXT bdaFeatures = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_KHR,
};
VkPhysicalDeviceComputeShaderDerivativesFeaturesNV csDerivFeatures = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_FEATURES_NV,
};
VkPhysicalDeviceShaderIntegerDotProductFeaturesKHR intDotProdFeatures = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES_KHR,
};
void Prepare(int argc, char **argv)
{
// require descriptor indexing
optDevExts.push_back(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
// dependencies of VK_EXT_descriptor_indexing
optDevExts.push_back(VK_KHR_MAINTENANCE3_EXTENSION_NAME);
// add float16/int8 extensions
optDevExts.push_back(VK_KHR_8BIT_STORAGE_EXTENSION_NAME);
optDevExts.push_back(VK_KHR_16BIT_STORAGE_EXTENSION_NAME);
optDevExts.push_back(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME);
// dependencies of VK_KHR_8bit_storage
optDevExts.push_back(VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME);
// add BDA extension
optDevExts.push_back(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
// compute shader derivatives
optDevExts.push_back(VK_NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME);
// integer dot product
optDevExts.push_back(VK_KHR_SHADER_INTEGER_DOT_PRODUCT_EXTENSION_NAME);
// we require this to pixel shader debug anyway, so we might as well require it for all tests.
features.fragmentStoresAndAtomics = VK_TRUE;
// this is so widely supported just require it without fallback
features.imageCubeArray = VK_TRUE;
VulkanGraphicsTest::Prepare(argc, argv);
if(!Avail.empty())
return;
const bool descIndexing = std::find(devExts.begin(), devExts.end(),
VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME) != devExts.end();
const bool storage16 = std::find(devExts.begin(), devExts.end(),
VK_KHR_16BIT_STORAGE_EXTENSION_NAME) != devExts.end();
const bool storage8 = std::find(devExts.begin(), devExts.end(),
VK_KHR_8BIT_STORAGE_EXTENSION_NAME) != devExts.end();
const bool float16int8 = std::find(devExts.begin(), devExts.end(),
VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME) != devExts.end();
const bool bda = std::find(devExts.begin(), devExts.end(),
VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME) != devExts.end();
const bool csDerivatives =
std::find(devExts.begin(), devExts.end(), VK_NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME) !=
devExts.end();
const bool intDotProduct =
std::find(devExts.begin(), devExts.end(),
VK_KHR_SHADER_INTEGER_DOT_PRODUCT_EXTENSION_NAME) != devExts.end();
vk_version = 0x10;
if(physProperties.apiVersion >= VK_MAKE_VERSION(1, 1, 0))
vk_version = 0x11;
if(physProperties.apiVersion >= VK_MAKE_VERSION(1, 2, 0))
vk_version = 0x12;
#define LIMIT_CHECK(limit, req) \
if(physProperties.limits.limit < req) \
Avail = fmt::format("Limit '" #limit "' {} is insufficient (need at least {})", \
physProperties.limits.limit, req);
if(descIndexing)
{
LIMIT_CHECK(maxPerStageDescriptorSampledImages, 128);
LIMIT_CHECK(maxPerStageDescriptorSamplers, 64);
LIMIT_CHECK(maxPerStageDescriptorStorageBuffers, 16);
LIMIT_CHECK(maxPerStageDescriptorStorageImages, 64);
}
VkFormatProperties props = {};
vkGetPhysicalDeviceFormatProperties(phys, VK_FORMAT_A2B10G10R10_UINT_PACK32, &props);
if((props.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT) == 0)
{
Avail = "VK_FORMAT_A2B10G10R10_UINT_PACK32 not supported in texel buffers";
return;
}
if((props.bufferFeatures & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT) == 0)
{
Avail = "VK_FORMAT_A2B10G10R10_UINT_PACK32 not supported in texel buffers";
return;
}
vkGetPhysicalDeviceFormatProperties(phys, VK_FORMAT_A2B10G10R10_UNORM_PACK32, &props);
if((props.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT) == 0)
{
Avail = "VK_FORMAT_A2B10G10R10_UNORM_PACK32 not supported in texel buffers";
return;
}
if((props.bufferFeatures & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT) == 0)
{
Avail = "VK_FORMAT_A2B10G10R10_UNORM_PACK32 not supported in texel buffers";
return;
}
// enable features we can optionally test with.
VkPhysicalDeviceFeatures supported;
vkGetPhysicalDeviceFeatures(phys, &supported);
if(supported.shaderFloat64)
features.shaderFloat64 = VK_TRUE;
if(supported.shaderInt64)
features.shaderInt64 = VK_TRUE;
if(supported.shaderInt16)
features.shaderInt16 = VK_TRUE;
if(descIndexing)
{
static VkPhysicalDeviceDescriptorIndexingFeaturesEXT descIndexingFeatures = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT,
};
getPhysFeatures2(&descIndexingFeatures);
// enable descriptor indexing on arrays of all types
if(!descIndexingFeatures.runtimeDescriptorArray)
Avail = "Descriptor indexing feature 'runtimeDescriptorArray' not available";
else if(!descIndexingFeatures.shaderUniformTexelBufferArrayDynamicIndexing)
Avail =
"Descriptor indexing feature 'shaderUniformTexelBufferArrayDynamicIndexing' not "
"available";
else if(!descIndexingFeatures.shaderStorageTexelBufferArrayDynamicIndexing)
Avail =
"Descriptor indexing feature 'shaderStorageTexelBufferArrayDynamicIndexing' not "
"available";
else if(!descIndexingFeatures.shaderUniformBufferArrayNonUniformIndexing)
Avail =
"Descriptor indexing feature 'shaderUniformBufferArrayNonUniformIndexing' not "
"available";
else if(!descIndexingFeatures.shaderSampledImageArrayNonUniformIndexing)
Avail =
"Descriptor indexing feature 'shaderSampledImageArrayNonUniformIndexing' not available";
else if(!descIndexingFeatures.shaderStorageBufferArrayNonUniformIndexing)
Avail =
"Descriptor indexing feature 'shaderStorageBufferArrayNonUniformIndexing' not "
"available";
else if(!descIndexingFeatures.shaderStorageImageArrayNonUniformIndexing)
Avail =
"Descriptor indexing feature 'shaderStorageImageArrayNonUniformIndexing' not available";
else if(!descIndexingFeatures.shaderUniformTexelBufferArrayNonUniformIndexing)
Avail =
"Descriptor indexing feature 'shaderUniformTexelBufferArrayNonUniformIndexing' not "
"available";
else if(!descIndexingFeatures.shaderStorageTexelBufferArrayNonUniformIndexing)
Avail =
"Descriptor indexing feature 'shaderStorageTexelBufferArrayNonUniformIndexing' not "
"available";
devInfoNext = &descIndexingFeatures;
}
if(storage16)
{
// enable all available features
getPhysFeatures2(&storage16Features);
storage16Features.pNext = (void *)devInfoNext;
devInfoNext = &storage16Features;
}
if(storage8)
{
// enable all available features
getPhysFeatures2(&storage8Features);
storage8Features.pNext = (void *)devInfoNext;
devInfoNext = &storage8Features;
}
if(float16int8)
{
// enable all available features
getPhysFeatures2(&float16Int8Features);
float16Int8Features.pNext = (void *)devInfoNext;
devInfoNext = &float16Int8Features;
}
if(bda)
{
getPhysFeatures2(&bdaFeatures);
bdaFeatures.pNext = (void *)devInfoNext;
devInfoNext = &bdaFeatures;
}
if(csDerivatives)
{
getPhysFeatures2(&csDerivFeatures);
csDerivFeatures.pNext = (void *)devInfoNext;
devInfoNext = &csDerivFeatures;
}
if(intDotProduct)
{
getPhysFeatures2(&intDotProdFeatures);
intDotProdFeatures.pNext = (void *)devInfoNext;
devInfoNext = &intDotProdFeatures;
}
}
int main()
{
// initialise, create window, create context, etc
if(!Init())
return 3;
make_asm_tests();
const bool descIndexing = std::find(devExts.begin(), devExts.end(),
VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME) != devExts.end();
const bool storage16 = std::find(devExts.begin(), devExts.end(),
VK_KHR_16BIT_STORAGE_EXTENSION_NAME) != devExts.end();
const bool storage8 = std::find(devExts.begin(), devExts.end(),
VK_KHR_8BIT_STORAGE_EXTENSION_NAME) != devExts.end();
const bool float16int8 = std::find(devExts.begin(), devExts.end(),
VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME) != devExts.end();
const bool bda = std::find(devExts.begin(), devExts.end(),
VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME) != devExts.end();
const bool csDerivatives =
std::find(devExts.begin(), devExts.end(), VK_NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME) !=
devExts.end();
const bool intDotProduct =
std::find(devExts.begin(), devExts.end(),
VK_KHR_SHADER_INTEGER_DOT_PRODUCT_EXTENSION_NAME) != devExts.end();
bool subgroupSupport = true;
static VkPhysicalDeviceSubgroupProperties subProps = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES,
};
if(devVersion < VK_API_VERSION_1_1)
{
TEST_LOG("Disabled subgroup support: Vulkan device version isn't 1.1");
subgroupSupport = false;
}
if(subgroupSupport)
{
getPhysProperties2(&subProps);
if(subProps.subgroupSize < 16)
{
TEST_LOG("Disabled subgroup support: Subgroup size is less than 16");
subgroupSupport = false;
}
}
if(subgroupSupport)
{
// require at least a few ops so we only have a few conditional compilations
const VkSubgroupFeatureFlags requiredOps =
VK_SUBGROUP_FEATURE_BASIC_BIT | VK_SUBGROUP_FEATURE_VOTE_BIT |
VK_SUBGROUP_FEATURE_ARITHMETIC_BIT | VK_SUBGROUP_FEATURE_BALLOT_BIT;
if((subProps.supportedOperations & requiredOps) != requiredOps)
{
TEST_LOG("Disabled subgroup support: Missing ops support");
subgroupSupport = false;
}
}
if(subgroupSupport)
{
if((subProps.supportedStages & VK_SHADER_STAGE_COMPUTE_BIT) == 0)
{
TEST_LOG("Disabled subgroup support: Missing compute subgroup support");
subgroupSupport = false;
}
}
if(storage16)
TEST_LOG("Running tests on 16-bit storage");
if(storage8)
TEST_LOG("Running tests on 8-bit storage");
if(float16int8)
TEST_LOG("Running tests on half and int8 arithmetic");
if(bda)
TEST_LOG("Running tests on buffer device address");
if(csDerivatives)
{
if(subgroupSupport)
TEST_LOG("Running tests on compute shader derivatives + suubgroup");
else
TEST_LOG("Running tests on compute shader derivatives");
}
if(intDotProduct)
{
if(intDotProdFeatures.shaderIntegerDotProduct)
TEST_LOG("Running tests on integer dot product");
}
if(features.shaderFloat64)
TEST_LOG("Running tests on doubles");
if(features.shaderInt64)
TEST_LOG("Running tests on int64");
if(features.shaderInt16)
TEST_LOG("Running tests on int16 arithmetic");
pixel_glsl1.replace(pixel_glsl1.find("#define TEST_DESC_INDEXING"),
sizeof("#define TEST_DESC_INDEXING"),
fmt::format("#define TEST_DESC_INDEXING {}", descIndexing ? 1 : 0));
pixel_glsl2.replace(pixel_glsl2.find("#define TEST_DESC_INDEXING"),
sizeof("#define TEST_DESC_INDEXING"),
fmt::format("#define TEST_DESC_INDEXING {}", descIndexing ? 1 : 0));
size_t lastTest = pixel_glsl1.rfind("case ");
lastTest += sizeof("case ") - 1;
const uint32_t numGLSL1Tests = atoi(pixel_glsl1.c_str() + lastTest) + 1;
lastTest = pixel_glsl2.rfind("case ");
lastTest += sizeof("case ") - 1;
const uint32_t numGLSL2Tests = atoi(pixel_glsl2.c_str() + lastTest) + 1;
const uint32_t numASMTests = (uint32_t)asm_tests.size();
VkDescriptorSetLayout setlayout0 = createDescriptorSetLayout(vkh::DescriptorSetLayoutCreateInfo({
{0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_VERTEX_BIT},
{10, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{11, VK_DESCRIPTOR_TYPE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{12, VK_DESCRIPTOR_TYPE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{13, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{14, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{15, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{16, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{17, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{18, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{19, VK_DESCRIPTOR_TYPE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{20, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{21, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{22, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{30, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{31, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{32, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{33, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{34, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{35, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{36, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
}));
std::vector<VkDescriptorSetLayout> setLayouts = {setlayout0};
// this set layout has arrays of each type. We'll uniformly, dynamic-uniformly, and
// non-uniformly access each of these
VkDescriptorSetLayout setlayout1 = VK_NULL_HANDLE;
VkDescriptorSetLayout setlayout2 = VK_NULL_HANDLE;
if(descIndexing)
{
setlayout1 = createDescriptorSetLayout(vkh::DescriptorSetLayoutCreateInfo({
{1, VK_DESCRIPTOR_TYPE_SAMPLER, 14, VK_SHADER_STAGE_FRAGMENT_BIT},
{2, VK_DESCRIPTOR_TYPE_SAMPLER, 14, VK_SHADER_STAGE_FRAGMENT_BIT},
{3, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 14, VK_SHADER_STAGE_FRAGMENT_BIT},
{4, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 14, VK_SHADER_STAGE_FRAGMENT_BIT},
{5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 14, VK_SHADER_STAGE_FRAGMENT_BIT},
{6, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 14, VK_SHADER_STAGE_FRAGMENT_BIT},
{7, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 14, VK_SHADER_STAGE_FRAGMENT_BIT},
{8, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 14, VK_SHADER_STAGE_FRAGMENT_BIT},
{9, VK_DESCRIPTOR_TYPE_SAMPLER, 14, VK_SHADER_STAGE_FRAGMENT_BIT},
{20, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 14, VK_SHADER_STAGE_FRAGMENT_BIT},
{21, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 14, VK_SHADER_STAGE_FRAGMENT_BIT},
}));
setlayout2 = createDescriptorSetLayout(vkh::DescriptorSetLayoutCreateInfo({
{0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{2, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{3, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{4, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{5, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{6, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{7, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{8, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{9, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{10, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{11, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{12, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{13, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{14, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{15, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{16, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{17, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{18, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{19, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{20, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{21, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{22, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{23, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{24, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{25, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{26, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{27, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{28, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{29, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{30, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{31, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{32, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{33, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{34, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{35, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{36, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{37, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{38, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{39, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{40, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{41, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{42, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{43, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{44, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{45, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{46, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{47, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{48, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{49, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{50, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{51, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{52, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{53, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{54, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{55, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{56, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{57, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{58, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
{59, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
}));
setLayouts.push_back(setlayout1);
setLayouts.push_back(setlayout2);
}
VkPipelineLayout layout = createPipelineLayout(vkh::PipelineLayoutCreateInfo(
setLayouts, {
vkh::PushConstantRange(VK_SHADER_STAGE_FRAGMENT_BIT, 16, sizeof(PushData)),
}));
// calculate number of tests, wrapping each row at 256
uint32_t texWidth = AlignUp(std::max(std::max(numGLSL1Tests, numGLSL2Tests), numASMTests), 256U);
uint32_t texHeight = std::max(1U, texWidth / 256U);
texWidth /= texHeight;
// 4x4 for each test
texWidth *= 4;
texHeight *= 4;
AllocatedImage img(
this,
vkh::ImageCreateInfo(texWidth, texHeight, 0, VK_FORMAT_R32G32B32A32_SFLOAT,
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT),
VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_GPU_ONLY}));
VkImageView imgview = createImageView(
vkh::ImageViewCreateInfo(img.image, VK_IMAGE_VIEW_TYPE_2D, VK_FORMAT_R32G32B32A32_SFLOAT));
vkh::RenderPassCreator renderPassCreateInfo;
renderPassCreateInfo.attachments.push_back(
vkh::AttachmentDescription(VK_FORMAT_R32G32B32A32_SFLOAT, VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_GENERAL, VK_ATTACHMENT_LOAD_OP_CLEAR));
renderPassCreateInfo.addSubpass({VkAttachmentReference({0, VK_IMAGE_LAYOUT_GENERAL})});
VkRenderPass renderPass = createRenderPass(renderPassCreateInfo);
VkFramebuffer framebuffer =
createFramebuffer(vkh::FramebufferCreateInfo(renderPass, {imgview}, {texWidth, texHeight}));
vkh::GraphicsPipelineCreateInfo pipeCreateInfo;
pipeCreateInfo.layout = layout;
pipeCreateInfo.renderPass = renderPass;
pipeCreateInfo.vertexInputState.vertexBindingDescriptions = {vkh::vertexBind(0, ConstsA2V)};
pipeCreateInfo.vertexInputState.vertexAttributeDescriptions = {
vkh::vertexAttr(0, 0, ConstsA2V, pos), vkh::vertexAttr(1, 0, ConstsA2V, zero),
vkh::vertexAttr(2, 0, ConstsA2V, one), vkh::vertexAttr(3, 0, ConstsA2V, negone),
vkh::vertexAttr(4, 0, ConstsA2V, uv),
};
pipeCreateInfo.stages = {
CompileShaderModule(vertex, ShaderLang::glsl, ShaderStage::vert, "main"),
CompileShaderModule(pixel_glsl1, ShaderLang::glsl, ShaderStage::frag, "main"),
};
VkPipeline glslpipe1 = createGraphicsPipeline(pipeCreateInfo);
pipeCreateInfo.stages = {
CompileShaderModule(vertex2, ShaderLang::glsl, ShaderStage::vert, "main"),
CompileShaderModule(pixel_glsl2, ShaderLang::glsl, ShaderStage::frag, "main"),
};
VkPipeline glslpipe2 = createGraphicsPipeline(pipeCreateInfo);
SPIRVTarget target = SPIRVTarget::vulkan;
if(vk_version >= 0x11)
target = SPIRVTarget::vulkan11;
if(vk_version >= 0x12)
target = SPIRVTarget::vulkan12;
pipeCreateInfo.stages = {
CompileShaderModule(vertex, ShaderLang::glsl, ShaderStage::vert, "main"),
CompileShaderModule(make_pixel_asm(), ShaderLang::spvasm, ShaderStage::frag, "main", {},
target),
};
VkPipeline asmpipe = createGraphicsPipeline(pipeCreateInfo);
VkDescriptorSetLayout compSetlayout =
createDescriptorSetLayout(vkh::DescriptorSetLayoutCreateInfo({
{0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT},
{14, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_COMPUTE_BIT},
{19, VK_DESCRIPTOR_TYPE_SAMPLER, 1, VK_SHADER_STAGE_COMPUTE_BIT},
{32, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_COMPUTE_BIT},
}));
VkPipelineLayout compLayout = createPipelineLayout(vkh::PipelineLayoutCreateInfo(
{compSetlayout}, {vkh::PushConstantRange(VK_SHADER_STAGE_ALL, 0, 8)}));
std::map<std::string, std::string> macros;
int numCompTests = 0;
size_t pos = 0;
while(pos != std::string::npos)
{
pos = computeShaderDerivs.find("IsTest(", pos);
if(pos == std::string::npos)
break;
pos += sizeof("IsTest(") - 1;
numCompTests = std::max(numCompTests, atoi(computeShaderDerivs.c_str() + pos) + 1);
}
macros["COMP_TESTS"] = fmt::format("{}", numCompTests);
// Must be a multiple of 4 in X
// Must be a multiple of 2 in Y
macros["GROUP_SIZE_X"] = "8";
macros["GROUP_SIZE_Y"] = "4";
macros["GROUP_SIZE_Z"] = "1";
std::string comppipe_name[8];
VkPipeline compPipes[8];
uint32_t countCompPipes = 0;
if(csDerivatives)
{
macros["WORKGROUP_SUPPORT"] = "0";
macros["SUBGROUP_SUPPORT"] = "0";
macros["QUAD_LAYOUT"] = "derivative_group_quadsNV";
comppipe_name[countCompPipes] =
fmt::format("{}x{}x{} : {}", macros["GROUP_SIZE_X"], macros["GROUP_SIZE_Y"],
macros["GROUP_SIZE_Z"], macros["QUAD_LAYOUT"]);
compPipes[countCompPipes] = createComputePipeline(vkh::ComputePipelineCreateInfo(
compLayout, CompileShaderModule(computeShaderDerivs, ShaderLang::glsl, ShaderStage::comp,
"main", macros, SPIRVTarget::vulkan11)));
++countCompPipes;
macros["QUAD_LAYOUT"] = "derivative_group_LinearNV";
comppipe_name[countCompPipes] =
fmt::format("{}x{}x{} : {}", macros["GROUP_SIZE_X"], macros["GROUP_SIZE_Y"],
macros["GROUP_SIZE_Z"], macros["QUAD_LAYOUT"]);
compPipes[countCompPipes] = createComputePipeline(vkh::ComputePipelineCreateInfo(
compLayout, CompileShaderModule(computeShaderDerivs, ShaderLang::glsl, ShaderStage::comp,
"main", macros, SPIRVTarget::vulkan11)));
++countCompPipes;
// with workgroup
macros["WORKGROUP_SUPPORT"] = "1";
macros["QUAD_LAYOUT"] = "derivative_group_quadsNV";
comppipe_name[countCompPipes] =
fmt::format("{}x{}x{} : {} + Workgroup", macros["GROUP_SIZE_X"], macros["GROUP_SIZE_Y"],
macros["GROUP_SIZE_Z"], macros["QUAD_LAYOUT"]);
compPipes[countCompPipes] = createComputePipeline(vkh::ComputePipelineCreateInfo(
compLayout, CompileShaderModule(computeShaderDerivs, ShaderLang::glsl, ShaderStage::comp,
"main", macros, SPIRVTarget::vulkan11)));
++countCompPipes;
macros["QUAD_LAYOUT"] = "derivative_group_LinearNV";
comppipe_name[countCompPipes] =
fmt::format("{}x{}x{} : {} + Workgroup", macros["GROUP_SIZE_X"], macros["GROUP_SIZE_Y"],
macros["GROUP_SIZE_Z"], macros["QUAD_LAYOUT"]);
compPipes[countCompPipes] = createComputePipeline(vkh::ComputePipelineCreateInfo(
compLayout, CompileShaderModule(computeShaderDerivs, ShaderLang::glsl, ShaderStage::comp,
"main", macros, SPIRVTarget::vulkan11)));
++countCompPipes;
if(subgroupSupport)
{
// with subgroup
macros["WORKGROUP_SUPPORT"] = "0";
macros["SUBGROUP_SUPPORT"] = "1";
macros["QUAD_LAYOUT"] = "derivative_group_quadsNV";
comppipe_name[countCompPipes] =
fmt::format("{}x{}x{} : {} + Subgroup", macros["GROUP_SIZE_X"], macros["GROUP_SIZE_Y"],
macros["GROUP_SIZE_Z"], macros["QUAD_LAYOUT"]);
compPipes[countCompPipes] = createComputePipeline(vkh::ComputePipelineCreateInfo(
compLayout, CompileShaderModule(computeShaderDerivs, ShaderLang::glsl, ShaderStage::comp,
"main", macros, SPIRVTarget::vulkan11)));
++countCompPipes;
macros["QUAD_LAYOUT"] = "derivative_group_LinearNV";
comppipe_name[countCompPipes] =
fmt::format("{}x{}x{} : {} + Subgroup", macros["GROUP_SIZE_X"], macros["GROUP_SIZE_Y"],
macros["GROUP_SIZE_Z"], macros["QUAD_LAYOUT"]);
compPipes[countCompPipes] = createComputePipeline(vkh::ComputePipelineCreateInfo(
compLayout, CompileShaderModule(computeShaderDerivs, ShaderLang::glsl, ShaderStage::comp,
"main", macros, SPIRVTarget::vulkan11)));
++countCompPipes;
// with subgroup and workgroup
macros["WORKGROUP_SUPPORT"] = "1";
macros["SUBGROUP_SUPPORT"] = "1";
macros["QUAD_LAYOUT"] = "derivative_group_quadsNV";
comppipe_name[countCompPipes] =
fmt::format("{}x{}x{} : {} + Subgroup + Workgroup", macros["GROUP_SIZE_X"],
macros["GROUP_SIZE_Y"], macros["GROUP_SIZE_Z"], macros["QUAD_LAYOUT"]);
compPipes[countCompPipes] = createComputePipeline(vkh::ComputePipelineCreateInfo(
compLayout, CompileShaderModule(computeShaderDerivs, ShaderLang::glsl, ShaderStage::comp,
"main", macros, SPIRVTarget::vulkan11)));
++countCompPipes;
macros["QUAD_LAYOUT"] = "derivative_group_LinearNV";
comppipe_name[countCompPipes] =
fmt::format("{}x{}x{} : {} + Subgroup + Workgroup", macros["GROUP_SIZE_X"],
macros["GROUP_SIZE_Y"], macros["GROUP_SIZE_Z"], macros["QUAD_LAYOUT"]);
compPipes[countCompPipes] = createComputePipeline(vkh::ComputePipelineCreateInfo(
compLayout, CompileShaderModule(computeShaderDerivs, ShaderLang::glsl, ShaderStage::comp,
"main", macros, SPIRVTarget::vulkan11)));
++countCompPipes;
}
}
AllocatedBuffer bufout(
this,
vkh::BufferCreateInfo(sizeof(Vec4f) * 1024 * numCompTests,
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT),
VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_CPU_TO_GPU}));
setName(bufout.buffer, "bufout");
VkDescriptorSet compSet = allocateDescriptorSet(compSetlayout);
float triWidth = 8.0f / float(texWidth);
float triHeight = 8.0f / float(texHeight);
ConstsA2V triangle[] = {
{Vec4f(-1.0f, -1.0f, triWidth, triHeight), 0.0f, 1.0f, -1.0f, Vec2f(0.0f, 0.0f)},
{Vec4f(-1.0f + triWidth, -1.0f, triWidth, triHeight), 0.0f, 1.0f, -1.0f, Vec2f(1.0f, 0.0f)},
{Vec4f(-1.0f, -1.0f + triHeight, triWidth, triHeight), 0.0f, 1.0f, -1.0f, Vec2f(0.0f, 1.0f)},
};
AllocatedBuffer vb(this,
vkh::BufferCreateInfo(sizeof(triangle), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
VK_BUFFER_USAGE_TRANSFER_DST_BIT),
VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_CPU_TO_GPU}));
vb.upload(triangle);
Texture rgba8;
LoadXPM(SmileyTexture, rgba8);
AllocatedImage queryTest(this,
vkh::ImageCreateInfo(183, 347, 0, VK_FORMAT_R8G8B8A8_UNORM,
VK_IMAGE_USAGE_SAMPLED_BIT, 4, 3),
VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_GPU_ONLY}));
VkImageView queryTestView = createImageView(vkh::ImageViewCreateInfo(
queryTest.image, VK_IMAGE_VIEW_TYPE_2D_ARRAY, VK_FORMAT_R8G8B8A8_UNORM));
AllocatedImage queryTestMS(
this,
vkh::ImageCreateInfo(183, 347, 0, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT, 1,
5, VK_SAMPLE_COUNT_4_BIT),
VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_GPU_ONLY}));
VkImageView queryTestMSView = createImageView(vkh::ImageViewCreateInfo(
queryTestMS.image, VK_IMAGE_VIEW_TYPE_2D_ARRAY, VK_FORMAT_R8G8B8A8_UNORM));
AllocatedImage smiley(
this,
vkh::ImageCreateInfo(rgba8.width, rgba8.height, 0, VK_FORMAT_R8G8B8A8_UNORM,
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT),
VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_GPU_ONLY}));
VkImageView smileyview = createImageView(
vkh::ImageViewCreateInfo(smiley.image, VK_IMAGE_VIEW_TYPE_2D, VK_FORMAT_R8G8B8A8_UNORM));
AllocatedBuffer uploadBuf(this,
vkh::BufferCreateInfo(rgba8.data.size() * sizeof(uint32_t),
VK_BUFFER_USAGE_TRANSFER_SRC_BIT),
VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_CPU_TO_GPU}));
AllocatedImage shadowimg(this,
vkh::ImageCreateInfo(16, 16, 0, VK_FORMAT_D32_SFLOAT,
VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT |
VK_IMAGE_USAGE_SAMPLED_BIT),
VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_GPU_ONLY}));
VkImageView shadowview = createImageView(
vkh::ImageViewCreateInfo(shadowimg.image, VK_IMAGE_VIEW_TYPE_2D, VK_FORMAT_D32_SFLOAT, {},
vkh::ImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT)));
uploadBuf.upload(rgba8.data.data(), rgba8.data.size() * sizeof(uint32_t));
std::vector<byte> typeData;
typeData.resize(sizeof(Vec4f) * 16 * 16 * 32 * 3);
uint32_t typeOffset[] = {
// float data
sizeof(Vec4f) * 16 * 16 * 32 * 0,
// uint data
sizeof(Vec4f) * 16 * 16 * 32 * 1,
// int data
sizeof(Vec4f) * 16 * 16 * 32 * 2,
};
for(size_t typeVariant = 0; typeVariant < 3; typeVariant++)
{
byte *dst = typeData.data() + typeOffset[typeVariant];
union
{
float f[4];
int i[4];
} rnd;
memset(&rnd, 0, sizeof(rnd));
for(size_t x = 0; x < 16; x++)
{
for(size_t y = 0; y < 16; y++)
{
for(size_t z = 0; z < 32; z++)
{
if(typeVariant == 0)
{
rnd.f[0] = RANDF(-10.0f, 10.0f);
rnd.f[1] = RANDF(-10.0f, 10.0f);
rnd.f[2] = RANDF(-10.0f, 10.0f);
rnd.f[3] = RANDF(-10.0f, 10.0f);
}
else if(typeVariant == 1)
{
rnd.i[0] = (int32_t)RANDF(100.0f, 500.0f);
rnd.i[1] = (int32_t)RANDF(100.0f, 500.0f);
rnd.i[2] = (int32_t)RANDF(100.0f, 500.0f);
rnd.i[3] = (int32_t)RANDF(100.0f, 500.0f);
}
else if(typeVariant == 2)
{
rnd.i[0] = (int32_t)RANDF(-200.0f, 200.0f);
rnd.i[1] = (int32_t)RANDF(-200.0f, 200.0f);
rnd.i[2] = (int32_t)RANDF(-200.0f, 200.0f);
rnd.i[3] = (int32_t)RANDF(-200.0f, 200.0f);
}
memcpy(dst, &rnd.f, sizeof(Vec4f));
}
}
}
}
AllocatedBuffer typeDataBuf(
this, vkh::BufferCreateInfo(typeData.size(), VK_BUFFER_USAGE_TRANSFER_SRC_BIT),
VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_CPU_TO_GPU}));
typeDataBuf.upload(typeData.data(), typeData.size());
AllocatedImage randomcube(
this,
vkh::ImageCreateInfo(rgba8.width, rgba8.height, 0, VK_FORMAT_R8G8B8A8_UNORM,
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, 1, 6,
VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT),
VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_GPU_ONLY}));
VkImageView randomcubeview = createImageView(vkh::ImageViewCreateInfo(
randomcube.image, VK_IMAGE_VIEW_TYPE_CUBE, VK_FORMAT_R8G8B8A8_UNORM));
{
VkCommandBuffer cmd = GetCommandBuffer();
vkBeginCommandBuffer(cmd, vkh::CommandBufferBeginInfo());
vkh::cmdPipelineBarrier(
cmd,
{
vkh::ImageMemoryBarrier(0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, smiley.image),
vkh::ImageMemoryBarrier(0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, randomcube.image),
vkh::ImageMemoryBarrier(0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_GENERAL, queryTest.image),
vkh::ImageMemoryBarrier(0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_GENERAL, queryTestMS.image),
});
VkBufferImageCopy copy = {};
copy.imageExtent = {rgba8.width, rgba8.height, 1};
copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
copy.imageSubresource.layerCount = 1;
vkCmdCopyBufferToImage(cmd, uploadBuf.buffer, smiley.image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &copy);
for(uint32_t i = 0; i < 6; i++)
{
copy.imageSubresource.baseArrayLayer = i;
vkCmdCopyBufferToImage(cmd, typeDataBuf.buffer, randomcube.image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &copy);
}
vkh::cmdPipelineBarrier(
cmd,
{
vkh::ImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, smiley.image),
vkh::ImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, randomcube.image),
});
vkEndCommandBuffer(cmd);
Submit(99, 99, {cmd});
vkDeviceWaitIdle(device);
}
VkSampler pointsampler = createSampler(vkh::SamplerCreateInfo(VK_FILTER_NEAREST));
VkSampler linearsampler = createSampler(vkh::SamplerCreateInfo(VK_FILTER_LINEAR));
VkSampler mipsampler = createSampler(vkh::SamplerCreateInfo(VK_FILTER_LINEAR));
VkSampler shadowsampler = createSampler(vkh::SamplerCreateInfo(
VK_FILTER_LINEAR, VK_SAMPLER_ADDRESS_MODE_REPEAT, 0.0f,
VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, 0.0f, 0.0f, 0.0f, VK_COMPARE_OP_LESS_OR_EQUAL));
VkDescriptorSet descset0 = allocateDescriptorSet(setlayout0);
VkDescriptorSet descset1 = VK_NULL_HANDLE;
VkDescriptorSet descset2 = VK_NULL_HANDLE;
if(descIndexing)
{
descset1 = allocateDescriptorSet(setlayout1);
descset2 = allocateDescriptorSet(setlayout2);
}
vkh::updateDescriptorSets(
device,
{
vkh::WriteDescriptorSet(compSet, 0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
{vkh::DescriptorBufferInfo(bufout.buffer)}),
vkh::WriteDescriptorSet(
compSet, 14, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
{vkh::DescriptorImageInfo(smileyview, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
linearsampler)}),
vkh::WriteDescriptorSet(
compSet, 19, VK_DESCRIPTOR_TYPE_SAMPLER,
{vkh::DescriptorImageInfo(VK_NULL_HANDLE, VK_IMAGE_LAYOUT_UNDEFINED, shadowsampler)}),
vkh::WriteDescriptorSet(
compSet, 32, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
{vkh::DescriptorImageInfo(shadowview, VK_IMAGE_LAYOUT_GENERAL, VK_NULL_HANDLE)}),
});
Vec4f cbufferdata[64] = {};
AllocatedBuffer cb(
this,
vkh::BufferCreateInfo(sizeof(cbufferdata) * 2, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT |
VK_BUFFER_USAGE_TRANSFER_DST_BIT),
VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_CPU_TO_GPU}));
cbufferdata[1] = Vec4f(1.1f, 2.2f, 3.3f, 4.4f);
cbufferdata[2] = Vec4f(5.5f, 6.6f, 7.7f, 8.8f);
cbufferdata[3] = Vec4f(std::numeric_limits<float>::quiet_NaN());
cbufferdata[4] = Vec4f(9.9f, 9.99f, 9.999f, 9.999f);
cbufferdata[6] = Vec4f(100.0f, 200.0f, 300.0f, 400.0f);
// unorm2PackSource
cbufferdata[7] = Vec4f(99.0f, 28099.0f / 65535.0f, 0.0f, 0.0f);
// snorm2PackSource
cbufferdata[8] = Vec4f(99.0f, -28099.0f / 32767.0f, 0.0f, 0.0f);
// unorm4PackSource
cbufferdata[9] = Vec4f(99.0f, 28.0f / 255.0f, 99.0f / 255.0f, 182.0f / 255.0f);
// snorm4PackSource
cbufferdata[10] = Vec4f(99.0f, -28.0f / 127.0f, 99.0f / 127.0f, -102.0f / 127.0f);
// halfPackSource - we pick exact half values to avoid rounding problems
cbufferdata[11] = Vec4f(98.125f, 76.375f, 54.5625f, 32.78125f);
uint32_t index = 4;
memcpy(&cbufferdata[1], &index, sizeof(index));
Vec4u unpack = {};
// unormUnpackSource
unpack.x = 0xf0dd103c;
// snormUnpackSource
unpack.y = 0xf0dd103c;
// halfUnpackSource
unpack.z = (uint32_t(MakeHalf(81.5f)) << 16) | MakeHalf(101.03f);
// unpack sources
memcpy(&cbufferdata[12], &unpack, sizeof(unpack));
double unpackDouble = 3.1415926535;
memcpy(&cbufferdata[13].x, &unpackDouble, sizeof(unpackDouble));
memcpy(&cbufferdata[14].z, &unpackDouble, sizeof(unpackDouble));
// move to account for offset
memmove(&cbufferdata[16], &cbufferdata[0], sizeof(Vec4f) * 16);
memset(&cbufferdata[0], 0, sizeof(Vec4f) * 16);
cb.upload(cbufferdata);
AllocatedBuffer texbuffer(
this,
vkh::BufferCreateInfo(sizeof(cbufferdata), VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT |
VK_BUFFER_USAGE_TRANSFER_DST_BIT),
VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_CPU_TO_GPU}));
texbuffer.upload(cbufferdata);
AllocatedBuffer store_buffer(
this,
vkh::BufferCreateInfo(1024 * sizeof(Vec4f), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
VK_BUFFER_USAGE_TRANSFER_DST_BIT),
VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_GPU_ONLY}));
AllocatedBuffer atomic_buffer(
this,
vkh::BufferCreateInfo(texWidth * texHeight * sizeof(Vec4f),
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT),
VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_GPU_ONLY}));
AllocatedBuffer store_texbuffer(
this,
vkh::BufferCreateInfo(1024 * sizeof(Vec4f), VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT |
VK_BUFFER_USAGE_TRANSFER_DST_BIT),
VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_GPU_ONLY}));
AllocatedBuffer texbuffer_1010102unorm(
this,
vkh::BufferCreateInfo(1024 * sizeof(uint32_t), VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT |
VK_BUFFER_USAGE_TRANSFER_DST_BIT),
VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_CPU_TO_GPU}));
AllocatedBuffer store_texbuffer_1010102unorm(
this,
vkh::BufferCreateInfo(1024 * sizeof(uint32_t), VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT |
VK_BUFFER_USAGE_TRANSFER_DST_BIT),
VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_GPU_ONLY}));
uint32_t unormdata[64] = {};
memset(unormdata, 0x42, sizeof(unormdata));
texbuffer_1010102unorm.upload(unormdata);
AllocatedBuffer texbuffer_1010102uint(
this,
vkh::BufferCreateInfo(1024 * sizeof(uint32_t), VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT |
VK_BUFFER_USAGE_TRANSFER_DST_BIT),
VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_CPU_TO_GPU}));
texbuffer_1010102uint.upload(unormdata);
AllocatedBuffer store_texbuffer_1010102uint(
this,
vkh::BufferCreateInfo(1024 * sizeof(uint32_t), VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT |
VK_BUFFER_USAGE_TRANSFER_DST_BIT),
VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_GPU_ONLY}));
VkBuffer bda_data_buffer = VK_NULL_HANDLE;
VkDeviceMemory bda_deviceMem = VK_NULL_HANDLE;
byte *bda_base_gpuptr = NULL;
if(bda)
{
vkh::BufferCreateInfo bda_buffer_info(sizeof(BDA_Data),
VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR);
VkMemoryAllocateInfo memAllocInfo = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO};
VkMemoryAllocateFlagsInfo memAllocFlags = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO};
memAllocFlags.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR;
memAllocInfo.pNext = &memAllocFlags;
const VkPhysicalDeviceMemoryProperties *memProps = NULL;
vmaGetMemoryProperties(allocator, &memProps);
vkCreateBuffer(device, bda_buffer_info, NULL, &bda_data_buffer);
VkMemoryRequirements mrq;
vkGetBufferMemoryRequirements(device, bda_data_buffer, &mrq);
memAllocInfo.allocationSize = mrq.size;
for(uint32_t i = 0; i < memProps->memoryTypeCount; i++)
{
if((mrq.memoryTypeBits & (1u << i)) &&
(memProps->memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT))
{
memAllocInfo.memoryTypeIndex = i;
break;
}
}
vkAllocateMemory(device, &memAllocInfo, NULL, &bda_deviceMem);
vkBindBufferMemory(device, bda_data_buffer, bda_deviceMem, 0);
VkBufferDeviceAddressInfoKHR bda_info = {VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_KHR};
bda_info.buffer = bda_data_buffer;
VkDeviceAddress bda_Addr = vkGetBufferDeviceAddressKHR(device, &bda_info);
bda_base_gpuptr = (byte *)bda_Addr; // not a valid cpu pointer
byte *bda_base_cpuptr = NULL;
vkMapMemory(device, bda_deviceMem, 0, mrq.size, 0, (void **)&bda_base_cpuptr);
BDA_Data *bda_data_cpu = (BDA_Data *)bda_base_cpuptr;
bda_data_cpu->f32[0] = 0.1f;
bda_data_cpu->f32[1] = 0.2f;
bda_data_cpu->f32[2] = 0.3f;
bda_data_cpu->f32[3] = 0.8f;
bda_data_cpu->f32[4] = 0.3f;
bda_data_cpu->f32[5] = 0.2f;
bda_data_cpu->f32[6] = 0.1f;
bda_data_cpu->f32[7] = 0.9f;
}
AllocatedImage store_image(
this,
vkh::ImageCreateInfo(128, 128, 0, VK_FORMAT_R32G32B32A32_SFLOAT,
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT),
VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_GPU_ONLY}));
VkImageView store_view = createImageView(vkh::ImageViewCreateInfo(
store_image.image, VK_IMAGE_VIEW_TYPE_2D, VK_FORMAT_R32G32B32A32_SFLOAT));
AllocatedImage atomic_image(
this,
vkh::ImageCreateInfo(texWidth, texHeight, 0, VK_FORMAT_R32_UINT,
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT),
VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_GPU_ONLY}));
VkImageView atomic_view = createImageView(
vkh::ImageViewCreateInfo(atomic_image.image, VK_IMAGE_VIEW_TYPE_2D, VK_FORMAT_R32_UINT));
VkBufferView bufview =
createBufferView(vkh::BufferViewCreateInfo(texbuffer.buffer, VK_FORMAT_R32G32B32A32_SFLOAT));
VkBufferView store_bufview = createBufferView(
vkh::BufferViewCreateInfo(store_texbuffer.buffer, VK_FORMAT_R32G32B32A32_SFLOAT));
VkBufferView bufview_1010102unorm = createBufferView(vkh::BufferViewCreateInfo(
texbuffer_1010102unorm.buffer, VK_FORMAT_A2B10G10R10_UNORM_PACK32, 96));
VkBufferView store_bufview_1010102unorm = createBufferView(vkh::BufferViewCreateInfo(
store_texbuffer_1010102unorm.buffer, VK_FORMAT_A2B10G10R10_UNORM_PACK32, 96));
VkBufferView bufview_1010102uint = createBufferView(vkh::BufferViewCreateInfo(
texbuffer_1010102uint.buffer, VK_FORMAT_A2B10G10R10_UINT_PACK32, 96));
VkBufferView store_bufview_1010102uint = createBufferView(vkh::BufferViewCreateInfo(
store_texbuffer_1010102uint.buffer, VK_FORMAT_A2B10G10R10_UINT_PACK32, 96));
setName(pointsampler, "pointsampler");
setName(linearsampler, "linearsampler");
setName(mipsampler, "mipsampler");
setName(queryTest.image, "queryTest");
setName(queryTestMS.image, "queryTestMS");
setName(smiley.image, "smiley");
setName(texbuffer.buffer, "texbuffer");
setName(store_buffer.buffer, "store_buffer");
setName(atomic_buffer.buffer, "atomic_buffer");
setName(store_texbuffer.buffer, "store_texbuffer");
setName(store_image.image, "store_image");
setName(atomic_image.image, "atomic_image");
setName(bufview_1010102unorm, "bufview_1010102unorm");
setName(store_bufview_1010102unorm, "store_texbuffer_1010102unorm");
setName(bufview_1010102uint, "bufview_1010102uint");
setName(store_bufview_1010102uint, "store_bufview_1010102uint");
AllocatedImage storezoo_u2D(
this,
vkh::ImageCreateInfo(16, 16, 0, VK_FORMAT_R32G32B32A32_UINT,
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT),
VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_GPU_ONLY}));
VkImageView storezoo_u2D_view = createImageView(vkh::ImageViewCreateInfo(
storezoo_u2D.image, VK_IMAGE_VIEW_TYPE_2D, VK_FORMAT_R32G32B32A32_UINT));
setName(storezoo_u2D.image, "storezoo_u2D");
vkh::updateDescriptorSets(
device,
{
vkh::WriteDescriptorSet(descset0, 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
{vkh::DescriptorBufferInfo(cb.buffer, 0, sizeof(cbufferdata))}),
vkh::WriteDescriptorSet(descset0, 10, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
{vkh::DescriptorBufferInfo(cb.buffer, 0, sizeof(cbufferdata))}),
vkh::WriteDescriptorSet(
descset0, 11, VK_DESCRIPTOR_TYPE_SAMPLER,
{vkh::DescriptorImageInfo(VK_NULL_HANDLE, VK_IMAGE_LAYOUT_UNDEFINED, pointsampler)}),
vkh::WriteDescriptorSet(
descset0, 12, VK_DESCRIPTOR_TYPE_SAMPLER,
{vkh::DescriptorImageInfo(VK_NULL_HANDLE, VK_IMAGE_LAYOUT_UNDEFINED, linearsampler)}),
vkh::WriteDescriptorSet(
descset0, 13, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
{vkh::DescriptorImageInfo(smileyview, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VK_NULL_HANDLE)}),
vkh::WriteDescriptorSet(
descset0, 14, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
{vkh::DescriptorImageInfo(smileyview, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
linearsampler)}),
vkh::WriteDescriptorSet(descset0, 15, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
{vkh::DescriptorBufferInfo(store_buffer.buffer)}),
vkh::WriteDescriptorSet(
descset0, 16, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
{vkh::DescriptorImageInfo(store_view, VK_IMAGE_LAYOUT_GENERAL, VK_NULL_HANDLE)}),
vkh::WriteDescriptorSet(descset0, 17, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, {bufview}),
vkh::WriteDescriptorSet(descset0, 18, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
{store_bufview}),
vkh::WriteDescriptorSet(
descset0, 19, VK_DESCRIPTOR_TYPE_SAMPLER,
{vkh::DescriptorImageInfo(VK_NULL_HANDLE, VK_IMAGE_LAYOUT_UNDEFINED, shadowsampler)}),
vkh::WriteDescriptorSet(
descset0, 20, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
{vkh::DescriptorImageInfo(randomcubeview, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
linearsampler)}),
vkh::WriteDescriptorSet(descset0, 21, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
{vkh::DescriptorBufferInfo(atomic_buffer.buffer)}),
vkh::WriteDescriptorSet(
descset0, 22, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
{vkh::DescriptorImageInfo(atomic_view, VK_IMAGE_LAYOUT_GENERAL, VK_NULL_HANDLE)}),
vkh::WriteDescriptorSet(
descset0, 30, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
{vkh::DescriptorImageInfo(queryTestView, VK_IMAGE_LAYOUT_GENERAL, mipsampler)}),
vkh::WriteDescriptorSet(
descset0, 31, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
{vkh::DescriptorImageInfo(queryTestMSView, VK_IMAGE_LAYOUT_GENERAL, mipsampler)}),
vkh::WriteDescriptorSet(
descset0, 32, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
{vkh::DescriptorImageInfo(shadowview, VK_IMAGE_LAYOUT_GENERAL, VK_NULL_HANDLE)}),
vkh::WriteDescriptorSet(descset0, 33, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
{bufview_1010102unorm}),
vkh::WriteDescriptorSet(descset0, 34, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
{store_bufview_1010102unorm}),
vkh::WriteDescriptorSet(descset0, 35, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
{bufview_1010102uint}),
vkh::WriteDescriptorSet(descset0, 36, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
{store_bufview_1010102uint}),
});
if(descIndexing)
{
vkh::updateDescriptorSets(
device, {
vkh::WriteDescriptorSet(
descset2, 41, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
{vkh::DescriptorImageInfo(storezoo_u2D_view, VK_IMAGE_LAYOUT_GENERAL,
VK_NULL_HANDLE)}),
});
for(uint32_t i = 0; i < 14; i++)
{
vkh::updateDescriptorSets(
device,
{
vkh::WriteDescriptorSet(descset1, 1, i, VK_DESCRIPTOR_TYPE_SAMPLER,
{vkh::DescriptorImageInfo(
VK_NULL_HANDLE, VK_IMAGE_LAYOUT_UNDEFINED, pointsampler)}),
vkh::WriteDescriptorSet(
descset1, 2, i, VK_DESCRIPTOR_TYPE_SAMPLER,
{vkh::DescriptorImageInfo(VK_NULL_HANDLE, VK_IMAGE_LAYOUT_UNDEFINED,
linearsampler)}),
vkh::WriteDescriptorSet(
descset1, 3, i, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
{vkh::DescriptorImageInfo(shadowview, VK_IMAGE_LAYOUT_GENERAL, VK_NULL_HANDLE)}),
vkh::WriteDescriptorSet(
descset1, 4, i, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
{vkh::DescriptorImageInfo(smileyview, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
linearsampler)}),
vkh::WriteDescriptorSet(descset1, 5, i, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
{vkh::DescriptorBufferInfo(store_buffer.buffer)}),
vkh::WriteDescriptorSet(
descset1, 6, i, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
{vkh::DescriptorImageInfo(store_view, VK_IMAGE_LAYOUT_GENERAL, VK_NULL_HANDLE)}),
vkh::WriteDescriptorSet(descset1, 7, i, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
{bufview}),
vkh::WriteDescriptorSet(descset1, 8, i, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
{store_bufview}),
vkh::WriteDescriptorSet(
descset1, 9, i, VK_DESCRIPTOR_TYPE_SAMPLER,
{vkh::DescriptorImageInfo(VK_NULL_HANDLE, VK_IMAGE_LAYOUT_UNDEFINED,
shadowsampler)}),
vkh::WriteDescriptorSet(
descset1, 20, i, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
{vkh::DescriptorImageInfo(queryTestView, VK_IMAGE_LAYOUT_GENERAL, mipsampler)}),
vkh::WriteDescriptorSet(
descset1, 21, i, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
{vkh::DescriptorImageInfo(queryTestMSView, VK_IMAGE_LAYOUT_GENERAL, mipsampler)}),
});
}
}
while(Running())
{
VkCommandBuffer cmd = GetCommandBuffer();
vkBeginCommandBuffer(cmd, vkh::CommandBufferBeginInfo());
VkImage swapimg =
StartUsingBackbuffer(cmd, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL);
vkCmdClearColorImage(cmd, swapimg, VK_IMAGE_LAYOUT_GENERAL,
vkh::ClearColorValue(0.2f, 0.2f, 0.2f, 1.0f), 1,
vkh::ImageSubresourceRange());
vkh::cmdPipelineBarrier(
cmd,
{
vkh::ImageMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_GENERAL, store_image.image),
vkh::ImageMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_GENERAL, atomic_image.image),
vkh::ImageMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_GENERAL, storezoo_u2D.image),
vkh::ImageMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_GENERAL, shadowimg.image,
vkh::ImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT)),
},
{
vkh::BufferMemoryBarrier(VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT, store_buffer.buffer),
vkh::BufferMemoryBarrier(VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT, atomic_buffer.buffer),
vkh::BufferMemoryBarrier(VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT, store_texbuffer.buffer),
vkh::BufferMemoryBarrier(VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT,
store_texbuffer_1010102uint.buffer),
vkh::BufferMemoryBarrier(VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT,
store_texbuffer_1010102unorm.buffer),
});
vkCmdClearDepthStencilImage(cmd, shadowimg.image, VK_IMAGE_LAYOUT_GENERAL,
vkh::ClearDepthStencilValue({0.5f, 0}), 1,
vkh::ImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT));
vkCmdClearColorImage(cmd, store_image.image, VK_IMAGE_LAYOUT_GENERAL,
vkh::ClearColorValue(6.66f, 6.66f, 6.66f, 6.66f), 1,
vkh::ImageSubresourceRange());
vkCmdClearColorImage(cmd, atomic_image.image, VK_IMAGE_LAYOUT_GENERAL,
vkh::ClearColorValue(0x42424242U, 0x42424242U, 0x42424242U, 0x42424242U),
1, vkh::ImageSubresourceRange());
vkCmdClearColorImage(cmd, storezoo_u2D.image, VK_IMAGE_LAYOUT_GENERAL,
vkh::ClearColorValue(8U, 18U, 28U, 38U), 1, vkh::ImageSubresourceRange());
vkCmdFillBuffer(cmd, store_buffer.buffer, 0, VK_WHOLE_SIZE, 0x42424242);
vkCmdFillBuffer(cmd, atomic_buffer.buffer, 0, VK_WHOLE_SIZE, 0x42424242);
const float val = 1.234f;
vkCmdFillBuffer(cmd, store_texbuffer.buffer, 0, 128, *(uint32_t *)&val);
vkCmdFillBuffer(cmd, store_texbuffer.buffer, 128, VK_WHOLE_SIZE, 0);
vkCmdFillBuffer(cmd, store_texbuffer_1010102uint.buffer, 0, 104, 0x42424242);
vkCmdFillBuffer(cmd, store_texbuffer_1010102uint.buffer, 104, VK_WHOLE_SIZE, 0);
vkCmdFillBuffer(cmd, store_texbuffer_1010102unorm.buffer, 0, 104, 0x42424242);
vkCmdFillBuffer(cmd, store_texbuffer_1010102unorm.buffer, 104, VK_WHOLE_SIZE, 0);
vkh::cmdPipelineBarrier(
cmd,
{
vkh::ImageMemoryBarrier(
VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT,
VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL, store_image.image),
vkh::ImageMemoryBarrier(
VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT,
VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL, atomic_image.image),
vkh::ImageMemoryBarrier(
VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT,
VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL, storezoo_u2D.image),
},
{
vkh::BufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT,
VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
store_buffer.buffer),
vkh::BufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT,
VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
atomic_buffer.buffer),
vkh::BufferMemoryBarrier(VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT, store_texbuffer.buffer),
});
VkViewport v = {};
v.maxDepth = 1.0f;
v.width = (float)texWidth;
v.height = (float)texHeight;
VkRect2D s = {};
s.extent.width = texWidth;
s.extent.height = texHeight;
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, glslpipe1);
vkCmdSetViewport(cmd, 0, 1, &v);
vkCmdSetScissor(cmd, 0, 1, &s);
vkh::cmdBindVertexBuffers(cmd, 0, {vb.buffer}, {0});
BDA_Data *bda_gpuptr = (BDA_Data *)bda_base_gpuptr;
PushData pushData;
pushData.push = Vec4i(101, 103, 107, 109);
pushData.bda_uvec2 = *(Vec2u *)(&bda_gpuptr);
pushData.bda_hi = (uint64_t)bda_gpuptr >> 32;
pushData.bda_lo = (uint64_t)bda_gpuptr & 0xFFFFFFFF;
pushData.bda_u64 = *(uint64_t *)(&bda_gpuptr);
std::vector<VkDescriptorSet> descSets = {descset0};
if(descIndexing)
{
descSets.push_back(descset1);
descSets.push_back(descset2);
}
vkh::cmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descSets,
{0, sizeof(Vec4f) * 16});
vkCmdPushConstants(cmd, layout, VK_SHADER_STAGE_FRAGMENT_BIT, 16, sizeof(PushData), &pushData);
vkCmdBeginRenderPass(cmd,
vkh::RenderPassBeginInfo(renderPass, framebuffer, s,
{vkh::ClearValue(0.0f, 0.0f, 0.0f, 0.0f)}),
VK_SUBPASS_CONTENTS_INLINE);
pushMarker(cmd, "GLSL1 tests");
uint32_t numTests = numGLSL1Tests;
uint32_t offset = 0;
// loop drawing 256 tests at a time
while(numTests > 0)
{
uint32_t num = std::min(numTests, 256U);
vkCmdDraw(cmd, 3, num, 0, offset);
offset += num;
numTests -= num;
}
popMarker(cmd);
vkCmdEndRenderPass(cmd);
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, asmpipe);
vkCmdBeginRenderPass(cmd,
vkh::RenderPassBeginInfo(renderPass, framebuffer, s,
{vkh::ClearValue(0.0f, 0.0f, 0.0f, 0.0f)}),
VK_SUBPASS_CONTENTS_INLINE);
pushMarker(cmd, "ASM tests");
numTests = numASMTests;
offset = 0;
// loop drawing 256 tests at a time
while(numTests > 0)
{
uint32_t num = std::min(numTests, 256U);
vkCmdDraw(cmd, 3, num, 0, offset);
offset += num;
numTests -= num;
}
popMarker(cmd);
vkCmdEndRenderPass(cmd);
// sync all the storage work
vkh::cmdPipelineBarrier(
cmd,
{
vkh::ImageMemoryBarrier(VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT,
VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL,
store_image.image),
vkh::ImageMemoryBarrier(VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT,
VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL,
atomic_image.image),
vkh::ImageMemoryBarrier(VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT,
VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL,
storezoo_u2D.image),
},
{
vkh::BufferMemoryBarrier(VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
store_buffer.buffer),
vkh::BufferMemoryBarrier(VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
atomic_buffer.buffer),
vkh::BufferMemoryBarrier(VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
store_texbuffer.buffer),
});
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, glslpipe2);
vkCmdBeginRenderPass(cmd,
vkh::RenderPassBeginInfo(renderPass, framebuffer, s,
{vkh::ClearValue(0.0f, 0.0f, 0.0f, 0.0f)}),
VK_SUBPASS_CONTENTS_INLINE);
pushMarker(cmd, "GLSL2 tests");
numTests = numGLSL2Tests;
offset = 0;
// loop drawing 256 tests at a time
while(numTests > 0)
{
uint32_t num = std::min(numTests, 256U);
vkCmdDraw(cmd, 3, num, 0, offset);
offset += num;
numTests -= num;
}
popMarker(cmd);
vkCmdEndRenderPass(cmd);
FinishUsingBackbuffer(cmd, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL);
pushMarker(cmd, "Compute Tests");
for(size_t p = 0; p < countCompPipes; p++)
{
vkh::cmdPipelineBarrier(
cmd, {},
{vkh::BufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_WRITE_BIT,
bufout.buffer, 0, sizeof(Vec4f) * 1024 * numCompTests)});
vkCmdFillBuffer(cmd, bufout.buffer, 0, sizeof(Vec4f) * 1024 * numCompTests, 0);
vkh::cmdPipelineBarrier(
cmd, {},
{vkh::BufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_WRITE_BIT,
bufout.buffer, 0, sizeof(Vec4f) * 1024 * numCompTests)});
pushMarker(cmd, comppipe_name[p]);
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, compPipes[p]);
vkh::cmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, compLayout, 0, {compSet}, {});
for(int i = 0; i < numCompTests; i++)
{
vkh::cmdPushConstants(cmd, compLayout, i);
vkCmdDispatch(cmd, 2, 1, 1);
}
popMarker(cmd);
}
popMarker(cmd);
vkEndCommandBuffer(cmd);
Submit(0, 1, {cmd});
Present();
}
CHECK_VKR(vkDeviceWaitIdle(device));
if(bda)
{
vkDestroyBuffer(device, bda_data_buffer, NULL);
vkUnmapMemory(device, bda_deviceMem);
vkFreeMemory(device, bda_deviceMem, NULL);
}
return 0;
}
};
REGISTER_TEST();