mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-17 00:47:13 +00:00
Validate MaxInterStageShaderComponents when creating shader module
According to the discussion[1], the sum of all the user-defined inter-stage component count and all the inter-stage builtin component count should be no more than MaxInterStageShaderComponents (currently in Dawn it is always 60). [1] https://github.com/gpuweb/gpuweb/issues/1962 BUG=dawn:1032 TEST=dawn_unittests Change-Id: Id5266b72b89c48f5b7073b8307f8f2c0512c8a33 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/61104 Commit-Queue: Kai Ninomiya <kainino@chromium.org> Reviewed-by: Austin Eng <enga@chromium.org> Reviewed-by: Kai Ninomiya <kainino@chromium.org>
This commit is contained in:
committed by
Dawn LUCI CQ
parent
9eb890dff4
commit
8d8fadbbe4
@@ -219,7 +219,7 @@ 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) {
|
||||
for (uint32_t location = 1; location <= maximumOutputLocation; ++location) {
|
||||
stream << "[[location(" << location << ")]] var" << location << ": f32;" << std::endl;
|
||||
}
|
||||
switch (shaderStage) {
|
||||
@@ -283,6 +283,156 @@ TEST_F(ShaderModuleValidationTest, MaximumShaderIOLocations) {
|
||||
}
|
||||
}
|
||||
|
||||
// Validate the maximum number of total inter-stage user-defined variable component count and
|
||||
// built-in variables cannot exceed kMaxInterStageShaderComponents.
|
||||
TEST_F(ShaderModuleValidationTest, MaximumInterStageShaderComponents) {
|
||||
auto generateShaderForTest = [](uint32_t totalUserDefinedInterStageShaderComponentCount,
|
||||
wgpu::ShaderStage shaderStage,
|
||||
const char* builtInDeclarations) {
|
||||
std::ostringstream stream;
|
||||
stream << "struct ShaderIO {" << std::endl << builtInDeclarations << std::endl;
|
||||
uint32_t vec4InputLocations = totalUserDefinedInterStageShaderComponentCount / 4;
|
||||
|
||||
for (uint32_t location = 0; location < vec4InputLocations; ++location) {
|
||||
stream << "[[location(" << location << ")]] var" << location << ": vec4<f32>;"
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
uint32_t lastComponentCount = totalUserDefinedInterStageShaderComponentCount % 4;
|
||||
if (lastComponentCount > 0) {
|
||||
stream << "[[location(" << vec4InputLocations << ")]] var" << vec4InputLocations
|
||||
<< ": ";
|
||||
if (lastComponentCount == 1) {
|
||||
stream << "f32;";
|
||||
} else {
|
||||
stream << " vec" << lastComponentCount << "<f32>;";
|
||||
}
|
||||
stream << 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();
|
||||
};
|
||||
|
||||
// Verify when there is no input builtin variable in a fragment shader, the total user-defined
|
||||
// input component count must be less than kMaxInterStageShaderComponents.
|
||||
{
|
||||
constexpr uint32_t kInterStageShaderComponentCount = kMaxInterStageShaderComponents;
|
||||
std::string correctFragmentShader =
|
||||
generateShaderForTest(kInterStageShaderComponentCount, wgpu::ShaderStage::Fragment, "");
|
||||
utils::CreateShaderModule(device, correctFragmentShader.c_str());
|
||||
|
||||
std::string errorFragmentShader = generateShaderForTest(kInterStageShaderComponentCount + 1,
|
||||
wgpu::ShaderStage::Fragment, "");
|
||||
ASSERT_DEVICE_ERROR(utils::CreateShaderModule(device, errorFragmentShader.c_str()));
|
||||
}
|
||||
|
||||
// [[position]] should be counted into the maximum inter-stage component count.
|
||||
// Note that in vertex shader we always have [[position]] so we don't need to specify it
|
||||
// again in the parameter "builtInDeclarations" of generateShaderForTest().
|
||||
{
|
||||
constexpr uint32_t kInterStageShaderComponentCount = kMaxInterStageShaderComponents - 4;
|
||||
std::string vertexShader =
|
||||
generateShaderForTest(kInterStageShaderComponentCount, wgpu::ShaderStage::Vertex, "");
|
||||
utils::CreateShaderModule(device, vertexShader.c_str());
|
||||
|
||||
std::string fragmentShader =
|
||||
generateShaderForTest(kInterStageShaderComponentCount, wgpu::ShaderStage::Fragment,
|
||||
"[[builtin(position)]] fragCoord: vec4<f32>;");
|
||||
utils::CreateShaderModule(device, fragmentShader.c_str());
|
||||
}
|
||||
|
||||
{
|
||||
constexpr uint32_t kInterStageShaderComponentCount = kMaxInterStageShaderComponents - 3;
|
||||
std::string vertexShader =
|
||||
generateShaderForTest(kInterStageShaderComponentCount, wgpu::ShaderStage::Vertex, "");
|
||||
ASSERT_DEVICE_ERROR(utils::CreateShaderModule(device, vertexShader.c_str()));
|
||||
|
||||
std::string fragmentShader =
|
||||
generateShaderForTest(kInterStageShaderComponentCount, wgpu::ShaderStage::Fragment,
|
||||
"[[builtin(position)]] fragCoord: vec4<f32>;");
|
||||
ASSERT_DEVICE_ERROR(utils::CreateShaderModule(device, fragmentShader.c_str()));
|
||||
}
|
||||
|
||||
// [[front_facing]] should be counted into the maximum inter-stage component count.
|
||||
{
|
||||
const char* builtinDeclaration = "[[builtin(front_facing)]] frontFacing : bool;";
|
||||
|
||||
{
|
||||
std::string fragmentShader =
|
||||
generateShaderForTest(kMaxInterStageShaderComponents - 1,
|
||||
wgpu::ShaderStage::Fragment, builtinDeclaration);
|
||||
utils::CreateShaderModule(device, fragmentShader.c_str());
|
||||
}
|
||||
|
||||
{
|
||||
std::string fragmentShader = generateShaderForTest(
|
||||
kMaxInterStageShaderComponents, wgpu::ShaderStage::Fragment, builtinDeclaration);
|
||||
ASSERT_DEVICE_ERROR(utils::CreateShaderModule(device, fragmentShader.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
// [[sample_index]] should be counted into the maximum inter-stage component count.
|
||||
{
|
||||
const char* builtinDeclaration = "[[builtin(sample_index)]] sampleIndex: u32;";
|
||||
|
||||
{
|
||||
std::string fragmentShader =
|
||||
generateShaderForTest(kMaxInterStageShaderComponents - 1,
|
||||
wgpu::ShaderStage::Fragment, builtinDeclaration);
|
||||
utils::CreateShaderModule(device, fragmentShader.c_str());
|
||||
}
|
||||
|
||||
{
|
||||
std::string fragmentShader = generateShaderForTest(
|
||||
kMaxInterStageShaderComponents, wgpu::ShaderStage::Fragment, builtinDeclaration);
|
||||
ASSERT_DEVICE_ERROR(utils::CreateShaderModule(device, fragmentShader.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
// [[sample_mask]] should be counted into the maximum inter-stage component count.
|
||||
{
|
||||
const char* builtinDeclaration = "[[builtin(front_facing)]] frontFacing : bool;";
|
||||
|
||||
{
|
||||
std::string fragmentShader =
|
||||
generateShaderForTest(kMaxInterStageShaderComponents - 1,
|
||||
wgpu::ShaderStage::Fragment, builtinDeclaration);
|
||||
utils::CreateShaderModule(device, fragmentShader.c_str());
|
||||
}
|
||||
|
||||
{
|
||||
std::string fragmentShader = generateShaderForTest(
|
||||
kMaxInterStageShaderComponents, wgpu::ShaderStage::Fragment, builtinDeclaration);
|
||||
ASSERT_DEVICE_ERROR(utils::CreateShaderModule(device, fragmentShader.c_str()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that we validate workgroup size limits.
|
||||
TEST_F(ShaderModuleValidationTest, ComputeWorkgroupSizeLimits) {
|
||||
DAWN_SKIP_TEST_IF(!HasToggleEnabled("use_tint_generator"));
|
||||
|
||||
Reference in New Issue
Block a user