aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Neto <dneto@google.com>2016-11-17 10:52:48 -0500
committerDavid Neto <dneto@google.com>2016-11-17 13:14:41 -0500
commit1ef0a89bcda32ab4befab6992752eac4c05f2c41 (patch)
tree609a95c120aa0c6377d8dfba152e475e590a0d9f
parent89eefb94d69e07576682e44cb3d55fa332ce2e91 (diff)
downloadshaderc-1ef0a89bcda32ab4befab6992752eac4c05f2c41.tar.gz
Support resource limits in C, C++ API
-rw-r--r--libshaderc/include/shaderc/shaderc.h91
-rw-r--r--libshaderc/include/shaderc/shaderc.hpp5
-rw-r--r--libshaderc/src/shaderc.cc19
-rw-r--r--libshaderc/src/shaderc_cpp_test.cc48
-rw-r--r--libshaderc/src/shaderc_test.cc52
-rw-r--r--libshaderc_util/include/libshaderc_util/compiler.h23
-rw-r--r--libshaderc_util/include/libshaderc_util/resources.h5
-rw-r--r--libshaderc_util/include/libshaderc_util/resources.inc107
-rw-r--r--libshaderc_util/src/compiler.cc36
-rw-r--r--libshaderc_util/src/compiler_test.cc70
10 files changed, 445 insertions, 11 deletions
diff --git a/libshaderc/include/shaderc/shaderc.h b/libshaderc/include/shaderc/shaderc.h
index 64d94ea..26d5421 100644
--- a/libshaderc/include/shaderc/shaderc.h
+++ b/libshaderc/include/shaderc/shaderc.h
@@ -86,6 +86,93 @@ typedef enum {
shaderc_optimization_level_size, // optimize towards reducing code size
} shaderc_optimization_level;
+// Resource limits.
+typedef enum {
+ shaderc_limit_max_lights,
+ shaderc_limit_max_clip_planes,
+ shaderc_limit_max_texture_units,
+ shaderc_limit_max_texture_coords,
+ shaderc_limit_max_vertex_attribs,
+ shaderc_limit_max_vertex_uniform_components,
+ shaderc_limit_max_varying_floats,
+ shaderc_limit_max_vertex_texture_image_units,
+ shaderc_limit_max_combined_texture_image_units,
+ shaderc_limit_max_texture_image_units,
+ shaderc_limit_max_fragment_uniform_components,
+ shaderc_limit_max_draw_buffers,
+ shaderc_limit_max_vertex_uniform_vectors,
+ shaderc_limit_max_varying_vectors,
+ shaderc_limit_max_fragment_uniform_vectors,
+ shaderc_limit_max_vertex_output_vectors,
+ shaderc_limit_max_fragment_input_vectors,
+ shaderc_limit_min_program_texel_offset,
+ shaderc_limit_max_program_texel_offset,
+ shaderc_limit_max_clip_distances,
+ shaderc_limit_max_compute_work_group_count_x,
+ shaderc_limit_max_compute_work_group_count_y,
+ shaderc_limit_max_compute_work_group_count_z,
+ shaderc_limit_max_compute_work_group_size_x,
+ shaderc_limit_max_compute_work_group_size_y,
+ shaderc_limit_max_compute_work_group_size_z,
+ shaderc_limit_max_compute_uniform_components,
+ shaderc_limit_max_compute_texture_image_units,
+ shaderc_limit_max_compute_image_uniforms,
+ shaderc_limit_max_compute_atomic_counters,
+ shaderc_limit_max_compute_atomic_counter_buffers,
+ shaderc_limit_max_varying_components,
+ shaderc_limit_max_vertex_output_components,
+ shaderc_limit_max_geometry_input_components,
+ shaderc_limit_max_geometry_output_components,
+ shaderc_limit_max_fragment_input_components,
+ shaderc_limit_max_image_units,
+ shaderc_limit_max_combined_image_units_and_fragment_outputs,
+ shaderc_limit_max_combined_shader_output_resources,
+ shaderc_limit_max_image_samples,
+ shaderc_limit_max_vertex_image_uniforms,
+ shaderc_limit_max_tess_control_image_uniforms,
+ shaderc_limit_max_tess_evaluation_image_uniforms,
+ shaderc_limit_max_geometry_image_uniforms,
+ shaderc_limit_max_fragment_image_uniforms,
+ shaderc_limit_max_combined_image_uniforms,
+ shaderc_limit_max_geometry_texture_image_units,
+ shaderc_limit_max_geometry_output_vertices,
+ shaderc_limit_max_geometry_total_output_components,
+ shaderc_limit_max_geometry_uniform_components,
+ shaderc_limit_max_geometry_varying_components,
+ shaderc_limit_max_tess_control_input_components,
+ shaderc_limit_max_tess_control_output_components,
+ shaderc_limit_max_tess_control_texture_image_units,
+ shaderc_limit_max_tess_control_uniform_components,
+ shaderc_limit_max_tess_control_total_output_components,
+ shaderc_limit_max_tess_evaluation_input_components,
+ shaderc_limit_max_tess_evaluation_output_components,
+ shaderc_limit_max_tess_evaluation_texture_image_units,
+ shaderc_limit_max_tess_evaluation_uniform_components,
+ shaderc_limit_max_tess_patch_components,
+ shaderc_limit_max_patch_vertices,
+ shaderc_limit_max_tess_gen_level,
+ shaderc_limit_max_viewports,
+ shaderc_limit_max_vertex_atomic_counters,
+ shaderc_limit_max_tess_control_atomic_counters,
+ shaderc_limit_max_tess_evaluation_atomic_counters,
+ shaderc_limit_max_geometry_atomic_counters,
+ shaderc_limit_max_fragment_atomic_counters,
+ shaderc_limit_max_combined_atomic_counters,
+ shaderc_limit_max_atomic_counter_bindings,
+ shaderc_limit_max_vertex_atomic_counter_buffers,
+ shaderc_limit_max_tess_control_atomic_counter_buffers,
+ shaderc_limit_max_tess_evaluation_atomic_counter_buffers,
+ shaderc_limit_max_geometry_atomic_counter_buffers,
+ shaderc_limit_max_fragment_atomic_counter_buffers,
+ shaderc_limit_max_combined_atomic_counter_buffers,
+ shaderc_limit_max_atomic_counter_buffer_size,
+ shaderc_limit_max_transform_feedback_buffers,
+ shaderc_limit_max_transform_feedback_interleaved_components,
+ shaderc_limit_max_cull_distances,
+ shaderc_limit_max_combined_clip_and_cull_distances,
+ shaderc_limit_max_samples,
+} shaderc_limit;
+
// Usage examples:
//
// Aggressively release compiler resources, but spend time in initialization
@@ -255,6 +342,10 @@ void shaderc_compile_options_set_target_env(shaderc_compile_options_t options,
void shaderc_compile_options_set_warnings_as_errors(
shaderc_compile_options_t options);
+// Sets a resource limit.
+void shaderc_compile_options_set_limit(
+ shaderc_compile_options_t options, shaderc_limit limit, int value);
+
// An opaque handle to the results of a call to any shaderc_compile_into_*()
// function.
typedef struct shaderc_compilation_result* shaderc_compilation_result_t;
diff --git a/libshaderc/include/shaderc/shaderc.hpp b/libshaderc/include/shaderc/shaderc.hpp
index a3facfc..3023ebb 100644
--- a/libshaderc/include/shaderc/shaderc.hpp
+++ b/libshaderc/include/shaderc/shaderc.hpp
@@ -243,6 +243,11 @@ class CompileOptions {
shaderc_compile_options_set_warnings_as_errors(options_);
}
+ // Sets a resource limit.
+ void SetLimit(shaderc_limit limit, int value) {
+ shaderc_compile_options_set_limit(options_, limit, value);
+ }
+
private:
CompileOptions& operator=(const CompileOptions& other) = delete;
shaderc_compile_options_t options_;
diff --git a/libshaderc/src/shaderc.cc b/libshaderc/src/shaderc.cc
index 15d16d2..c7b6ef2 100644
--- a/libshaderc/src/shaderc.cc
+++ b/libshaderc/src/shaderc.cc
@@ -238,6 +238,20 @@ shaderc_util::Compiler::TargetEnv GetCompilerTargetEnv(shaderc_target_env env) {
return shaderc_util::Compiler::TargetEnv::Vulkan;
}
+// Returns the Compiler::Limit enum for the given shaderc_limit enum.
+shaderc_util::Compiler::Limit CompilerLimit(shaderc_limit limit) {
+ switch (limit) {
+#define RESOURCE(NAME,FIELD,CNAME) \
+ case shaderc_limit_##CNAME: return shaderc_util::Compiler::Limit::NAME;
+#include "libshaderc_util/resources.inc"
+#undef RESOURCE
+ default:
+ break;
+ }
+ assert(0 && "Should not have reached here");
+ return static_cast<shaderc_util::Compiler::Limit>(0);
+}
+
} // anonymous namespace
struct shaderc_compile_options {
@@ -346,6 +360,11 @@ void shaderc_compile_options_set_warnings_as_errors(
options->compiler.SetWarningsAsErrors();
}
+void shaderc_compile_options_set_limit(
+ shaderc_compile_options_t options, shaderc_limit limit, int value) {
+ options->compiler.SetLimit(CompilerLimit(limit), value);
+}
+
shaderc_compiler_t shaderc_compiler_initialize() {
static shaderc_util::GlslangInitializer* initializer =
new shaderc_util::GlslangInitializer;
diff --git a/libshaderc/src/shaderc_cpp_test.cc b/libshaderc/src/shaderc_cpp_test.cc
index 6917e59..bf5aa33 100644
--- a/libshaderc/src/shaderc_cpp_test.cc
+++ b/libshaderc/src/shaderc_cpp_test.cc
@@ -1100,4 +1100,52 @@ TEST(
HasSubstr("OpEntryPoint Vertex %EntryPoint \"EntryPoint\""));
}
+// Returns a fragment shader accessing a texture with the given
+// offset.
+std::string ShaderWithTexOffset(int offset) {
+ std::ostringstream oss;
+ oss <<
+ "#version 150\n"
+ "uniform sampler1D tex;\n"
+ "void main() { vec4 x = textureOffset(tex, 1.0, " << offset << "); }\n";
+ return oss.str();
+}
+
+// Ensure compilation is sensitive to limit setting. Sample just
+// two particular limits.
+TEST_F(CppInterface, LimitsTexelOffsetDefault) {
+ EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(-9).c_str(),
+ shaderc_glsl_fragment_shader,
+ options_));
+ EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(-8).c_str(),
+ shaderc_glsl_fragment_shader,
+ options_));
+ EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(7).c_str(),
+ shaderc_glsl_fragment_shader,
+ options_));
+ EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(8).c_str(),
+ shaderc_glsl_fragment_shader,
+ options_));
+}
+
+TEST_F(CppInterface, LimitsTexelOffsetLowerMinimum) {
+ options_.SetLimit(shaderc_limit_min_program_texel_offset, -99);
+ EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(-100).c_str(),
+ shaderc_glsl_fragment_shader,
+ options_));
+ EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(-99).c_str(),
+ shaderc_glsl_fragment_shader,
+ options_));
+}
+
+TEST_F(CppInterface, LimitsTexelOffsetHigherMaximum) {
+ options_.SetLimit(shaderc_limit_max_program_texel_offset, 10);
+ EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(10).c_str(),
+ shaderc_glsl_fragment_shader,
+ options_));
+ EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(11).c_str(),
+ shaderc_glsl_fragment_shader,
+ options_));
+}
+
} // anonymous namespace
diff --git a/libshaderc/src/shaderc_test.cc b/libshaderc/src/shaderc_test.cc
index bde5cf0..927a53d 100644
--- a/libshaderc/src/shaderc_test.cc
+++ b/libshaderc/src/shaderc_test.cc
@@ -1373,4 +1373,56 @@ TEST(EntryPointTest, LangHlslOnHlslVertexSucceedsWithGivenEntryPointName) {
<< std::string(shaderc_result_get_bytes(compilation.result()));
}
+// Returns a fragment shader accessing a texture with the given
+// offset.
+std::string ShaderWithTexOffset(int offset) {
+ std::ostringstream oss;
+ oss <<
+ "#version 150\n"
+ "uniform sampler1D tex;\n"
+ "void main() { vec4 x = textureOffset(tex, 1.0, " << offset << "); }\n";
+ return oss.str();
+}
+
+// Ensure compilation is sensitive to limit setting. Sample just
+// two particular limits.
+TEST_F(CompileStringTest, LimitsTexelOffsetDefault) {
+ EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(-9).c_str(),
+ shaderc_glsl_fragment_shader,
+ options_.get()));
+ EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(-8).c_str(),
+ shaderc_glsl_fragment_shader,
+ options_.get()));
+ EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(7).c_str(),
+ shaderc_glsl_fragment_shader,
+ options_.get()));
+ EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(8).c_str(),
+ shaderc_glsl_fragment_shader,
+ options_.get()));
+}
+
+TEST_F(CompileStringTest, LimitsTexelOffsetLowerMinimum) {
+ shaderc_compile_options_set_limit(options_.get(),
+ shaderc_limit_min_program_texel_offset,
+ -99);
+ EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(-100).c_str(),
+ shaderc_glsl_fragment_shader,
+ options_.get()));
+ EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(-99).c_str(),
+ shaderc_glsl_fragment_shader,
+ options_.get()));
+}
+
+TEST_F(CompileStringTest, LimitsTexelOffsetHigherMaximum) {
+ shaderc_compile_options_set_limit(options_.get(),
+ shaderc_limit_max_program_texel_offset,
+ 10);
+ EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(10).c_str(),
+ shaderc_glsl_fragment_shader,
+ options_.get()));
+ EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(11).c_str(),
+ shaderc_glsl_fragment_shader,
+ options_.get()));
+}
+
} // anonymous namespace
diff --git a/libshaderc_util/include/libshaderc_util/compiler.h b/libshaderc_util/include/libshaderc_util/compiler.h
index fc47766..50ab01c 100644
--- a/libshaderc_util/include/libshaderc_util/compiler.h
+++ b/libshaderc_util/include/libshaderc_util/compiler.h
@@ -26,6 +26,7 @@
#include "counting_includer.h"
#include "file_finder.h"
#include "mutex.h"
+#include "resources.h"
#include "string_piece.h"
namespace shaderc_util {
@@ -117,6 +118,13 @@ class Compiler {
Size, // Optimization towards reducing code size.
};
+ // Resource limits. These map to the "max*" fields in glslang::TBuiltInResource.
+ enum class Limit {
+#define RESOURCE(NAME,FIELD,CNAME) NAME,
+#include "resources.inc"
+#undef RESOURCE
+ };
+
// Creates an default compiler instance targeting at Vulkan environment. Uses
// version 110 and no profile specification as the default for GLSL.
Compiler()
@@ -130,7 +138,8 @@ class Compiler {
generate_debug_info_(false),
enabled_opt_passes_(),
target_env_(TargetEnv::Vulkan),
- source_language_(SourceLanguage::GLSL) {}
+ source_language_(SourceLanguage::GLSL),
+ limits_(kDefaultTBuiltInResource) {}
// Requests that the compiler place debug information into the object code,
// such as identifier names and line numbers.
@@ -163,14 +172,19 @@ class Compiler {
// subsequent CompileShader() calls.
void SetForcedVersionProfile(int version, EProfile profile);
+ // Sets a resource limit.
+ void SetLimit(Limit limit, int value);
+
+ // Returns the current limit.
+ int GetLimit(Limit limit) const;
+
// Compiles the shader source in the input_source_string parameter.
//
// If the forced_shader stage parameter is not EShLangCount then
// the shader is assumed to be of the given stage.
//
// For HLSL compilation, entry_point_name is the null-terminated string for
- // the
- // entry point. For GLSL compilation, entry_point_name is ignored, and
+ // the entry point. For GLSL compilation, entry_point_name is ignored, and
// compilation assumes the entry point is named "main".
//
// The stage_callback function will be called if a shader_stage has
@@ -310,6 +324,9 @@ class Compiler {
// The source language. Defaults to GLSL.
SourceLanguage source_language_;
+
+ // The resource limits to be used.
+ TBuiltInResource limits_;
};
// Converts a string to a vector of uint32_t by copying the content of a given
diff --git a/libshaderc_util/include/libshaderc_util/resources.h b/libshaderc_util/include/libshaderc_util/resources.h
index 5b185b8..a8f635b 100644
--- a/libshaderc_util/include/libshaderc_util/resources.h
+++ b/libshaderc_util/include/libshaderc_util/resources.h
@@ -15,10 +15,13 @@
#ifndef LIBSHADERC_UTIL_RESOURCES_H_
#define LIBSHADERC_UTIL_RESOURCES_H_
-struct TBuiltInResource;
+// We want TBuiltInResource
+#include "glslang/Include/ResourceLimits.h"
namespace shaderc_util {
+using TBuiltInResource = ::TBuiltInResource;
+
// A set of suitable defaults.
extern const TBuiltInResource kDefaultTBuiltInResource;
diff --git a/libshaderc_util/include/libshaderc_util/resources.inc b/libshaderc_util/include/libshaderc_util/resources.inc
new file mode 100644
index 0000000..8e86f01
--- /dev/null
+++ b/libshaderc_util/include/libshaderc_util/resources.inc
@@ -0,0 +1,107 @@
+// 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.
+
+// These are the resource limits in a glslang::TBuiltInResource.
+// The first field is the string name to be used in a configuration setting.
+// The second field is the fieldname in TBuiltInResource.
+// The third field is the enum name fragment for shaderc_limit.
+//
+// TODO(dneto): Consider using a single list of names, but use a Python script
+// to generate *this* file. The original data file would have the first field,
+// then generate the second field by lowering the case of the first letter, and
+// generate the third field by taking the second field, and converting a
+// lower-to-upper case transition into an underscore with lower-case.
+RESOURCE(MaxLights,maxLights,max_lights)
+RESOURCE(MaxClipPlanes,maxClipPlanes,max_clip_planes)
+RESOURCE(MaxTextureUnits,maxTextureUnits,max_texture_units)
+RESOURCE(MaxTextureCoords,maxTextureCoords,max_texture_coords)
+RESOURCE(MaxVertexAttribs,maxVertexAttribs,max_vertex_attribs)
+RESOURCE(MaxVertexUniformComponents,maxVertexUniformComponents,max_vertex_uniform_components)
+RESOURCE(MaxVaryingFloats,maxVaryingFloats,max_varying_floats)
+RESOURCE(MaxVertexTextureImageUnits,maxVertexTextureImageUnits,max_vertex_texture_image_units)
+RESOURCE(MaxCombinedTextureImageUnits,maxCombinedTextureImageUnits,max_combined_texture_image_units)
+RESOURCE(MaxTextureImageUnits,maxTextureImageUnits,max_texture_image_units)
+RESOURCE(MaxFragmentUniformComponents,maxFragmentUniformComponents,max_fragment_uniform_components)
+RESOURCE(MaxDrawBuffers,maxDrawBuffers,max_draw_buffers)
+RESOURCE(MaxVertexUniformVectors,maxVertexUniformVectors,max_vertex_uniform_vectors)
+RESOURCE(MaxVaryingVectors,maxVaryingVectors,max_varying_vectors)
+RESOURCE(MaxFragmentUniformVectors,maxFragmentUniformVectors,max_fragment_uniform_vectors)
+RESOURCE(MaxVertexOutputVectors,maxVertexOutputVectors,max_vertex_output_vectors)
+RESOURCE(MaxFragmentInputVectors,maxFragmentInputVectors,max_fragment_input_vectors)
+RESOURCE(MinProgramTexelOffset,minProgramTexelOffset,min_program_texel_offset)
+RESOURCE(MaxProgramTexelOffset,maxProgramTexelOffset,max_program_texel_offset)
+RESOURCE(MaxClipDistances,maxClipDistances,max_clip_distances)
+RESOURCE(MaxComputeWorkGroupCountX,maxComputeWorkGroupCountX,max_compute_work_group_count_x)
+RESOURCE(MaxComputeWorkGroupCountY,maxComputeWorkGroupCountY,max_compute_work_group_count_y)
+RESOURCE(MaxComputeWorkGroupCountZ,maxComputeWorkGroupCountZ,max_compute_work_group_count_z)
+RESOURCE(MaxComputeWorkGroupSizeX,maxComputeWorkGroupSizeX,max_compute_work_group_size_x)
+RESOURCE(MaxComputeWorkGroupSizeY,maxComputeWorkGroupSizeY,max_compute_work_group_size_y)
+RESOURCE(MaxComputeWorkGroupSizeZ,maxComputeWorkGroupSizeZ,max_compute_work_group_size_z)
+RESOURCE(MaxComputeUniformComponents,maxComputeUniformComponents,max_compute_uniform_components)
+RESOURCE(MaxComputeTextureImageUnits,maxComputeTextureImageUnits,max_compute_texture_image_units)
+RESOURCE(MaxComputeImageUniforms,maxComputeImageUniforms,max_compute_image_uniforms)
+RESOURCE(MaxComputeAtomicCounters,maxComputeAtomicCounters,max_compute_atomic_counters)
+RESOURCE(MaxComputeAtomicCounterBuffers,maxComputeAtomicCounterBuffers,max_compute_atomic_counter_buffers)
+RESOURCE(MaxVaryingComponents,maxVaryingComponents,max_varying_components)
+RESOURCE(MaxVertexOutputComponents,maxVertexOutputComponents,max_vertex_output_components)
+RESOURCE(MaxGeometryInputComponents,maxGeometryInputComponents,max_geometry_input_components)
+RESOURCE(MaxGeometryOutputComponents,maxGeometryOutputComponents,max_geometry_output_components)
+RESOURCE(MaxFragmentInputComponents,maxFragmentInputComponents,max_fragment_input_components)
+RESOURCE(MaxImageUnits,maxImageUnits,max_image_units)
+RESOURCE(MaxCombinedImageUnitsAndFragmentOutputs,maxCombinedImageUnitsAndFragmentOutputs,max_combined_image_units_and_fragment_outputs)
+RESOURCE(MaxCombinedShaderOutputResources,maxCombinedShaderOutputResources,max_combined_shader_output_resources)
+RESOURCE(MaxImageSamples,maxImageSamples,max_image_samples)
+RESOURCE(MaxVertexImageUniforms,maxVertexImageUniforms,max_vertex_image_uniforms)
+RESOURCE(MaxTessControlImageUniforms,maxTessControlImageUniforms,max_tess_control_image_uniforms)
+RESOURCE(MaxTessEvaluationImageUniforms,maxTessEvaluationImageUniforms,max_tess_evaluation_image_uniforms)
+RESOURCE(MaxGeometryImageUniforms,maxGeometryImageUniforms,max_geometry_image_uniforms)
+RESOURCE(MaxFragmentImageUniforms,maxFragmentImageUniforms,max_fragment_image_uniforms)
+RESOURCE(MaxCombinedImageUniforms,maxCombinedImageUniforms,max_combined_image_uniforms)
+RESOURCE(MaxGeometryTextureImageUnits,maxGeometryTextureImageUnits,max_geometry_texture_image_units)
+RESOURCE(MaxGeometryOutputVertices,maxGeometryOutputVertices,max_geometry_output_vertices)
+RESOURCE(MaxGeometryTotalOutputComponents,maxGeometryTotalOutputComponents,max_geometry_total_output_components)
+RESOURCE(MaxGeometryUniformComponents,maxGeometryUniformComponents,max_geometry_uniform_components)
+RESOURCE(MaxGeometryVaryingComponents,maxGeometryVaryingComponents,max_geometry_varying_components)
+RESOURCE(MaxTessControlInputComponents,maxTessControlInputComponents,max_tess_control_input_components)
+RESOURCE(MaxTessControlOutputComponents,maxTessControlOutputComponents,max_tess_control_output_components)
+RESOURCE(MaxTessControlTextureImageUnits,maxTessControlTextureImageUnits,max_tess_control_texture_image_units)
+RESOURCE(MaxTessControlUniformComponents,maxTessControlUniformComponents,max_tess_control_uniform_components)
+RESOURCE(MaxTessControlTotalOutputComponents,maxTessControlTotalOutputComponents,max_tess_control_total_output_components)
+RESOURCE(MaxTessEvaluationInputComponents,maxTessEvaluationInputComponents,max_tess_evaluation_input_components)
+RESOURCE(MaxTessEvaluationOutputComponents,maxTessEvaluationOutputComponents,max_tess_evaluation_output_components)
+RESOURCE(MaxTessEvaluationTextureImageUnits,maxTessEvaluationTextureImageUnits,max_tess_evaluation_texture_image_units)
+RESOURCE(MaxTessEvaluationUniformComponents,maxTessEvaluationUniformComponents,max_tess_evaluation_uniform_components)
+RESOURCE(MaxTessPatchComponents,maxTessPatchComponents,max_tess_patch_components)
+RESOURCE(MaxPatchVertices,maxPatchVertices,max_patch_vertices)
+RESOURCE(MaxTessGenLevel,maxTessGenLevel,max_tess_gen_level)
+RESOURCE(MaxViewports,maxViewports,max_viewports)
+RESOURCE(MaxVertexAtomicCounters,maxVertexAtomicCounters,max_vertex_atomic_counters)
+RESOURCE(MaxTessControlAtomicCounters,maxTessControlAtomicCounters,max_tess_control_atomic_counters)
+RESOURCE(MaxTessEvaluationAtomicCounters,maxTessEvaluationAtomicCounters,max_tess_evaluation_atomic_counters)
+RESOURCE(MaxGeometryAtomicCounters,maxGeometryAtomicCounters,max_geometry_atomic_counters)
+RESOURCE(MaxFragmentAtomicCounters,maxFragmentAtomicCounters,max_fragment_atomic_counters)
+RESOURCE(MaxCombinedAtomicCounters,maxCombinedAtomicCounters,max_combined_atomic_counters)
+RESOURCE(MaxAtomicCounterBindings,maxAtomicCounterBindings,max_atomic_counter_bindings)
+RESOURCE(MaxVertexAtomicCounterBuffers,maxVertexAtomicCounterBuffers,max_vertex_atomic_counter_buffers)
+RESOURCE(MaxTessControlAtomicCounterBuffers,maxTessControlAtomicCounterBuffers,max_tess_control_atomic_counter_buffers)
+RESOURCE(MaxTessEvaluationAtomicCounterBuffers,maxTessEvaluationAtomicCounterBuffers,max_tess_evaluation_atomic_counter_buffers)
+RESOURCE(MaxGeometryAtomicCounterBuffers,maxGeometryAtomicCounterBuffers,max_geometry_atomic_counter_buffers)
+RESOURCE(MaxFragmentAtomicCounterBuffers,maxFragmentAtomicCounterBuffers,max_fragment_atomic_counter_buffers)
+RESOURCE(MaxCombinedAtomicCounterBuffers,maxCombinedAtomicCounterBuffers,max_combined_atomic_counter_buffers)
+RESOURCE(MaxAtomicCounterBufferSize,maxAtomicCounterBufferSize,max_atomic_counter_buffer_size)
+RESOURCE(MaxTransformFeedbackBuffers,maxTransformFeedbackBuffers,max_transform_feedback_buffers)
+RESOURCE(MaxTransformFeedbackInterleavedComponents,maxTransformFeedbackInterleavedComponents,max_transform_feedback_interleaved_components)
+RESOURCE(MaxCullDistances,maxCullDistances,max_cull_distances)
+RESOURCE(MaxCombinedClipAndCullDistances,maxCombinedClipAndCullDistances,max_combined_clip_and_cull_distances)
+RESOURCE(MaxSamples,maxSamples,max_samples)
diff --git a/libshaderc_util/src/compiler.cc b/libshaderc_util/src/compiler.cc
index a170a4c..574ccfd 100644
--- a/libshaderc_util/src/compiler.cc
+++ b/libshaderc_util/src/compiler.cc
@@ -91,6 +91,29 @@ EShMessages GetMessageRules(shaderc_util::Compiler::TargetEnv env,
} // anonymous namespace
namespace shaderc_util {
+
+void Compiler::SetLimit(Compiler::Limit limit, int value) {
+ switch (limit) {
+#define RESOURCE(NAME, FIELD, CNAME) \
+ case Limit::NAME: \
+ limits_.FIELD = value; \
+ break;
+#include "libshaderc_util/resources.inc"
+#undef RESOURCE
+ }
+}
+
+int Compiler::GetLimit(Compiler::Limit limit) const {
+ switch (limit) {
+#define RESOURCE(NAME, FIELD, CNAME) \
+ case Limit::NAME: \
+ return limits_.FIELD;
+#include "libshaderc_util/resources.inc"
+#undef RESOURCE
+ }
+ return 0; // Unreachable
+}
+
std::tuple<bool, std::vector<uint32_t>, size_t> Compiler::Compile(
const string_piece& input_source_string, EShLanguage forced_shader_stage,
const std::string& error_tag, const char* entry_point_name,
@@ -183,10 +206,10 @@ std::tuple<bool, std::vector<uint32_t>, size_t> Compiler::Compile(
shader.setEntryPoint(entry_point_name);
// TODO(dneto): Generate source-level debug info if requested.
- bool success = shader.parse(
- &shaderc_util::kDefaultTBuiltInResource, default_version_,
- default_profile_, force_version_profile_, kNotForwardCompatible,
- GetMessageRules(target_env_, source_language_), includer);
+ bool success =
+ shader.parse(&limits_, default_version_, default_profile_,
+ force_version_profile_, kNotForwardCompatible,
+ GetMessageRules(target_env_, source_language_), includer);
success &= PrintFilteredErrors(error_tag, error_stream, warnings_as_errors_,
suppress_warnings_, shader.getInfoLog(),
@@ -306,9 +329,8 @@ std::tuple<bool, std::string, std::string> Compiler::PreprocessShader(
std::string preprocessed_shader;
const bool success = shader.preprocess(
- &shaderc_util::kDefaultTBuiltInResource, default_version_,
- default_profile_, force_version_profile_, kNotForwardCompatible, rules,
- &preprocessed_shader, includer);
+ &limits_, default_version_, default_profile_, force_version_profile_,
+ kNotForwardCompatible, rules, &preprocessed_shader, includer);
if (success) {
return std::make_tuple(true, preprocessed_shader, shader.getInfoLog());
diff --git a/libshaderc_util/src/compiler_test.cc b/libshaderc_util/src/compiler_test.cc
index 3af7c22..9938848 100644
--- a/libshaderc_util/src/compiler_test.cc
+++ b/libshaderc_util/src/compiler_test.cc
@@ -25,6 +25,7 @@ namespace {
using shaderc_util::Compiler;
using ::testing::HasSubstr;
+using ::testing::Eq;
// A trivial vertex shader
const char kVertexShader[] =
@@ -360,4 +361,73 @@ TEST_F(CompilerTest, EntryPointParameterTakesEffectForHLSL) {
<< assembly;
}
+// A test case for setting resource limits.
+struct SetLimitCase {
+ Compiler::Limit limit;
+ int default_value;
+ int value;
+};
+
+using LimitTest = testing::TestWithParam<SetLimitCase>;
+
+TEST_P(LimitTest, Sample) {
+ Compiler compiler;
+ EXPECT_THAT(compiler.GetLimit(GetParam().limit),
+ Eq(GetParam().default_value));
+ compiler.SetLimit(GetParam().limit, GetParam().value);
+ EXPECT_THAT(compiler.GetLimit(GetParam().limit), Eq(GetParam().value));
+}
+
+#define CASE(LIMIT, DEFAULT, NEW) \
+ { Compiler::Limit::LIMIT, DEFAULT, NEW }
+INSTANTIATE_TEST_CASE_P(
+ CompilerTest, LimitTest,
+ // See resources.cc for the defaults.
+ testing::ValuesIn(std::vector<SetLimitCase>{
+ // clang-format off
+ // This is just a sampling of the possible values.
+ CASE(MaxLights, 8, 99),
+ CASE(MaxClipPlanes, 6, 10929),
+ CASE(MaxTessControlAtomicCounters, 0, 72),
+ CASE(MaxSamples, 4, 8),
+ // clang-format on
+ }), );
+#undef CASE
+
+// Returns a fragment shader accessing a texture with the given
+// offset.
+std::string ShaderWithTexOffset(int offset) {
+ std::ostringstream oss;
+ oss << "#version 150\n"
+ "uniform sampler1D tex;\n"
+ "void main() { vec4 x = textureOffset(tex, 1.0, "
+ << offset << "); }\n";
+ return oss.str();
+}
+
+// Ensure compilation is sensitive to limit setting. Sample just
+// two particular limits. The default minimum texel offset is -8,
+// and the default maximum texel offset is 7.
+TEST_F(CompilerTest, TexelOffsetDefaults) {
+ const EShLanguage stage = EShLangFragment;
+ EXPECT_FALSE(SimpleCompilationSucceeds(ShaderWithTexOffset(-9), stage));
+ EXPECT_TRUE(SimpleCompilationSucceeds(ShaderWithTexOffset(-8), stage));
+ EXPECT_TRUE(SimpleCompilationSucceeds(ShaderWithTexOffset(7), stage));
+ EXPECT_FALSE(SimpleCompilationSucceeds(ShaderWithTexOffset(8), stage));
+}
+
+TEST_F(CompilerTest, TexelOffsetLowerTheMinimum) {
+ const EShLanguage stage = EShLangFragment;
+ compiler_.SetLimit(Compiler::Limit::MinProgramTexelOffset, -99);
+ EXPECT_FALSE(SimpleCompilationSucceeds(ShaderWithTexOffset(-100), stage));
+ EXPECT_TRUE(SimpleCompilationSucceeds(ShaderWithTexOffset(-99), stage));
+}
+
+TEST_F(CompilerTest, TexelOffsetRaiseTheMaximum) {
+ const EShLanguage stage = EShLangFragment;
+ compiler_.SetLimit(Compiler::Limit::MaxProgramTexelOffset, 100);
+ EXPECT_TRUE(SimpleCompilationSucceeds(ShaderWithTexOffset(100), stage));
+ EXPECT_FALSE(SimpleCompilationSucceeds(ShaderWithTexOffset(101), stage));
+}
+
} // anonymous namespace