microsoft/clc: Add a test for specializing via SPIRV-Tools
Acked-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10322>
This commit is contained in:
@@ -2232,3 +2232,82 @@ TEST_F(ComputeTest, unused_arg)
|
||||
for (int i = 0; i < 4; ++i)
|
||||
EXPECT_EQ(dest[i], i + 1);
|
||||
}
|
||||
|
||||
TEST_F(ComputeTest, spec_constant)
|
||||
{
|
||||
const char *spirv_asm = R"(
|
||||
OpCapability Addresses
|
||||
OpCapability Kernel
|
||||
OpCapability Int64
|
||||
%1 = OpExtInstImport "OpenCL.std"
|
||||
OpMemoryModel Physical64 OpenCL
|
||||
OpEntryPoint Kernel %2 "main_test" %__spirv_BuiltInGlobalInvocationId
|
||||
%4 = OpString "kernel_arg_type.main_test.uint*,"
|
||||
OpSource OpenCL_C 102000
|
||||
OpName %__spirv_BuiltInGlobalInvocationId "__spirv_BuiltInGlobalInvocationId"
|
||||
OpName %output "output"
|
||||
OpName %entry "entry"
|
||||
OpName %output_addr "output.addr"
|
||||
OpName %id "id"
|
||||
OpName %call "call"
|
||||
OpName %conv "conv"
|
||||
OpName %idxprom "idxprom"
|
||||
OpName %arrayidx "arrayidx"
|
||||
OpName %add "add"
|
||||
OpName %mul "mul"
|
||||
OpName %idxprom1 "idxprom1"
|
||||
OpName %arrayidx2 "arrayidx2"
|
||||
OpDecorate %__spirv_BuiltInGlobalInvocationId BuiltIn GlobalInvocationId
|
||||
OpDecorate %__spirv_BuiltInGlobalInvocationId Constant
|
||||
OpDecorate %id Alignment 4
|
||||
OpDecorate %output_addr Alignment 8
|
||||
OpDecorate %uint_1 SpecId 1
|
||||
%ulong = OpTypeInt 64 0
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_1 = OpSpecConstant %uint 1
|
||||
%v3ulong = OpTypeVector %ulong 3
|
||||
%_ptr_Input_v3ulong = OpTypePointer Input %v3ulong
|
||||
%void = OpTypeVoid
|
||||
%_ptr_CrossWorkgroup_uint = OpTypePointer CrossWorkgroup %uint
|
||||
%24 = OpTypeFunction %void %_ptr_CrossWorkgroup_uint
|
||||
%_ptr_Function__ptr_CrossWorkgroup_uint = OpTypePointer Function %_ptr_CrossWorkgroup_uint
|
||||
%_ptr_Function_uint = OpTypePointer Function %uint
|
||||
%__spirv_BuiltInGlobalInvocationId = OpVariable %_ptr_Input_v3ulong Input
|
||||
%2 = OpFunction %void DontInline %24
|
||||
%output = OpFunctionParameter %_ptr_CrossWorkgroup_uint
|
||||
%entry = OpLabel
|
||||
%output_addr = OpVariable %_ptr_Function__ptr_CrossWorkgroup_uint Function
|
||||
%id = OpVariable %_ptr_Function_uint Function
|
||||
OpStore %output_addr %output Aligned 8
|
||||
%27 = OpLoad %v3ulong %__spirv_BuiltInGlobalInvocationId Aligned 32
|
||||
%call = OpCompositeExtract %ulong %27 0
|
||||
%conv = OpUConvert %uint %call
|
||||
OpStore %id %conv Aligned 4
|
||||
%28 = OpLoad %_ptr_CrossWorkgroup_uint %output_addr Aligned 8
|
||||
%29 = OpLoad %uint %id Aligned 4
|
||||
%idxprom = OpUConvert %ulong %29
|
||||
%arrayidx = OpInBoundsPtrAccessChain %_ptr_CrossWorkgroup_uint %28 %idxprom
|
||||
%30 = OpLoad %uint %arrayidx Aligned 4
|
||||
%31 = OpLoad %uint %id Aligned 4
|
||||
%add = OpIAdd %uint %31 %uint_1
|
||||
%mul = OpIMul %uint %30 %add
|
||||
%32 = OpLoad %_ptr_CrossWorkgroup_uint %output_addr Aligned 8
|
||||
%33 = OpLoad %uint %id Aligned 4
|
||||
%idxprom1 = OpUConvert %ulong %33
|
||||
%arrayidx2 = OpInBoundsPtrAccessChain %_ptr_CrossWorkgroup_uint %32 %idxprom1
|
||||
OpStore %arrayidx2 %mul Aligned 4
|
||||
OpReturn
|
||||
OpFunctionEnd)";
|
||||
Shader shader = assemble(spirv_asm);
|
||||
Shader spec_shader = specialize(shader, 1, 5);
|
||||
|
||||
auto inout = ShaderArg<uint32_t>({ 0x00000001, 0x10000001, 0x00020002, 0x04010203 },
|
||||
SHADER_ARG_INOUT);
|
||||
const uint32_t expected[] = {
|
||||
0x00000005, 0x60000006, 0x000e000e, 0x20081018
|
||||
};
|
||||
CompileArgs args = { inout.size(), 1, 1 };
|
||||
run_shader(spec_shader, args, inout);
|
||||
for (int i = 0; i < inout.size(); ++i)
|
||||
EXPECT_EQ(inout[i], expected[i]);
|
||||
}
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
#include "compute_test.h"
|
||||
#include "dxcapi.h"
|
||||
|
||||
#include <spirv-tools/libspirv.hpp>
|
||||
|
||||
using std::runtime_error;
|
||||
using Microsoft::WRL::ComPtr;
|
||||
|
||||
@@ -850,6 +852,29 @@ ComputeTest::link(const std::vector<Shader> &sources,
|
||||
return shader;
|
||||
}
|
||||
|
||||
ComputeTest::Shader
|
||||
ComputeTest::assemble(const char *source)
|
||||
{
|
||||
spvtools::SpirvTools tools(SPV_ENV_UNIVERSAL_1_0);
|
||||
std::vector<uint32_t> binary;
|
||||
if (!tools.Assemble(source, strlen(source), &binary))
|
||||
throw runtime_error("failed to assemble");
|
||||
|
||||
ComputeTest::Shader shader;
|
||||
shader.obj = std::shared_ptr<clc_binary>(new clc_binary{}, [](clc_binary *spirv)
|
||||
{
|
||||
free(spirv->data);
|
||||
delete spirv;
|
||||
});
|
||||
shader.obj->size = binary.size() * 4;
|
||||
shader.obj->data = malloc(shader.obj->size);
|
||||
memcpy(shader.obj->data, binary.data(), shader.obj->size);
|
||||
|
||||
configure(shader, NULL);
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
void
|
||||
ComputeTest::configure(Shader &shader,
|
||||
const struct clc_runtime_kernel_conf *conf)
|
||||
|
||||
@@ -167,6 +167,9 @@ protected:
|
||||
link(const std::vector<Shader> &sources,
|
||||
bool create_library = false);
|
||||
|
||||
Shader
|
||||
assemble(const char *source);
|
||||
|
||||
void
|
||||
configure(Shader &shader,
|
||||
const struct clc_runtime_kernel_conf *conf);
|
||||
@@ -174,6 +177,33 @@ protected:
|
||||
void
|
||||
validate(Shader &shader);
|
||||
|
||||
template <typename T>
|
||||
Shader
|
||||
specialize(Shader &shader, uint32_t id, T const& val)
|
||||
{
|
||||
Shader new_shader;
|
||||
new_shader.obj = std::shared_ptr<clc_binary>(new clc_binary{}, [](clc_binary *spirv)
|
||||
{
|
||||
clc_free_spirv(spirv);
|
||||
delete spirv;
|
||||
});
|
||||
if (!shader.metadata)
|
||||
configure(shader, NULL);
|
||||
|
||||
clc_spirv_specialization spec;
|
||||
spec.id = id;
|
||||
memcpy(&spec.value, &val, sizeof(val));
|
||||
clc_spirv_specialization_consts consts;
|
||||
consts.specializations = &spec;
|
||||
consts.num_specializations = 1;
|
||||
if (!clc_specialize_spirv(shader.obj.get(), shader.metadata.get(), &consts, new_shader.obj.get()))
|
||||
throw runtime_error("failed to specialize");
|
||||
|
||||
configure(new_shader, NULL);
|
||||
|
||||
return new_shader;
|
||||
}
|
||||
|
||||
enum ShaderArgDirection {
|
||||
SHADER_ARG_INPUT = 1,
|
||||
SHADER_ARG_OUTPUT = 2,
|
||||
|
||||
@@ -63,8 +63,8 @@ if dep_dxheaders.found()
|
||||
clc_compiler_test = executable('clc_compiler_test',
|
||||
['clc_compiler_test.cpp', 'compute_test.cpp'],
|
||||
link_with : [libclc_compiler],
|
||||
dependencies : [idep_gtest, idep_mesautil, idep_libdxil_compiler, dep_dxheaders],
|
||||
include_directories : [inc_include, inc_src])
|
||||
dependencies : [idep_gtest, idep_mesautil, idep_libdxil_compiler, dep_dxheaders, dep_spirv_tools],
|
||||
include_directories : [inc_include, inc_src, inc_spirv])
|
||||
|
||||
test('clc_compiler_test', clc_compiler_test, timeout: 180)
|
||||
endif
|
||||
|
||||
Reference in New Issue
Block a user