Skip to content

Commit

Permalink
Add -fentry-point to glslc
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
dneto0 committed Nov 16, 2016
1 parent 725a8fd commit 89eefb9
Show file tree
Hide file tree
Showing 13 changed files with 245 additions and 60 deletions.
2 changes: 2 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 7 additions & 0 deletions glslc/README.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Clang-compatible arguments.
glslc [-c|-S|-E]
[-x ...] [-std=standard]
[-fshader-stage=...]
[-fentry-point=...]
[--target-env=...]
[-g]
[-O0|-Os]
Expand Down Expand Up @@ -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
Expand Down
34 changes: 17 additions & 17 deletions glslc/src/file_compiler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand All @@ -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>.
Expand All @@ -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;
Expand All @@ -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);
}
}
Expand Down
21 changes: 14 additions & 7 deletions glslc/src/file_compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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.
Expand All @@ -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.
//
Expand Down
23 changes: 11 additions & 12 deletions glslc/src/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -57,6 +50,9 @@ An input file of - represents standard input.
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.
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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});
}
}

Expand All @@ -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();
Expand Down
3 changes: 2 additions & 1 deletion glslc/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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()
54 changes: 54 additions & 0 deletions glslc/test/expect.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import difflib
import os
import re
import subprocess
from glslc_test_framework import GlslCTest


Expand Down Expand Up @@ -212,6 +213,33 @@ def check_object_file_preamble(self, status):
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.
Expand Down Expand Up @@ -280,6 +308,32 @@ def check_assembly_file_preamble(self, status):
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.
Expand Down
12 changes: 6 additions & 6 deletions glslc/test/expect_nosetest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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])

0 comments on commit 89eefb9

Please sign in to comment.