summaryrefslogtreecommitdiffstats
path: root/tests/language-feature/inheritance/struct-inherit-interface-requirement.slang
blob: c6d30ed911f3f10b64205da344c64751562ec542 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
// struct-inherit-interface-requirement.slang

//TEST(compute):COMPARE_COMPUTE: -shaderobj
//TEST(compute):COMPARE_COMPUTE: -vk -shaderobj

// Test that a `struct` type can use an inherited
// member to satisfy an interface requirement.
#pragma warning(disable:30816)

interface ITweak
{
	int tweak(int val);
	int twiddle(int val);
}

// Note: `Base` intentionally doesn't inherit from `ITweak`,
// but it *does* provide a method that could satisfy one
// of the interface requirements.
//
struct Base
{
	int a;

	int tweak(int val) { return val ^ a; }
}

struct Derived : Base, ITweak
{
	// Note: it is important for this type to have an additional
	// field beyond the one in `Base`, because it ensures that
	// the two types `Base` and `Derived` aren't structurally
	// equivalent when compiled through HLSL (which silently allows
	// certain type mismatches so long as there is a memberwise
	// structural match).
	int b;

	int twiddle(int val)
	{
		return val + b;
	}
}

int tweakAndTwiddle<T : ITweak>(T tweaker, int val)
{
	int tmp = val;
	tmp = tweaker.tweak(tmp);
	tmp = tweaker.twiddle(tmp);
	return tmp;
}


int test(int val)
{
	Derived d;
	d.a = 0xFF;
	d.b = 1;

	return tweakAndTwiddle(d, val);
}

//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name=outputBuffer
RWStructuredBuffer<int> outputBuffer;

[numthreads(4, 1, 1)]
void computeMain(int3 dispatchThreadID : SV_DispatchThreadID)
{
    int tid = dispatchThreadID.x;
    int inVal = tid;
    int outVal = test(inVal);
    outputBuffer[tid] = outVal;
}