Derivative opcodes require Fragment exec model

Added validator check that all derivative opcodes require Fragment
execution model.
This commit is contained in:
Andrey Tuganov 2017-11-24 10:29:05 -05:00 committed by David Neto
parent c170afd93b
commit d8b2013ecf
2 changed files with 34 additions and 16 deletions

View File

@ -52,8 +52,10 @@ spv_result_t DerivativesPass(ValidationState_t& _,
<< spvOpcodeString(opcode); << spvOpcodeString(opcode);
} }
// All derivative opcodes require Fragment execution model. _.current_function().RegisterExecutionModelLimitation(
// This needs to be checked elsewhere. SpvExecutionModelFragment, std::string(
"Derivative instructions require Fragment execution model: ") +
spvOpcodeString(opcode));
break; break;
} }

View File

@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include <sstream>
#include <string> #include <string>
#include "gmock/gmock.h" #include "gmock/gmock.h"
@ -27,17 +28,19 @@ using ValidateDerivatives = spvtest::ValidateBase<bool>;
std::string GenerateShaderCode( std::string GenerateShaderCode(
const std::string& body, const std::string& body,
const std::string& capabilities_and_extensions = "") { const std::string& capabilities_and_extensions = "",
const std::string capabilities = const std::string& execution_model = "Fragment") {
R"( std::stringstream ss;
ss << R"(
OpCapability Shader OpCapability Shader
OpCapability DerivativeControl)"; OpCapability DerivativeControl
)";
const std::string after_extension_before_body = ss << capabilities_and_extensions;
R"( ss << "OpMemoryModel Logical GLSL450\n";
%ext_inst = OpExtInstImport "GLSL.std.450" ss << "OpEntryPoint " << execution_model << " %main \"main\"\n";
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main "main" ss << R"(
%void = OpTypeVoid %void = OpTypeVoid
%func = OpTypeFunction %void %func = OpTypeFunction %void
%bool = OpTypeBool %bool = OpTypeBool
@ -53,15 +56,16 @@ OpEntryPoint Fragment %main "main"
%f32vec4_var_input = OpVariable %f32vec4_ptr_input Input %f32vec4_var_input = OpVariable %f32vec4_ptr_input Input
%main = OpFunction %void None %func %main = OpFunction %void None %func
%main_entry = OpLabel)"; %main_entry = OpLabel
)";
const std::string after_body = ss << body;
R"(
ss << R"(
OpReturn OpReturn
OpFunctionEnd)"; OpFunctionEnd)";
return capabilities + capabilities_and_extensions + return ss.str();
after_extension_before_body + body + after_body;
} }
TEST_F(ValidateDerivatives, ScalarSuccess) { TEST_F(ValidateDerivatives, ScalarSuccess) {
@ -126,4 +130,16 @@ TEST_F(ValidateDerivatives, OpDPdxWrongPType) {
"DPdx")); "DPdx"));
} }
TEST_F(ValidateDerivatives, OpDPdxWrongExecutionModel) {
const std::string body = R"(
%f32vec4_var = OpLoad %f32vec4 %f32vec4_var_input
%val1 = OpDPdx %f32vec4 %f32vec4_var
)";
CompileSuccessfully(GenerateShaderCode(body, "", "Vertex").c_str());
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
EXPECT_THAT(getDiagnosticString(), HasSubstr(
"Derivative instructions require Fragment execution model: DPdx"));
}
} // anonymous namespace } // anonymous namespace