-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathShaderMetaReflection.cpp
More file actions
138 lines (127 loc) · 5.48 KB
/
Copy pathShaderMetaReflection.cpp
File metadata and controls
138 lines (127 loc) · 5.48 KB
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#include "ShaderMetaReflection.h"
#include <optional>
namespace
{
std::optional<RHIShaderValueType> ExpectedType(ShaderPropertyType type)
{
switch (type)
{
case ShaderPropertyType::Float:
return RHIShaderValueType{ RHIShaderScalarKind::Float32, 1, 1, 1 };
case ShaderPropertyType::Float2:
return RHIShaderValueType{ RHIShaderScalarKind::Float32, 1, 2, 1 };
case ShaderPropertyType::Float3:
return RHIShaderValueType{ RHIShaderScalarKind::Float32, 1, 3, 1 };
case ShaderPropertyType::Float4:
return RHIShaderValueType{ RHIShaderScalarKind::Float32, 1, 4, 1 };
case ShaderPropertyType::Int:
return RHIShaderValueType{ RHIShaderScalarKind::Int32, 1, 1, 1 };
case ShaderPropertyType::Bool:
return RHIShaderValueType{ RHIShaderScalarKind::Bool, 1, 1, 1 };
case ShaderPropertyType::Float4x4:
return RHIShaderValueType{ RHIShaderScalarKind::Float32, 4, 4, 1 };
case ShaderPropertyType::Texture2D:
return std::nullopt;
}
return std::nullopt;
}
bool MergeCandidate(const ShaderMetaPropertyBinding& candidate,
std::optional<ShaderMetaPropertyBinding>& selected, std::string& outError)
{
if (!selected)
{
selected = candidate;
return true;
}
if (*selected == candidate) return true;
outError = "ShaderMeta property binding이 stage 사이에서 다르다: "
+ candidate.name;
return false;
}
}
bool ShaderMetaReflection::Resolve(const ShaderMeta& meta,
std::span<const RHIShaderReflection> stageReflections,
ShaderMetaBindingLayout& outLayout, std::string& outError)
{
if (stageReflections.empty())
{
outError = "ShaderMeta reflection stage가 없다";
return false;
}
ShaderMetaBindingLayout resolved;
resolved.properties.reserve(meta.properties.size());
for (const ShaderPropertyDesc& property : meta.properties)
{
std::optional<ShaderMetaPropertyBinding> selected;
const std::optional<RHIShaderValueType> expected = ExpectedType(property.type);
for (const RHIShaderReflection& reflection : stageReflections)
{
for (const RHIShaderResourceReflection& resource : reflection.resources)
{
if (ShaderPropertyType::Texture2D == property.type)
{
if (resource.name != property.name
|| RHIShaderResourceKind::Texture != resource.kind)
{
continue;
}
if (1 != resource.arrayElements)
{
outError = "ShaderMeta texture2d property가 배열 resource다: "
+ property.name;
return false;
}
const ShaderMetaPropertyBinding candidate{
property.name, property.type, resource.kind, resource.name,
resource.registerIndex, resource.registerSpace, 0, 0,
};
if (!MergeCandidate(candidate, selected, outError)) return false;
continue;
}
if (RHIShaderResourceKind::ConstantBuffer != resource.kind) continue;
for (const RHIShaderFieldReflection& field : resource.fields)
{
if (field.name != property.name) continue;
if (!expected || field.type != *expected)
{
outError = "ShaderMeta property와 shader field type이 다르다: "
+ property.name;
return false;
}
const ShaderMetaPropertyBinding candidate{
property.name, property.type, resource.kind, resource.name,
resource.registerIndex, resource.registerSpace,
field.byteOffset, field.byteSize,
};
if (!MergeCandidate(candidate, selected, outError)) return false;
if (resolved.constantBufferName.empty())
{
resolved.constantBufferName = resource.name;
resolved.constantBufferRegister = resource.registerIndex;
resolved.constantBufferSpace = resource.registerSpace;
resolved.constantBufferByteSize = resource.byteSize;
}
else if (resolved.constantBufferName != resource.name
|| resolved.constantBufferRegister != resource.registerIndex
|| resolved.constantBufferSpace != resource.registerSpace
|| resolved.constantBufferByteSize != resource.byteSize)
{
outError = "ShaderMeta 숫자 property가 둘 이상의 constant buffer에 있다: "
+ property.name;
return false;
}
}
}
}
if (!selected)
{
outError = "ShaderMeta property에 대응하는 shader 선언이 없다: "
+ property.name;
return false;
}
resolved.properties.push_back(std::move(*selected));
}
outLayout = std::move(resolved);
outError.clear();
return true;
}