diff options
author | David Neto <dneto@google.com> | 2016-11-17 10:52:48 -0500 |
---|---|---|
committer | David Neto <dneto@google.com> | 2016-11-17 13:14:41 -0500 |
commit | 1ef0a89bcda32ab4befab6992752eac4c05f2c41 (patch) | |
tree | 609a95c120aa0c6377d8dfba152e475e590a0d9f | |
parent | 89eefb94d69e07576682e44cb3d55fa332ce2e91 (diff) | |
download | shaderc-1ef0a89bcda32ab4befab6992752eac4c05f2c41.tar.gz |
Support resource limits in C, C++ API
-rw-r--r-- | libshaderc/include/shaderc/shaderc.h | 91 | ||||
-rw-r--r-- | libshaderc/include/shaderc/shaderc.hpp | 5 | ||||
-rw-r--r-- | libshaderc/src/shaderc.cc | 19 | ||||
-rw-r--r-- | libshaderc/src/shaderc_cpp_test.cc | 48 | ||||
-rw-r--r-- | libshaderc/src/shaderc_test.cc | 52 | ||||
-rw-r--r-- | libshaderc_util/include/libshaderc_util/compiler.h | 23 | ||||
-rw-r--r-- | libshaderc_util/include/libshaderc_util/resources.h | 5 | ||||
-rw-r--r-- | libshaderc_util/include/libshaderc_util/resources.inc | 107 | ||||
-rw-r--r-- | libshaderc_util/src/compiler.cc | 36 | ||||
-rw-r--r-- | libshaderc_util/src/compiler_test.cc | 70 |
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 |