aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Neto <dneto@google.com>2016-10-29 11:30:00 -0400
committerDavid Neto <dneto@google.com>2016-11-16 16:36:26 -0500
commit89eefb94d69e07576682e44cb3d55fa332ce2e91 (patch)
tree2239b78dfa98602d3515aee07d64c43843375ac1
parent725a8fd2e7b98f45905f8ac791c62e6239ce2898 (diff)
downloadshaderc-89eefb94d69e07576682e44cb3d55fa332ce2e91.tar.gz
Add -fentry-point to glslc
Updates to test infrastructure: - TestStatus carries raw PlaceHolder objects - FileShader placeholder now takes an optional assembly_substr. If present, that's a substring expected to be in the dissasembled output of an module generated from that placeholder's input. - Add test mixin classes to check for substring in assembly output per shader input file. - Pass the path to the spirv-dis to the tests, and store it in the test manager class.
-rw-r--r--CHANGES2
-rw-r--r--glslc/README.asciidoc7
-rw-r--r--glslc/src/file_compiler.cc34
-rw-r--r--glslc/src/file_compiler.h21
-rw-r--r--glslc/src/main.cc23
-rw-r--r--glslc/test/CMakeLists.txt3
-rw-r--r--glslc/test/expect.py54
-rw-r--r--glslc/test/expect_nosetest.py12
-rwxr-xr-xglslc/test/glslc_test_framework.py24
-rw-r--r--glslc/test/option_dash_x.py8
-rw-r--r--glslc/test/option_fentry_point.py109
-rw-r--r--glslc/test/parameter_tests.py3
-rw-r--r--glslc/test/placeholder.py5
13 files changed, 245 insertions, 60 deletions
diff --git a/CHANGES b/CHANGES
index db599b1..4cf6bd4 100644
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,8 @@ v2016.2-dev 2016-10-12
- Support HLSL compilation, exposing functionality in Glslang.
- Supported in C, C++ API
- glslc accepts "-x hlsl", and assumes .hlsl files are HLSL.
+ - glslc accepts "-fentry-point=<name>" to set entry point name,
+ overriding default value "main".
v2016.1 2016-10-12
- C API for assembling now takes an options object
diff --git a/glslc/README.asciidoc b/glslc/README.asciidoc
index a7cdad4..a8f22c9 100644
--- a/glslc/README.asciidoc
+++ b/glslc/README.asciidoc
@@ -14,6 +14,7 @@ Clang-compatible arguments.
glslc [-c|-S|-E]
[-x ...] [-std=standard]
[-fshader-stage=...]
+ [-fentry-point=...]
[--target-env=...]
[-g]
[-O0|-Os]
@@ -150,6 +151,12 @@ command line, please put SPIR-V assembly files ahead of the first
`-fshader-stage=`, since `-fshader-stage=` only affects the treatment of
subsequent files.
+[[option-f-entry-point]]
+==== `-fentry-point=`
+
+`-fentry-point=<name>` lets you specify the entry point name. This is only
+significant for HLSL compilation. The default is "main".
+
==== `-std=`
`-std=<value>` lets you specify a shader version and profile on the command
diff --git a/glslc/src/file_compiler.cc b/glslc/src/file_compiler.cc
index 1aed39d..5469736 100644
--- a/glslc/src/file_compiler.cc
+++ b/glslc/src/file_compiler.cc
@@ -62,16 +62,14 @@ bool EmitSpirvBinaryAsCommaSeparatedNumbers(const CompilationResultType& result,
} // anonymous namespace
namespace glslc {
-bool FileCompiler::CompileShaderFile(const std::string& input_file,
- shaderc_shader_kind shader_stage,
- shaderc_source_language lang) {
+bool FileCompiler::CompileShaderFile(const InputFileSpec& input_file) {
std::vector<char> input_data;
- std::string path = input_file;
+ std::string path = input_file.name;
if (!shaderc_util::ReadFile(path, &input_data)) {
return false;
}
- std::string output_name = GetOutputFileName(input_file);
+ std::string output_name = GetOutputFileName(input_file.name);
std::ofstream potential_file_stream;
std::ostream* output_stream =
@@ -80,7 +78,7 @@ bool FileCompiler::CompileShaderFile(const std::string& input_file,
// An error message has already been emitted to the stderr stream.
return false;
}
- string_piece error_file_name = input_file;
+ string_piece error_file_name = input_file.name;
if (error_file_name == "-") {
// If the input file was stdin, we want to output errors as <stdin>.
@@ -100,12 +98,12 @@ bool FileCompiler::CompileShaderFile(const std::string& input_file,
const auto& used_source_files = includer->file_path_trace();
options_.SetIncluder(std::move(includer));
- if (shader_stage == shaderc_spirv_assembly) {
+ if (input_file.stage == shaderc_spirv_assembly) {
// Only act if the requested target is SPIR-V binary.
if (output_type_ == OutputType::SpirvBinary) {
const auto result =
compiler_.AssembleToSpv(source_string.data(), source_string.size());
- return EmitCompiledResult(result, input_file, error_file_name,
+ return EmitCompiledResult(result, input_file.name, error_file_name,
used_source_files, output_stream);
} else {
return true;
@@ -115,28 +113,30 @@ bool FileCompiler::CompileShaderFile(const std::string& input_file,
// Set the language. Since we only use the options object in this
// method, then it's ok to always set it without resetting it after
// compilation. A subsequent compilation will set it again anyway.
- options_.SetSourceLanguage(lang);
+ options_.SetSourceLanguage(input_file.language);
switch (output_type_) {
case OutputType::SpirvBinary: {
const auto result = compiler_.CompileGlslToSpv(
- source_string.data(), source_string.size(), shader_stage,
- error_file_name.data(), options_);
- return EmitCompiledResult(result, input_file, error_file_name,
+ source_string.data(), source_string.size(), input_file.stage,
+ error_file_name.data(), input_file.entry_point_name.c_str(),
+ options_);
+ return EmitCompiledResult(result, input_file.name, error_file_name,
used_source_files, output_stream);
}
case OutputType::SpirvAssemblyText: {
const auto result = compiler_.CompileGlslToSpvAssembly(
- source_string.data(), source_string.size(), shader_stage,
- error_file_name.data(), options_);
- return EmitCompiledResult(result, input_file, error_file_name,
+ source_string.data(), source_string.size(), input_file.stage,
+ error_file_name.data(), input_file.entry_point_name.c_str(),
+ options_);
+ return EmitCompiledResult(result, input_file.name, error_file_name,
used_source_files, output_stream);
}
case OutputType::PreprocessedText: {
const auto result = compiler_.PreprocessGlsl(
- source_string.data(), source_string.size(), shader_stage,
+ source_string.data(), source_string.size(), input_file.stage,
error_file_name.data(), options_);
- return EmitCompiledResult(result, input_file, error_file_name,
+ return EmitCompiledResult(result, input_file.name, error_file_name,
used_source_files, output_stream);
}
}
diff --git a/glslc/src/file_compiler.h b/glslc/src/file_compiler.h
index 4d8cb35..2f45e92 100644
--- a/glslc/src/file_compiler.h
+++ b/glslc/src/file_compiler.h
@@ -25,6 +25,14 @@
namespace glslc {
+// Describes an input file to be compiled.
+struct InputFileSpec {
+ std::string name;
+ shaderc_shader_kind stage;
+ shaderc_source_language language;
+ std::string entry_point_name;
+};
+
// Context for managing compilation of source GLSL files into destination
// SPIR-V files or preprocessed output.
class FileCompiler {
@@ -46,10 +54,11 @@ class FileCompiler {
total_warnings_(0),
total_errors_(0) {}
- // Compiles a shader received in input_file, returning true on success and
- // false otherwise. If force_shader_stage is not shaderc_glsl_infer_source or
- // any default shader stage then the given shader_stage will be used,
- // otherwise it will be determined from the source or the file type.
+ // Compiles a shader received as specified by input_file, returning true
+ // on success and false otherwise. If force_shader_stage is not
+ // shaderc_glsl_infer_source or any default shader stage then the given
+ // shader_stage will be used, otherwise it will be determined from the source
+ // or the file type.
//
// Places the compilation output into a new file whose name is derived from
// input_file according to the rules from glslc/README.asciidoc.
@@ -59,9 +68,7 @@ class FileCompiler {
//
// Any errors/warnings found in the shader source will be output to std::cerr
// and increment the counts reported by OutputMessages().
- bool CompileShaderFile(const std::string& input_file,
- shaderc_shader_kind shader_stage,
- shaderc_source_language lang);
+ bool CompileShaderFile(const InputFileSpec& input_file);
// Adds a directory to be searched when processing #include directives.
//
diff --git a/glslc/src/main.cc b/glslc/src/main.cc
index 193bc7f..571e65f 100644
--- a/glslc/src/main.cc
+++ b/glslc/src/main.cc
@@ -33,13 +33,6 @@ using shaderc_util::string_piece;
namespace {
-// Describes an input file to be compiled.
-struct InputFileSpec {
- std::string name;
- shaderc_shader_kind stage;
- shaderc_source_language language;
-};
-
// Prints the help message.
void PrintHelp(std::ostream* out) {
*out << R"(glslc - Compile shaders into SPIR-V
@@ -57,6 +50,9 @@ Options:
Treat subsequent input files as having stage <stage>.
Valid stages are vertex, fragment, tesscontrol, tesseval,
geometry, and compute.
+ -fentry-point=<name>
+ Specify the entry point name for HLSL compilation, for
+ all subsequent source files. Default is "main".
-g Generate source-level debug information.
Currently this option has no effect.
--help Display available options.
@@ -120,11 +116,12 @@ const char kBuildVersion[] =
} // anonymous namespace
int main(int argc, char** argv) {
- std::vector<InputFileSpec> input_files;
+ std::vector<glslc::InputFileSpec> input_files;
shaderc_shader_kind current_fshader_stage = shaderc_glsl_infer_from_source;
bool source_language_forced = false;
shaderc_source_language current_source_language =
shaderc_source_language_glsl;
+ std::string current_entry_point_name("main");
glslc::FileCompiler compiler;
bool success = true;
bool has_stdin_input = false;
@@ -156,6 +153,9 @@ int main(int argc, char** argv) {
<< std::endl;
return 1;
}
+ } else if (arg.starts_with("-fentry-point=")) {
+ current_entry_point_name =
+ arg.substr(std::strlen("-fentry-point=")).str();
} else if (arg.starts_with("-std=")) {
const string_piece standard = arg.substr(std::strlen("-std="));
int version;
@@ -358,11 +358,11 @@ int main(int argc, char** argv) {
// already been emitted before). So we should deduce the shader kind
// from the file name. If current_fshader_stage is specifed to one of
// the forced shader kinds, use that for the following compilation.
- input_files.emplace_back(InputFileSpec{
+ input_files.emplace_back(glslc::InputFileSpec{
arg.str(), (current_fshader_stage == shaderc_glsl_infer_from_source
? glslc::DeduceDefaultShaderKindFromFileName(arg)
: current_fshader_stage),
- language});
+ language, current_entry_point_name});
}
}
@@ -371,8 +371,7 @@ int main(int argc, char** argv) {
if (!success) return 1;
for (const auto& input_file : input_files) {
- success &= compiler.CompileShaderFile(input_file.name, input_file.stage,
- input_file.language);
+ success &= compiler.CompileShaderFile(input_file);
}
compiler.OutputMessages();
diff --git a/glslc/test/CMakeLists.txt b/glslc/test/CMakeLists.txt
index bb82a70..cca9314 100644
--- a/glslc/test/CMakeLists.txt
+++ b/glslc/test/CMakeLists.txt
@@ -5,5 +5,6 @@ if(${SHADERC_ENABLE_TESTS})
add_test(NAME glslc_tests
COMMAND ${PYTHON_EXE}
${CMAKE_CURRENT_SOURCE_DIR}/glslc_test_framework.py
- $<TARGET_FILE:glslc_exe> --test-dir ${CMAKE_CURRENT_SOURCE_DIR})
+ $<TARGET_FILE:glslc_exe> $<TARGET_FILE:spirv-dis>
+ --test-dir ${CMAKE_CURRENT_SOURCE_DIR})
endif()
diff --git a/glslc/test/expect.py b/glslc/test/expect.py
index 00e31d4..cfd0524 100644
--- a/glslc/test/expect.py
+++ b/glslc/test/expect.py
@@ -21,6 +21,7 @@ methods in the mixin classes.
import difflib
import os
import re
+import subprocess
from glslc_test_framework import GlslCTest
@@ -212,6 +213,33 @@ class ValidObjectFile(SuccessfulReturn, CorrectObjectFilePreamble):
return True, ''
+class ValidObjectFileWithAssemblySubstr(SuccessfulReturn, CorrectObjectFilePreamble):
+ """Mixin class for checking that every input file generates a valid object
+ file following the object file naming rule, there is no output on
+ stdout/stderr, and the disassmbly contains a specified substring per input."""
+
+ def check_object_file_disassembly(self, status):
+ for an_input in status.inputs:
+ object_filename = get_object_filename(an_input.filename)
+ obj_file = str(os.path.join(status.directory, object_filename))
+ success, message = self.verify_object_file_preamble(obj_file)
+ if not success:
+ return False, message
+ cmd = [status.test_manager.disassembler_path, '--no-color', obj_file]
+ process = subprocess.Popen(
+ args=cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE, cwd=status.directory)
+ output = process.communicate(None)
+ disassembly = output[0]
+ if not isinstance(an_input.assembly_substr, str):
+ return False, "Missing assembly_substr member"
+ if an_input.assembly_substr not in disassembly:
+ return False, ('Incorrect disassembly output:\n{asm}\n'
+ 'Expected substring not found:\n{exp}'.format(
+ asm=disassembly, exp=an_input.assembly_substr))
+ return True, ''
+
+
class ValidNamedObjectFile(SuccessfulReturn, CorrectObjectFilePreamble):
"""Mixin class for checking that a list of object files with the given
names are correctly generated, and there is no output on stdout/stderr.
@@ -280,6 +308,32 @@ class ValidAssemblyFile(SuccessfulReturn, CorrectAssemblyFilePreamble):
return True, ''
+class ValidAssemblyFileWithSubstr(ValidAssemblyFile):
+ """Mixin class for checking that every input file generates a valid assembly
+ file following the assembly file naming rule, there is no output on
+ stdout/stderr, and all assembly files have the given substring specified
+ by expected_assembly_substr.
+
+ To mix in this class, subclasses need to provde expected_assembly_substr
+ as the expected substring.
+ """
+
+ def check_assembly_with_substr(self, status):
+ for input_filename in status.input_filenames:
+ assembly_filename = get_assembly_filename(input_filename)
+ success, message = self.verify_assembly_file_preamble(
+ os.path.join(status.directory, assembly_filename))
+ if not success:
+ return False, message
+ with open(assembly_filename, 'r') as f:
+ content = f.read()
+ if self.expected_assembly_substr not in convert_to_unix_line_endings(content):
+ return False, ('Incorrect assembly output:\n{asm}\n'
+ 'Expected substring not found:\n{exp}'.format(
+ asm=content, exp=self.expected_assembly_substr))
+ return True, ''
+
+
class ValidNamedAssemblyFile(SuccessfulReturn, CorrectAssemblyFilePreamble):
"""Mixin class for checking that a list of assembly files with the given
names are correctly generated, and there is no output on stdout/stderr.
diff --git a/glslc/test/expect_nosetest.py b/glslc/test/expect_nosetest.py
index dc33e4d..567b0a0 100644
--- a/glslc/test/expect_nosetest.py
+++ b/glslc/test/expect_nosetest.py
@@ -41,20 +41,20 @@ class TestStdoutMatchADotC(expect.StdoutMatch):
def nosetest_stdout_match_regex_has_match():
test = TestStdoutMatchADotC()
- status = TestStatus(returncode=0, stdout='0abc1', stderr=None,
- directory=None, input_filenames=None)
+ status = TestStatus(test_manager=None, returncode=0, stdout='0abc1',
+ stderr=None, directory=None, inputs=None, input_filenames=None)
assert_true(test.check_stdout_match(status)[0])
def nosetest_stdout_match_regex_no_match():
test = TestStdoutMatchADotC()
- status = TestStatus(returncode=0, stdout='ab', stderr=None,
- directory=None, input_filenames=None)
+ status = TestStatus(test_manager=None, returncode=0, stdout='ab',
+ stderr=None, directory=None, inputs=None, input_filenames=None)
assert_false(test.check_stdout_match(status)[0])
def nosetest_stdout_match_regex_empty_stdout():
test = TestStdoutMatchADotC()
- status = TestStatus(returncode=0, stdout='', stderr=None,
- directory=None, input_filenames=None)
+ status = TestStatus(test_manager=None, returncode=0, stdout='', stderr=None,
+ directory=None, inputs=None, input_filenames=None)
assert_false(test.check_stdout_match(status)[0])
diff --git a/glslc/test/glslc_test_framework.py b/glslc/test/glslc_test_framework.py
index 9454a66..6bf43a7 100755
--- a/glslc/test/glslc_test_framework.py
+++ b/glslc/test/glslc_test_framework.py
@@ -28,7 +28,7 @@ case is then run by the following steps:
The transformed list elements are then supplied as glslc arguments.
3. If the environment member variable exists, its write() method will be
invoked.
- 4. All expected_* member varibles will be inspected and all placeholders in
+ 4. All expected_* member variables will be inspected and all placeholders in
them will be expanded by calling instantiate_for_expectation() on those
placeholders. After placeholder expansion, if the expected_* variable is
a list, its element will be joined together with '' to form a single
@@ -141,12 +141,15 @@ class GlslCTest:
class TestStatus:
"""A struct for holding run status of a test case."""
- def __init__(self, returncode, stdout, stderr, directory, input_filenames):
+ def __init__(self, test_manager, returncode, stdout, stderr, directory, inputs, input_filenames):
+ self.test_manager = test_manager
self.returncode = returncode
self.stdout = stdout
self.stderr = stderr
# temporary directory where the test runs
self.directory = directory
+ # List of inputs, as PlaceHolder objects.
+ self.inputs = inputs
# the names of input shader files (potentially including paths)
self.input_filenames = input_filenames
@@ -198,8 +201,9 @@ def inside_glslc_testsuite(testsuite_name):
class TestManager:
"""Manages and runs a set of tests."""
- def __init__(self, executable_path):
+ def __init__(self, executable_path, disassembler_path):
self.executable_path = executable_path
+ self.disassembler_path = disassembler_path
self.num_successes = 0
self.num_failures = 0
self.num_tests = 0
@@ -236,7 +240,8 @@ class TestCase:
def __init__(self, test, test_manager):
self.test = test
self.test_manager = test_manager
- self.file_shaders = [] # filenames of shader files
+ self.inputs = [] # inputs, as PlaceHolder objects.
+ self.file_shaders = [] # filenames of shader files.
self.stdin_shader = None # text to be passed to glslc as stdin
def setUp(self):
@@ -250,8 +255,8 @@ class TestCase:
if isinstance(arg, PlaceHolder) else arg
for arg in self.test.glslc_args]
# Get all shader files' names
- self.file_shaders = [
- arg.filename for arg in glslc_args if isinstance(arg, PlaceHolder)]
+ self.inputs = [arg for arg in glslc_args if isinstance(arg, PlaceHolder)]
+ self.file_shaders = [arg.filename for arg in self.inputs]
if 'environment' in get_all_variables(self.test):
self.test.environment.write(self.directory)
@@ -294,8 +299,9 @@ class TestCase:
cwd=self.directory)
output = process.communicate(self.stdin_shader)
test_status = TestStatus(
+ self.test_manager,
process.returncode, output[0], output[1],
- self.directory, self.file_shaders)
+ self.directory, self.inputs, self.file_shaders)
run_results = [getattr(self.test, test_method)(test_status)
for test_method in get_all_test_methods(
self.test.__class__)]
@@ -313,6 +319,8 @@ def main():
parser = argparse.ArgumentParser()
parser.add_argument('glslc', metavar='path/to/glslc', type=str, nargs=1,
help='Path to glslc')
+ parser.add_argument('spirvdis', metavar='path/to/glslc', type=str, nargs=1,
+ help='Path to spirv-dis')
parser.add_argument('--leave-output', action='store_const', const=1,
help='Do not clean up temporary directories')
parser.add_argument('--test-dir', nargs=1,
@@ -322,7 +330,7 @@ def main():
root_dir = os.getcwd()
if args.test_dir:
root_dir = args.test_dir[0]
- manager = TestManager(args.glslc[0])
+ manager = TestManager(args.glslc[0], args.spirvdis[0])
if args.leave_output:
manager.leave_output = True
for root, _, filenames in os.walk(root_dir):
diff --git a/glslc/test/option_dash_x.py b/glslc/test/option_dash_x.py
index 43b8b96..3645340 100644
--- a/glslc/test/option_dash_x.py
+++ b/glslc/test/option_dash_x.py
@@ -51,14 +51,6 @@ class TestDashXGlslOnHlslShader(expect.ErrorMessageSubstr):
@inside_glslc_testsuite('OptionDashX')
-class TestDashXHlslOnHlslShader(expect.ValidObjectFile):
- """Tests -x hlsl on an HLSL shader."""
-
- shader = FileShader(HLSL_VERTEX_SHADER, '.vert')
- glslc_args = ['-x', 'hlsl', '-c', shader]
-
-
-@inside_glslc_testsuite('OptionDashX')
class TestDashXHlslOnGlslShader(expect.ErrorMessageSubstr):
"""Tests -x hlsl on a GLSL shader."""
diff --git a/glslc/test/option_fentry_point.py b/glslc/test/option_fentry_point.py
new file mode 100644
index 0000000..5d8f96f
--- /dev/null
+++ b/glslc/test/option_fentry_point.py
@@ -0,0 +1,109 @@
+# Copyright 2016 The Shaderc Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import expect
+from glslc_test_framework import inside_glslc_testsuite
+from placeholder import FileShader
+
+MINIMAL_SHADER = "#version 140\nvoid main(){}"
+# This one is valid GLSL but not valid HLSL.
+GLSL_VERTEX_SHADER = "#version 140\nvoid main(){ gl_Position = vec4(1.0);}"
+# This one is valid HLSL but not valid GLSL.
+HLSL_VERTEX_SHADER = "float4 EntryPoint() : SV_POSITION { return float4(1.0); }"
+HLSL_VERTEX_SHADER_WITH_MAIN = "float4 main() : SV_POSITION { return float4(1.0); }"
+HLSL_VERTEX_SHADER_WITH_FOOBAR = "float4 Foobar() : SV_POSITION { return float4(1.0); }"
+
+# Expected assembly code within certain shaders.
+ASSEMBLY_ENTRY_POINT = "OpEntryPoint Vertex %EntryPoint \"EntryPoint\""
+ASSEMBLY_MAIN = "OpEntryPoint Vertex %main \"main\""
+ASSEMBLY_FOOBAR = "OpEntryPoint Vertex %Foobar \"Foobar\""
+
+
+@inside_glslc_testsuite('OptionFEntryPoint')
+class TestEntryPointDefaultsToMainForGlsl(expect.ValidAssemblyFileWithSubstr):
+ """Tests that entry point name defaults to "main" in a GLSL shader."""
+
+ shader = FileShader(GLSL_VERTEX_SHADER, '.vert')
+ glslc_args = ['-S', shader]
+ expected_assembly_substr = ASSEMBLY_MAIN
+
+
+@inside_glslc_testsuite('OptionFEntryPoint')
+class TestEntryPointDefaultsToMainForHlsl(expect.ValidAssemblyFileWithSubstr):
+ """Tests that entry point name defaults to "main" in an HLSL shader."""
+
+ shader = FileShader(HLSL_VERTEX_SHADER_WITH_MAIN, '.vert')
+ glslc_args = ['-x', 'hlsl', '-S', shader]
+ expected_assembly_substr = ASSEMBLY_MAIN
+
+
+@inside_glslc_testsuite('OptionFEntryPoint')
+class TestFEntryPointMainOnGlslShader(expect.ValidAssemblyFileWithSubstr):
+ """Tests -fentry-point=main with a GLSL shader."""
+
+ shader = FileShader(GLSL_VERTEX_SHADER, '.vert')
+ glslc_args = ['-fentry-point=main', '-S', shader]
+ expected_assembly_substr = ASSEMBLY_MAIN
+
+
+@inside_glslc_testsuite('OptionFEntryPoint')
+class TestFEntryPointMainOnHlslShader(expect.ValidAssemblyFileWithSubstr):
+ """Tests -x hlsl on an HLSL shader with -fentry-point=main and -S."""
+
+ shader = FileShader(HLSL_VERTEX_SHADER, '.vert')
+ glslc_args = ['-x', 'hlsl', '-fentry-point=main', '-S', shader]
+ expected_assembly_substr = ASSEMBLY_MAIN
+
+
+@inside_glslc_testsuite('OptionFEntryPoint')
+class TestFEntryPointSpecifiedOnHlslShaderInDisassembly(expect.ValidObjectFileWithAssemblySubstr):
+ """Tests -x hlsl on an HLSL shader with -fentry-point=EntryPoint."""
+
+ shader = FileShader(HLSL_VERTEX_SHADER, '.vert', assembly_substr=ASSEMBLY_ENTRY_POINT)
+ glslc_args = ['-x', 'hlsl', '-fentry-point=EntryPoint', '-c', shader]
+
+
+@inside_glslc_testsuite('OptionFEntryPoint')
+class TestFEntryPointAffectsSubsequentShaderFiles(expect.ValidObjectFileWithAssemblySubstr):
+ """Tests -x hlsl affects several subsequent shader source files."""
+
+ shader1 = FileShader(HLSL_VERTEX_SHADER, '.vert', assembly_substr=ASSEMBLY_ENTRY_POINT)
+ shader2 = FileShader(HLSL_VERTEX_SHADER, '.vert', assembly_substr=ASSEMBLY_ENTRY_POINT)
+ glslc_args = ['-x', 'hlsl', '-fentry-point=EntryPoint', '-c', shader1, shader2]
+
+
+@inside_glslc_testsuite('OptionFEntryPoint')
+class TestFEntryPointOverridesItself(expect.ValidObjectFileWithAssemblySubstr):
+ """Tests that a later -fentry-point option overrides an earlier use."""
+
+ shader = FileShader(HLSL_VERTEX_SHADER, '.vert', assembly_substr=ASSEMBLY_ENTRY_POINT)
+ glslc_args = ['-x', 'hlsl', '-fentry-point=foobar', '-fentry-point=EntryPoint',
+ '-c', shader]
+
+
+@inside_glslc_testsuite('OptionFEntryPoint')
+class TestFEntryPointDefaultAndTwoOthers(expect.ValidObjectFileWithAssemblySubstr):
+ """Tests three shaders with different entry point names. The first uses "main"
+ with default entry point processing, and the remaining shaders get their
+ own -fentry-point argument."""
+
+ shaderMain = FileShader(HLSL_VERTEX_SHADER_WITH_MAIN, '.vert',
+ assembly_substr=ASSEMBLY_MAIN)
+ shaderEntryPoint = FileShader(HLSL_VERTEX_SHADER, '.vert',
+ assembly_substr=ASSEMBLY_ENTRY_POINT)
+ shaderFoobar = FileShader(HLSL_VERTEX_SHADER_WITH_FOOBAR, '.vert',
+ assembly_substr=ASSEMBLY_FOOBAR)
+ glslc_args = ['-x', 'hlsl', '-c', shaderMain,
+ '-fentry-point=EntryPoint', shaderEntryPoint,
+ '-fentry-point=Foobar', shaderFoobar]
diff --git a/glslc/test/parameter_tests.py b/glslc/test/parameter_tests.py
index ff450b1..cbb6f11 100644
--- a/glslc/test/parameter_tests.py
+++ b/glslc/test/parameter_tests.py
@@ -61,6 +61,9 @@ Options:
Treat subsequent input files as having stage <stage>.
Valid stages are vertex, fragment, tesscontrol, tesseval,
geometry, and compute.
+ -fentry-point=<name>
+ Specify the entry point name for HLSL compilation, for
+ all subsequent source files. Default is "main".
-g Generate source-level debug information.
Currently this option has no effect.
--help Display available options.
diff --git a/glslc/test/placeholder.py b/glslc/test/placeholder.py
index 9c5bcfc..8a701bf 100644
--- a/glslc/test/placeholder.py
+++ b/glslc/test/placeholder.py
@@ -59,12 +59,15 @@ class PlaceHolder(object):
class FileShader(PlaceHolder):
"""Stands for a shader whose source code is in a file."""
- def __init__(self, source, suffix):
+ def __init__(self, source, suffix, assembly_substr=None):
assert isinstance(source, str)
assert isinstance(suffix, str)
self.source = source
self.suffix = suffix
self.filename = None
+ # If provided, this is a substring which is expected to be in
+ # the disassembly of the module generated from this input file.
+ self.assembly_substr = assembly_substr
def instantiate_for_glslc_args(self, testcase):
"""Creates a temporary file and writes the source into it.