Add validation to the maximum inter-shader stage variable location

This patch adds the validation rules on the maximum inter-shader
stage variable locations. According to Vulkan SPEC, "Each effective
Location must have a value less than the number of location avaiable for
the given interface", and according to Table 18 "Shader Input and Output
Locations", the number of available vertex output locations is
maxVertexOutputComponents / 4, and the number of available fragment input
locations is maxFragmentInputComponents / 4.

BUG=dawn:802
TEST=dawn_unittests

Change-Id: I73a66ad69c808fbd0b128abaed1ca84f19a7925d
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/58640
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
This commit is contained in:
Jiawei Shao 2021-07-21 08:26:58 +00:00 committed by Dawn LUCI CQ
parent 8bee260b74
commit 46513c7810
2 changed files with 84 additions and 0 deletions

View File

@ -888,6 +888,8 @@ namespace dawn_native {
return DAWN_VALIDATION_ERROR(errorStream.str().c_str()); return DAWN_VALIDATION_ERROR(errorStream.str().c_str());
} }
constexpr uint32_t kMaxInterStageShaderLocation =
kMaxInterStageShaderComponents / 4 - 1;
for (auto& entryPoint : entryPoints) { for (auto& entryPoint : entryPoints) {
ASSERT(result.count(entryPoint.name) == 0); ASSERT(result.count(entryPoint.name) == 0);
@ -928,6 +930,12 @@ namespace dawn_native {
<< output_var.name; << output_var.name;
return DAWN_VALIDATION_ERROR(ss.str()); return DAWN_VALIDATION_ERROR(ss.str());
} }
uint32_t location = output_var.location_decoration;
if (DAWN_UNLIKELY(location > kMaxInterStageShaderLocation)) {
std::stringstream ss;
ss << "Vertex output location (" << location << ") over limits";
return DAWN_VALIDATION_ERROR(ss.str());
}
} }
} }
@ -937,6 +945,12 @@ namespace dawn_native {
return DAWN_VALIDATION_ERROR( return DAWN_VALIDATION_ERROR(
"Need location decoration on fragment input"); "Need location decoration on fragment input");
} }
uint32_t location = input_var.location_decoration;
if (DAWN_UNLIKELY(location > kMaxInterStageShaderLocation)) {
std::stringstream ss;
ss << "Fragment input location (" << location << ") over limits";
return DAWN_VALIDATION_ERROR(ss.str());
}
} }
for (const auto& output_var : entryPoint.output_variables) { for (const auto& output_var : entryPoint.output_variables) {

View File

@ -212,3 +212,73 @@ TEST_F(ShaderModuleValidationTest, GetCompilationMessages) {
shaderModule.GetCompilationInfo(callback, nullptr); shaderModule.GetCompilationInfo(callback, nullptr);
} }
// Validate the maximum location of effective inter-stage variables cannot be greater than 14
// (kMaxInterStageShaderComponents / 4 - 1).
TEST_F(ShaderModuleValidationTest, MaximumShaderIOLocations) {
auto generateShaderForTest = [](uint32_t maximumOutputLocation, wgpu::ShaderStage shaderStage) {
std::ostringstream stream;
stream << "struct ShaderIO {" << std::endl;
for (uint32_t location = 0; location <= maximumOutputLocation; ++location) {
stream << "[[location(" << location << ")]] var" << location << ": f32;" << std::endl;
}
switch (shaderStage) {
case wgpu::ShaderStage::Vertex: {
stream << R"(
[[builtin(position)]] pos: vec4<f32>;
};
[[stage(vertex)]] fn main() -> ShaderIO {
var shaderIO : ShaderIO;
shaderIO.pos = vec4<f32>(0.0, 0.0, 0.0, 1.0);
return shaderIO;
})";
} break;
case wgpu::ShaderStage::Fragment: {
stream << R"(
};
[[stage(fragment)]] fn main(shaderIO: ShaderIO) -> [[location(0)]] vec4<f32> {
return vec4<f32>(0.0, 0.0, 0.0, 1.0);
})";
} break;
case wgpu::ShaderStage::Compute:
default:
UNREACHABLE();
}
return stream.str();
};
constexpr uint32_t kMaxInterShaderIOLocation = kMaxInterStageShaderComponents / 4 - 1;
// It is allowed to create a shader module with the maximum active vertex output location == 14;
{
std::string vertexShader =
generateShaderForTest(kMaxInterShaderIOLocation, wgpu::ShaderStage::Vertex);
utils::CreateShaderModule(device, vertexShader.c_str());
}
// It isn't allowed to create a shader module with the maximum active vertex output location >
// 14;
{
std::string vertexShader =
generateShaderForTest(kMaxInterShaderIOLocation + 1, wgpu::ShaderStage::Vertex);
ASSERT_DEVICE_ERROR(utils::CreateShaderModule(device, vertexShader.c_str()));
}
// It is allowed to create a shader module with the maximum active fragment input location ==
// 14;
{
std::string fragmentShader =
generateShaderForTest(kMaxInterShaderIOLocation, wgpu::ShaderStage::Fragment);
utils::CreateShaderModule(device, fragmentShader.c_str());
}
// It is allowed to create a shader module with the maximum active vertex output location > 14;
{
std::string fragmentShader =
generateShaderForTest(kMaxInterShaderIOLocation + 1, wgpu::ShaderStage::Fragment);
ASSERT_DEVICE_ERROR(utils::CreateShaderModule(device, fragmentShader.c_str()));
}
}