Files
renderdoc/util/test/demos/vk/vk_shader_debug_zoo.cpp
T

5185 lines
187 KiB
C++

/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2019-2025 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(
vec4 varscope_test(int coord, vec2 inpos_param, vec2 inpos_incr_param)
{
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.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;
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);
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;
}
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 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",
});
}
}
}
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<uint8_t> u8_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 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 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_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_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_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"
"%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"
"%u64 = OpTypeInt 64 0\n";
capabilities += "OpCapability Int64\n";
}
if(features.shaderInt16 || storage16Features.storageBuffer16BitAccess ||
storage16Features.uniformAndStorageBuffer16BitAccess ||
storage16Features.storagePushConstant16 || storage16Features.storageInputOutput16)
{
typesConstants +=
"%i16 = OpTypeInt 16 1\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";
}
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)
{
typesConstants += "\n";
for(uint8_t u : u8_constants)
typesConstants += fmt::format("%u8_{0} = OpConstant %u8 {0}\n", u);
}
if(features.shaderInt16)
{
typesConstants += "\n";
for(uint16_t u : u16_constants)
typesConstants += fmt::format("%u16_{0} = OpConstant %u16 {0}\n", u);
}
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,
};
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);
// 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();
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;
}
}
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();
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(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);
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);
}
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);
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();