modules/egl/teglCreateContextExtTests.cpp \
modules/egl/teglCreateContextTests.cpp \
modules/egl/teglCreateSurfaceTests.cpp \
+ modules/egl/teglGetFrameTimestampsTests.cpp \
modules/egl/teglGetProcAddressTests.cpp \
modules/egl/teglGLES1RenderUtil.cpp \
modules/egl/teglGLES2RenderUtil.cpp \
modules/egl/teglQuerySurfaceTests.cpp \
modules/egl/teglRenderCase.cpp \
modules/egl/teglRenderTests.cpp \
+ modules/egl/teglRobustnessTests.cpp \
modules/egl/teglResizeTests.cpp \
modules/egl/teglSimpleConfigCase.cpp \
modules/egl/teglSurfacelessContextTests.cpp \
modules/gles31/functional/es31fNegativeShaderDirectiveTests.cpp \
modules/gles31/functional/es31fNegativeShaderFunctionTests.cpp \
modules/gles31/functional/es31fNegativeShaderImageLoadStoreTests.cpp \
+ modules/gles31/functional/es31fNegativeShaderStorageTests.cpp \
modules/gles31/functional/es31fNegativeStateApiTests.cpp \
+ modules/gles31/functional/es31fNegativeSSBOBlockTests.cpp \
+ modules/gles31/functional/es31fNegativeTessellationTests.cpp \
modules/gles31/functional/es31fNegativeTestShared.cpp \
modules/gles31/functional/es31fNegativeTextureApiTests.cpp \
modules/gles31/functional/es31fNegativeVertexArrayApiTests.cpp \
modules/gles31/functional/es31fVertexAttributeBindingTests.cpp \
modules/gles31/functional/es31fCopyImageTests.cpp \
modules/gles31/functional/es31fDrawBuffersIndexedTests.cpp \
+ modules/gles31/functional/es31fSRGBDecodeTests.cpp \
modules/gles31/stress/es31sDrawTests.cpp \
modules/gles31/stress/es31sStressTests.cpp \
modules/gles31/stress/es31sTessellationGeometryInteractionTests.cpp \
external/vulkancts/modules/vulkan/vktTestPackage.cpp \
external/vulkancts/modules/vulkan/vktTestPackageEntry.cpp \
external/vulkancts/modules/vulkan/wsi/vktWsiDisplayTimingTests.cpp \
+ external/vulkancts/modules/vulkan/wsi/vktWsiIncrementalPresentTests.cpp \
external/vulkancts/modules/vulkan/wsi/vktWsiSurfaceTests.cpp \
external/vulkancts/modules/vulkan/wsi/vktWsiSwapchainTests.cpp \
external/vulkancts/modules/vulkan/wsi/vktWsiTests.cpp
-DDEQP_GLES2_RUNTIME_LOAD=1 \
-DQP_SUPPORT_PNG=1 \
-Wconversion \
+ -fwrapv \
-Wno-sign-conversion
LOCAL_SHARED_LIBRARIES := \
$(deqp_compile_flags)
LOCAL_SDK_VERSION := 22
-LOCAL_CPPFLAGS += -Wno-non-virtual-dtor -fwrapv
+LOCAL_CPPFLAGS += -Wno-non-virtual-dtor -Wno-delete-non-virtual-dtor
LOCAL_NDK_STL_VARIANT := gnustl_static
LOCAL_RTTI_FLAG := -frtti -fexceptions
LOCAL_MULTILIB := both
<option name="deqp-gl-config-name" value="rgba8888d24s8ms0"/>
<option name="deqp-surface-type" value="window"/>
<option name="deqp-screen-rotation" value="unspecified"/>
- <option name="runtime-hint" value="24m"/>
+ <option name="runtime-hint" value="23m"/>
<option name="deqp-config-required" value="true"/>
</test>
<test class="com.drawelements.deqp.runner.DeqpTestRunner">
<option name="deqp-gl-config-name" value="rgba8888d24s8ms0"/>
<option name="deqp-surface-type" value="window"/>
<option name="deqp-screen-rotation" value="unspecified"/>
- <option name="runtime-hint" value="40m"/>
+ <option name="runtime-hint" value="46m"/>
<option name="deqp-config-required" value="true"/>
</test>
<test class="com.drawelements.deqp.runner.DeqpTestRunner">
<option name="deqp-gl-config-name" value="rgba8888d24s8ms0"/>
<option name="deqp-surface-type" value="window"/>
<option name="deqp-screen-rotation" value="unspecified"/>
- <option name="runtime-hint" value="1h15m"/>
+ <option name="runtime-hint" value="1h50m"/>
<option name="deqp-config-required" value="true"/>
</test>
<test class="com.drawelements.deqp.runner.DeqpTestRunner">
<option name="deqp-gl-config-name" value="rgba8888d24s8ms0"/>
<option name="deqp-surface-type" value="window"/>
<option name="deqp-screen-rotation" value="0"/>
- <option name="runtime-hint" value="7m"/>
+ <option name="runtime-hint" value="1m"/>
</test>
<test class="com.drawelements.deqp.runner.DeqpTestRunner">
<option name="deqp-package" value="dEQP-GLES3"/>
<option name="deqp-gl-config-name" value="rgba8888d24s8ms0"/>
<option name="deqp-surface-type" value="window"/>
<option name="deqp-screen-rotation" value="90"/>
- <option name="runtime-hint" value="7m"/>
+ <option name="runtime-hint" value="1m"/>
</test>
<test class="com.drawelements.deqp.runner.DeqpTestRunner">
<option name="deqp-package" value="dEQP-GLES3"/>
<option name="deqp-gl-config-name" value="rgba8888d24s8ms0"/>
<option name="deqp-surface-type" value="window"/>
<option name="deqp-screen-rotation" value="180"/>
- <option name="runtime-hint" value="7m"/>
+ <option name="runtime-hint" value="1m"/>
</test>
<test class="com.drawelements.deqp.runner.DeqpTestRunner">
<option name="deqp-package" value="dEQP-GLES3"/>
<option name="deqp-gl-config-name" value="rgba8888d24s8ms0"/>
<option name="deqp-surface-type" value="window"/>
<option name="deqp-screen-rotation" value="270"/>
- <option name="runtime-hint" value="7m"/>
+ <option name="runtime-hint" value="1m"/>
</test>
<test class="com.drawelements.deqp.runner.DeqpTestRunner">
<option name="deqp-package" value="dEQP-GLES3"/>
<option name="deqp-gl-config-name" value="rgba8888d24s8ms4"/>
<option name="deqp-surface-type" value="window"/>
<option name="deqp-screen-rotation" value="unspecified"/>
- <option name="runtime-hint" value="10m"/>
+ <option name="runtime-hint" value="1m"/>
</test>
<test class="com.drawelements.deqp.runner.DeqpTestRunner">
<option name="deqp-package" value="dEQP-GLES3"/>
<option name="deqp-gl-config-name" value="rgb565d0s0ms0"/>
<option name="deqp-surface-type" value="window"/>
<option name="deqp-screen-rotation" value="unspecified"/>
- <option name="runtime-hint" value="10m"/>
+ <option name="runtime-hint" value="1m"/>
</test>
<test class="com.drawelements.deqp.runner.DeqpTestRunner">
<option name="deqp-package" value="dEQP-GLES31"/>
<option name="deqp-gl-config-name" value="rgba8888d24s8ms0"/>
<option name="deqp-surface-type" value="window"/>
<option name="deqp-screen-rotation" value="unspecified"/>
- <option name="runtime-hint" value="7h30m"/>
+ <option name="runtime-hint" value="1h40m"/>
<option name="deqp-config-required" value="true"/>
</test>
<test class="com.drawelements.deqp.runner.DeqpTestRunner">
<test class="com.drawelements.deqp.runner.DeqpTestRunner">
<option name="deqp-package" value="dEQP-VK"/>
<option name="deqp-caselist-file" value="vk-master.txt"/>
- <option name="runtime-hint" value="3h45m"/>
+ <option name="runtime-hint" value="2h29m"/>
</test>
</configuration>
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_1
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_2
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_3
-dEQP-GLES31.functional.separate_shader.validation.varying.match_different_struct_names
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_name
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_type
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_precision
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_name
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_precision
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_array_size
-dEQP-GLES31.functional.separate_shader.validation.io_blocks.match_different_member_struct_names
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_name
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_type
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_precision
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_1
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_2
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_3
-dEQP-GLES31.functional.separate_shader.validation.varying.match_different_struct_names
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_name
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_type
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_precision
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_name
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_precision
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_array_size
-dEQP-GLES31.functional.separate_shader.validation.io_blocks.match_different_member_struct_names
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_name
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_type
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_precision
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_explicit_location
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_2
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_3
-dEQP-GLES31.functional.separate_shader.validation.varying.match_different_struct_names
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_type
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_precision
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_array_element_type
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_name
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_precision
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_array_size
-dEQP-GLES31.functional.separate_shader.validation.io_blocks.match_different_member_struct_names
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_name
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_type
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_precision
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_explicit_location
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_2
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_3
-dEQP-GLES31.functional.separate_shader.validation.varying.match_different_struct_names
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_type
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_precision
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_array_element_type
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_name
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_precision
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_array_size
-dEQP-GLES31.functional.separate_shader.validation.io_blocks.match_different_member_struct_names
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_name
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_type
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_precision
dEQP-EGL.functional.create_context.rgba8888_depth_no_stencil
dEQP-EGL.functional.create_context.rgba8888_depth_stencil
dEQP-EGL.functional.create_context.other
+dEQP-EGL.functional.create_context.no_config
dEQP-EGL.functional.query_context.simple.query_api
dEQP-EGL.functional.query_context.get_current_context.rgb565_window
dEQP-EGL.functional.query_context.get_current_context.rgb565_pixmap
dEQP-EGL.functional.choose_config.random.surface_type
dEQP-EGL.functional.choose_config.random.sample_buffers
dEQP-EGL.functional.choose_config.random.all
+dEQP-EGL.functional.choose_config.color_component_type_ext.dont_care
+dEQP-EGL.functional.choose_config.color_component_type_ext.fixed
+dEQP-EGL.functional.choose_config.color_component_type_ext.float
dEQP-EGL.functional.color_clears.single_context.gles1.rgb565_window
dEQP-EGL.functional.color_clears.single_context.gles1.rgb565_pixmap
dEQP-EGL.functional.color_clears.single_context.gles1.rgb565_pbuffer
dEQP-EGL.functional.multithread.single_window_context
dEQP-EGL.functional.multithread.pbuffer_single_window_context
dEQP-EGL.functional.get_proc_address.extension.egl_android_blob_cache
+dEQP-EGL.functional.get_proc_address.extension.egl_android_create_native_client_buffer
dEQP-EGL.functional.get_proc_address.extension.egl_android_native_fence_sync
+dEQP-EGL.functional.get_proc_address.extension.egl_android_presentation_time
dEQP-EGL.functional.get_proc_address.extension.egl_angle_query_surface_pointer
dEQP-EGL.functional.get_proc_address.extension.egl_ext_device_base
dEQP-EGL.functional.get_proc_address.extension.egl_ext_device_enumeration
dEQP-EGL.functional.get_proc_address.extension.egl_ext_device_query
+dEQP-EGL.functional.get_proc_address.extension.egl_ext_image_dma_buf_import_modifiers
dEQP-EGL.functional.get_proc_address.extension.egl_ext_output_base
dEQP-EGL.functional.get_proc_address.extension.egl_ext_platform_base
dEQP-EGL.functional.get_proc_address.extension.egl_ext_stream_consumer_egloutput
dEQP-EGL.functional.get_proc_address.extension.egl_khr_partial_update
dEQP-EGL.functional.get_proc_address.extension.egl_khr_reusable_sync
dEQP-EGL.functional.get_proc_address.extension.egl_khr_stream
+dEQP-EGL.functional.get_proc_address.extension.egl_khr_stream_attrib
dEQP-EGL.functional.get_proc_address.extension.egl_khr_stream_consumer_gltexture
dEQP-EGL.functional.get_proc_address.extension.egl_khr_stream_cross_process_fd
dEQP-EGL.functional.get_proc_address.extension.egl_khr_stream_fifo
dEQP-EGL.functional.get_proc_address.extension.egl_nv_post_sub_buffer
dEQP-EGL.functional.get_proc_address.extension.egl_nv_stream_consumer_gltexture_yuv
dEQP-EGL.functional.get_proc_address.extension.egl_nv_stream_metadata
+dEQP-EGL.functional.get_proc_address.extension.egl_nv_stream_reset
dEQP-EGL.functional.get_proc_address.extension.egl_nv_stream_sync
dEQP-EGL.functional.get_proc_address.extension.egl_nv_sync
dEQP-EGL.functional.get_proc_address.extension.egl_nv_system_time
dEQP-EGL.functional.mutable_render_buffer.querySurface
dEQP-EGL.functional.mutable_render_buffer.negativeConfigBit
dEQP-EGL.functional.mutable_render_buffer.basic
+dEQP-EGL.functional.get_frame_timestamps.rgb565_no_depth_no_stencil
+dEQP-EGL.functional.get_frame_timestamps.rgb565_no_depth_stencil
+dEQP-EGL.functional.get_frame_timestamps.rgb565_depth_no_stencil
+dEQP-EGL.functional.get_frame_timestamps.rgb565_depth_stencil
+dEQP-EGL.functional.get_frame_timestamps.rgb888_no_depth_no_stencil
+dEQP-EGL.functional.get_frame_timestamps.rgb888_no_depth_stencil
+dEQP-EGL.functional.get_frame_timestamps.rgb888_depth_no_stencil
+dEQP-EGL.functional.get_frame_timestamps.rgb888_depth_stencil
+dEQP-EGL.functional.get_frame_timestamps.rgba4444_no_depth_no_stencil
+dEQP-EGL.functional.get_frame_timestamps.rgba4444_no_depth_stencil
+dEQP-EGL.functional.get_frame_timestamps.rgba4444_depth_no_stencil
+dEQP-EGL.functional.get_frame_timestamps.rgba4444_depth_stencil
+dEQP-EGL.functional.get_frame_timestamps.rgba5551_no_depth_no_stencil
+dEQP-EGL.functional.get_frame_timestamps.rgba5551_no_depth_stencil
+dEQP-EGL.functional.get_frame_timestamps.rgba5551_depth_no_stencil
+dEQP-EGL.functional.get_frame_timestamps.rgba5551_depth_stencil
+dEQP-EGL.functional.get_frame_timestamps.rgba8888_no_depth_no_stencil
+dEQP-EGL.functional.get_frame_timestamps.rgba8888_no_depth_stencil
+dEQP-EGL.functional.get_frame_timestamps.rgba8888_depth_no_stencil
+dEQP-EGL.functional.get_frame_timestamps.rgba8888_depth_stencil
+dEQP-EGL.functional.get_frame_timestamps.other
+dEQP-EGL.functional.robustness.create_context.query_robust_access
+dEQP-EGL.functional.robustness.create_context.no_reset_notification
+dEQP-EGL.functional.robustness.create_context.lose_context_on_reset
+dEQP-EGL.functional.robustness.reset_context.shaders.infinite_loop.reset_status.vertex
+dEQP-EGL.functional.robustness.reset_context.shaders.infinite_loop.reset_status.fragment
+dEQP-EGL.functional.robustness.reset_context.shaders.infinite_loop.reset_status.vertex_and_fragment
+dEQP-EGL.functional.robustness.reset_context.shaders.infinite_loop.reset_status.compute
+dEQP-EGL.functional.robustness.reset_context.shaders.infinite_loop.sync_status.vertex
+dEQP-EGL.functional.robustness.reset_context.shaders.infinite_loop.sync_status.fragment
+dEQP-EGL.functional.robustness.reset_context.shaders.infinite_loop.sync_status.vertex_and_fragment
+dEQP-EGL.functional.robustness.reset_context.shaders.infinite_loop.sync_status.compute
+dEQP-EGL.functional.robustness.reset_context.shaders.infinite_loop.query_status.vertex
+dEQP-EGL.functional.robustness.reset_context.shaders.infinite_loop.query_status.fragment
+dEQP-EGL.functional.robustness.reset_context.shaders.infinite_loop.query_status.vertex_and_fragment
+dEQP-EGL.functional.robustness.reset_context.shaders.infinite_loop.query_status.compute
+dEQP-EGL.functional.robustness.reset_context.shaders.infinite_loop.shared_context_status.vertex
+dEQP-EGL.functional.robustness.reset_context.shaders.infinite_loop.shared_context_status.fragment
+dEQP-EGL.functional.robustness.reset_context.shaders.infinite_loop.shared_context_status.vertex_and_fragment
+dEQP-EGL.functional.robustness.reset_context.shaders.infinite_loop.shared_context_status.compute
+dEQP-EGL.functional.robustness.reset_context.shaders.infinite_loop.recover_from_reset.vertex
+dEQP-EGL.functional.robustness.reset_context.shaders.infinite_loop.recover_from_reset.fragment
+dEQP-EGL.functional.robustness.reset_context.shaders.infinite_loop.recover_from_reset.vertex_and_fragment
+dEQP-EGL.functional.robustness.reset_context.shaders.infinite_loop.recover_from_reset.compute
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds.reset_status.reads.uniform_block.vertex
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds.reset_status.reads.uniform_block.fragment
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds.reset_status.reads.uniform_block.vertex_and_fragment
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds.reset_status.reads.uniform_block.compute
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds.reset_status.reads.shader_storage_block.vertex
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds.reset_status.reads.shader_storage_block.fragment
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds.reset_status.reads.shader_storage_block.vertex_and_fragment
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds.reset_status.reads.shader_storage_block.compute
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds.reset_status.reads.local_array.vertex
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds.reset_status.reads.local_array.fragment
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds.reset_status.reads.local_array.vertex_and_fragment
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds.reset_status.reads.local_array.compute
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds.reset_status.writes.uniform_block.vertex
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds.reset_status.writes.uniform_block.fragment
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds.reset_status.writes.uniform_block.vertex_and_fragment
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds.reset_status.writes.uniform_block.compute
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds.reset_status.writes.shader_storage_block.vertex
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds.reset_status.writes.shader_storage_block.fragment
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds.reset_status.writes.shader_storage_block.vertex_and_fragment
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds.reset_status.writes.shader_storage_block.compute
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds.reset_status.writes.local_array.vertex
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds.reset_status.writes.local_array.fragment
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds.reset_status.writes.local_array.vertex_and_fragment
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds.reset_status.writes.local_array.compute
+dEQP-EGL.functional.robustness.reset_context.fixed_function_pipeline.reset_status.index_buffer_out_of_bounds
+dEQP-EGL.functional.robustness.reset_context.fixed_function_pipeline.reset_status.vertex_buffer_out_of_bounds
+dEQP-EGL.functional.robustness.negative_context.invalid_robust_context_creation
+dEQP-EGL.functional.robustness.negative_context.invalid_robust_shared_context_creation
dEQP-GLES31.functional.shaders.linkage.tessellation.varying.rules.vertex_fragment_same_varying_name_2
dEQP-GLES31.functional.shaders.linkage.tessellation.varying.rules.invalid_vertex_index
dEQP-GLES31.functional.shaders.linkage.tessellation.varying.rules.input_non_array
+dEQP-GLES31.functional.shaders.linkage.tessellation.varying.rules.output_non_array
dEQP-GLES31.functional.shaders.linkage.tessellation.varying.rules.input_array_size_mismatch
dEQP-GLES31.functional.shaders.linkage.tessellation.varying.rules.internal_array_size_mismatch
+dEQP-GLES31.functional.shaders.linkage.tessellation.varying.rules.invalid_patch_in_usage
+dEQP-GLES31.functional.shaders.linkage.tessellation.varying.rules.invalid_patch_out_usage
+dEQP-GLES31.functional.shaders.linkage.tessellation.varying.rules.invalid_per_patch_qualifier_usage
dEQP-GLES31.functional.shaders.linkage.tessellation.varying.rules.per_patch_qualifier_mismatch_1
dEQP-GLES31.functional.shaders.linkage.tessellation.varying.rules.per_patch_qualifier_mismatch_2
dEQP-GLES31.functional.shaders.linkage.tessellation.varying.rules.input_block
dEQP-GLES31.functional.shaders.linkage.tessellation.varying.rules.input_block_non_array
+dEQP-GLES31.functional.shaders.linkage.tessellation.varying.rules.output_block_non_array
dEQP-GLES31.functional.shaders.linkage.tessellation.varying.rules.input_block_array_size_mismatch
dEQP-GLES31.functional.shaders.linkage.tessellation.varying.rules.output_block
dEQP-GLES31.functional.shaders.linkage.tessellation.varying.rules.output_block_array
dEQP-GLES31.functional.shaders.linkage.tessellation.uniform.types.uvec3
dEQP-GLES31.functional.shaders.linkage.tessellation.uniform.types.uvec4
dEQP-GLES31.functional.shaders.linkage.tessellation.uniform.types.float_struct
+dEQP-GLES31.functional.shaders.linkage.tessellation.layout_declarations.rules.primitive_mode_mismatch
+dEQP-GLES31.functional.shaders.linkage.tessellation.layout_declarations.rules.spacing_mode_mismatch
+dEQP-GLES31.functional.shaders.linkage.tessellation.layout_declarations.rules.vertex_order_mismatch
+dEQP-GLES31.functional.shaders.linkage.tessellation.layout_declarations.rules.vertex_count_mismatch
+dEQP-GLES31.functional.shaders.linkage.tessellation.barriers.rules.invalid_barrier_usage_within_control_flow
+dEQP-GLES31.functional.shaders.linkage.tessellation.barriers.rules.invalid_barrier_usage_after_return
dEQP-GLES31.functional.shaders.linkage.tessellation_geometry.varying.rules.type_mismatch
dEQP-GLES31.functional.shaders.linkage.tessellation_geometry.varying.rules.different_precision
dEQP-GLES31.functional.shaders.linkage.tessellation_geometry.varying.rules.no_output_declaration
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_1
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_2
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_3
-dEQP-GLES31.functional.separate_shader.validation.varying.match_different_struct_names
+dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_different_struct_names
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_name
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_type
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_precision
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_precision
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_different_member_interpolation
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_array_size
-dEQP-GLES31.functional.separate_shader.validation.io_blocks.match_different_member_struct_names
+dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_different_member_struct_names
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_name
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_type
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_precision
dEQP-GLES31.functional.debug.negative_coverage.callbacks.shader_directive.tessellation_shader
dEQP-GLES31.functional.debug.negative_coverage.callbacks.shader_directive.texture_buffer
dEQP-GLES31.functional.debug.negative_coverage.callbacks.shader_directive.texture_cube_map_array
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.shader_directive.accessing_bounding_box_type
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.ssbo_block.ssbo_block_interface_matching_tests
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.ssbo_block.ssbo_using_shared_qualifier_tests
dEQP-GLES31.functional.debug.negative_coverage.callbacks.precise.precise_as_variable_name
dEQP-GLES31.functional.debug.negative_coverage.callbacks.precise.precise_as_function_name
dEQP-GLES31.functional.debug.negative_coverage.callbacks.precise.precise_as_function_argument
dEQP-GLES31.functional.debug.negative_coverage.callbacks.advanced_blend.blend_qualifier_mismatch
dEQP-GLES31.functional.debug.negative_coverage.callbacks.advanced_blend.attachment_advanced_equation
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.shader_storage.block_number_limits
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.shader_storage.max_combined_block_number_limit
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.tessellation.single_tessellation_stage
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.tessellation.invalid_primitive_mode
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.tessellation.tessellation_not_active
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.tessellation.invalid_program_state
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.tessellation.get_programiv
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.tessellation.invalid_program_queries
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.tessellation.tessellation_control_invalid_vertex_count
dEQP-GLES31.functional.debug.negative_coverage.log.buffer.bind_buffer
dEQP-GLES31.functional.debug.negative_coverage.log.buffer.delete_buffers
dEQP-GLES31.functional.debug.negative_coverage.log.buffer.gen_buffers
dEQP-GLES31.functional.debug.negative_coverage.log.shader_directive.tessellation_shader
dEQP-GLES31.functional.debug.negative_coverage.log.shader_directive.texture_buffer
dEQP-GLES31.functional.debug.negative_coverage.log.shader_directive.texture_cube_map_array
+dEQP-GLES31.functional.debug.negative_coverage.log.shader_directive.accessing_bounding_box_type
+dEQP-GLES31.functional.debug.negative_coverage.log.ssbo_block.ssbo_block_interface_matching_tests
+dEQP-GLES31.functional.debug.negative_coverage.log.ssbo_block.ssbo_using_shared_qualifier_tests
dEQP-GLES31.functional.debug.negative_coverage.log.precise.precise_as_variable_name
dEQP-GLES31.functional.debug.negative_coverage.log.precise.precise_as_function_name
dEQP-GLES31.functional.debug.negative_coverage.log.precise.precise_as_function_argument
dEQP-GLES31.functional.debug.negative_coverage.log.advanced_blend.blend_qualifier_mismatch
dEQP-GLES31.functional.debug.negative_coverage.log.advanced_blend.attachment_advanced_equation
+dEQP-GLES31.functional.debug.negative_coverage.log.shader_storage.block_number_limits
+dEQP-GLES31.functional.debug.negative_coverage.log.shader_storage.max_combined_block_number_limit
+dEQP-GLES31.functional.debug.negative_coverage.log.tessellation.single_tessellation_stage
+dEQP-GLES31.functional.debug.negative_coverage.log.tessellation.invalid_primitive_mode
+dEQP-GLES31.functional.debug.negative_coverage.log.tessellation.tessellation_not_active
+dEQP-GLES31.functional.debug.negative_coverage.log.tessellation.invalid_program_state
+dEQP-GLES31.functional.debug.negative_coverage.log.tessellation.get_programiv
+dEQP-GLES31.functional.debug.negative_coverage.log.tessellation.invalid_program_queries
+dEQP-GLES31.functional.debug.negative_coverage.log.tessellation.tessellation_control_invalid_vertex_count
dEQP-GLES31.functional.debug.negative_coverage.get_error.buffer.bind_buffer
dEQP-GLES31.functional.debug.negative_coverage.get_error.buffer.delete_buffers
dEQP-GLES31.functional.debug.negative_coverage.get_error.buffer.gen_buffers
dEQP-GLES31.functional.debug.negative_coverage.get_error.shader_directive.tessellation_shader
dEQP-GLES31.functional.debug.negative_coverage.get_error.shader_directive.texture_buffer
dEQP-GLES31.functional.debug.negative_coverage.get_error.shader_directive.texture_cube_map_array
+dEQP-GLES31.functional.debug.negative_coverage.get_error.shader_directive.accessing_bounding_box_type
+dEQP-GLES31.functional.debug.negative_coverage.get_error.ssbo_block.ssbo_block_interface_matching_tests
+dEQP-GLES31.functional.debug.negative_coverage.get_error.ssbo_block.ssbo_using_shared_qualifier_tests
dEQP-GLES31.functional.debug.negative_coverage.get_error.precise.precise_as_variable_name
dEQP-GLES31.functional.debug.negative_coverage.get_error.precise.precise_as_function_name
dEQP-GLES31.functional.debug.negative_coverage.get_error.precise.precise_as_function_argument
dEQP-GLES31.functional.debug.negative_coverage.get_error.advanced_blend.blend_qualifier_mismatch
dEQP-GLES31.functional.debug.negative_coverage.get_error.advanced_blend.attachment_advanced_equation
+dEQP-GLES31.functional.debug.negative_coverage.get_error.shader_storage.block_number_limits
+dEQP-GLES31.functional.debug.negative_coverage.get_error.shader_storage.max_combined_block_number_limit
+dEQP-GLES31.functional.debug.negative_coverage.get_error.tessellation.single_tessellation_stage
+dEQP-GLES31.functional.debug.negative_coverage.get_error.tessellation.invalid_primitive_mode
+dEQP-GLES31.functional.debug.negative_coverage.get_error.tessellation.tessellation_not_active
+dEQP-GLES31.functional.debug.negative_coverage.get_error.tessellation.invalid_program_state
+dEQP-GLES31.functional.debug.negative_coverage.get_error.tessellation.get_programiv
+dEQP-GLES31.functional.debug.negative_coverage.get_error.tessellation.invalid_program_queries
+dEQP-GLES31.functional.debug.negative_coverage.get_error.tessellation.tessellation_control_invalid_vertex_count
dEQP-GLES31.functional.debug.externally_generated.application_messages
dEQP-GLES31.functional.debug.externally_generated.third_party_messages
dEQP-GLES31.functional.debug.externally_generated.push_pop_stack
dEQP-GLES31.functional.layout_binding.image.image3d.fragment_binding_max_array
dEQP-GLES31.functional.layout_binding.negative.sampler.sampler2d.vertex_binding_over_max
dEQP-GLES31.functional.layout_binding.negative.sampler.sampler2d.fragment_binding_over_max
+dEQP-GLES31.functional.layout_binding.negative.sampler.sampler2d.tess_control_binding_over_max
+dEQP-GLES31.functional.layout_binding.negative.sampler.sampler2d.tess_evaluation_binding_over_max
dEQP-GLES31.functional.layout_binding.negative.sampler.sampler2d.vertex_binding_neg
dEQP-GLES31.functional.layout_binding.negative.sampler.sampler2d.fragment_binding_neg
+dEQP-GLES31.functional.layout_binding.negative.sampler.sampler2d.tess_control_binding_neg
+dEQP-GLES31.functional.layout_binding.negative.sampler.sampler2d.tess_evaluation_binding_neg
dEQP-GLES31.functional.layout_binding.negative.sampler.sampler2d.vertex_binding_over_max_array
dEQP-GLES31.functional.layout_binding.negative.sampler.sampler2d.fragment_binding_over_max_array
+dEQP-GLES31.functional.layout_binding.negative.sampler.sampler2d.tess_control_binding_over_max_array
+dEQP-GLES31.functional.layout_binding.negative.sampler.sampler2d.tess_evaluation_binding_over_max_array
dEQP-GLES31.functional.layout_binding.negative.sampler.sampler2d.vertex_binding_neg_array
dEQP-GLES31.functional.layout_binding.negative.sampler.sampler2d.fragment_binding_neg_array
+dEQP-GLES31.functional.layout_binding.negative.sampler.sampler2d.tess_control_binding_neg_array
+dEQP-GLES31.functional.layout_binding.negative.sampler.sampler2d.tess_evaluation_binding_neg_array
dEQP-GLES31.functional.layout_binding.negative.sampler.sampler2d.binding_contradictory
dEQP-GLES31.functional.layout_binding.negative.sampler.sampler2d.binding_contradictory_array
dEQP-GLES31.functional.layout_binding.negative.sampler.sampler3d.vertex_binding_over_max
dEQP-GLES31.functional.layout_binding.negative.sampler.sampler3d.fragment_binding_over_max
+dEQP-GLES31.functional.layout_binding.negative.sampler.sampler3d.tess_control_binding_over_max
+dEQP-GLES31.functional.layout_binding.negative.sampler.sampler3d.tess_evaluation_binding_over_max
dEQP-GLES31.functional.layout_binding.negative.sampler.sampler3d.vertex_binding_neg
dEQP-GLES31.functional.layout_binding.negative.sampler.sampler3d.fragment_binding_neg
+dEQP-GLES31.functional.layout_binding.negative.sampler.sampler3d.tess_control_binding_neg
+dEQP-GLES31.functional.layout_binding.negative.sampler.sampler3d.tess_evaluation_binding_neg
dEQP-GLES31.functional.layout_binding.negative.sampler.sampler3d.vertex_binding_over_max_array
dEQP-GLES31.functional.layout_binding.negative.sampler.sampler3d.fragment_binding_over_max_array
+dEQP-GLES31.functional.layout_binding.negative.sampler.sampler3d.tess_control_binding_over_max_array
+dEQP-GLES31.functional.layout_binding.negative.sampler.sampler3d.tess_evaluation_binding_over_max_array
dEQP-GLES31.functional.layout_binding.negative.sampler.sampler3d.vertex_binding_neg_array
dEQP-GLES31.functional.layout_binding.negative.sampler.sampler3d.fragment_binding_neg_array
+dEQP-GLES31.functional.layout_binding.negative.sampler.sampler3d.tess_control_binding_neg_array
+dEQP-GLES31.functional.layout_binding.negative.sampler.sampler3d.tess_evaluation_binding_neg_array
dEQP-GLES31.functional.layout_binding.negative.sampler.sampler3d.binding_contradictory
dEQP-GLES31.functional.layout_binding.negative.sampler.sampler3d.binding_contradictory_array
dEQP-GLES31.functional.layout_binding.negative.ubo.vertex_binding_over_max
dEQP-GLES31.functional.layout_binding.negative.ubo.fragment_binding_over_max
+dEQP-GLES31.functional.layout_binding.negative.ubo.tess_control_binding_over_max
+dEQP-GLES31.functional.layout_binding.negative.ubo.tess_evaluation_binding_over_max
dEQP-GLES31.functional.layout_binding.negative.ubo.vertex_binding_neg
dEQP-GLES31.functional.layout_binding.negative.ubo.fragment_binding_neg
+dEQP-GLES31.functional.layout_binding.negative.ubo.tess_control_binding_neg
+dEQP-GLES31.functional.layout_binding.negative.ubo.tess_evaluation_binding_neg
dEQP-GLES31.functional.layout_binding.negative.ubo.vertex_binding_over_max_array
dEQP-GLES31.functional.layout_binding.negative.ubo.fragment_binding_over_max_array
+dEQP-GLES31.functional.layout_binding.negative.ubo.tess_control_binding_over_max_array
+dEQP-GLES31.functional.layout_binding.negative.ubo.tess_evaluation_binding_over_max_array
dEQP-GLES31.functional.layout_binding.negative.ubo.vertex_binding_neg_array
dEQP-GLES31.functional.layout_binding.negative.ubo.fragment_binding_neg_array
+dEQP-GLES31.functional.layout_binding.negative.ubo.tess_control_binding_neg_array
+dEQP-GLES31.functional.layout_binding.negative.ubo.tess_evaluation_binding_neg_array
dEQP-GLES31.functional.layout_binding.negative.ubo.binding_contradictory
dEQP-GLES31.functional.layout_binding.negative.ubo.binding_contradictory_array
dEQP-GLES31.functional.layout_binding.negative.ssbo.vertex_binding_over_max
dEQP-GLES31.functional.layout_binding.negative.ssbo.fragment_binding_over_max
+dEQP-GLES31.functional.layout_binding.negative.ssbo.tess_control_binding_over_max
+dEQP-GLES31.functional.layout_binding.negative.ssbo.tess_evaluation_binding_over_max
dEQP-GLES31.functional.layout_binding.negative.ssbo.vertex_binding_neg
dEQP-GLES31.functional.layout_binding.negative.ssbo.fragment_binding_neg
+dEQP-GLES31.functional.layout_binding.negative.ssbo.tess_control_binding_neg
+dEQP-GLES31.functional.layout_binding.negative.ssbo.tess_evaluation_binding_neg
dEQP-GLES31.functional.layout_binding.negative.ssbo.vertex_binding_over_max_array
dEQP-GLES31.functional.layout_binding.negative.ssbo.fragment_binding_over_max_array
+dEQP-GLES31.functional.layout_binding.negative.ssbo.tess_control_binding_over_max_array
+dEQP-GLES31.functional.layout_binding.negative.ssbo.tess_evaluation_binding_over_max_array
dEQP-GLES31.functional.layout_binding.negative.ssbo.vertex_binding_neg_array
dEQP-GLES31.functional.layout_binding.negative.ssbo.fragment_binding_neg_array
+dEQP-GLES31.functional.layout_binding.negative.ssbo.tess_control_binding_neg_array
+dEQP-GLES31.functional.layout_binding.negative.ssbo.tess_evaluation_binding_neg_array
dEQP-GLES31.functional.layout_binding.negative.ssbo.binding_contradictory
dEQP-GLES31.functional.layout_binding.negative.ssbo.binding_contradictory_array
dEQP-GLES31.functional.layout_binding.negative.image.image2d.vertex_binding_over_max
dEQP-GLES31.functional.layout_binding.negative.image.image2d.fragment_binding_over_max
+dEQP-GLES31.functional.layout_binding.negative.image.image2d.tess_control_binding_over_max
+dEQP-GLES31.functional.layout_binding.negative.image.image2d.tess_evaluation_binding_over_max
dEQP-GLES31.functional.layout_binding.negative.image.image2d.vertex_binding_neg
dEQP-GLES31.functional.layout_binding.negative.image.image2d.fragment_binding_neg
+dEQP-GLES31.functional.layout_binding.negative.image.image2d.tess_control_binding_neg
+dEQP-GLES31.functional.layout_binding.negative.image.image2d.tess_evaluation_binding_neg
dEQP-GLES31.functional.layout_binding.negative.image.image2d.vertex_binding_over_max_array
dEQP-GLES31.functional.layout_binding.negative.image.image2d.fragment_binding_over_max_array
+dEQP-GLES31.functional.layout_binding.negative.image.image2d.tess_control_binding_over_max_array
+dEQP-GLES31.functional.layout_binding.negative.image.image2d.tess_evaluation_binding_over_max_array
dEQP-GLES31.functional.layout_binding.negative.image.image2d.vertex_binding_neg_array
dEQP-GLES31.functional.layout_binding.negative.image.image2d.fragment_binding_neg_array
+dEQP-GLES31.functional.layout_binding.negative.image.image2d.tess_control_binding_neg_array
+dEQP-GLES31.functional.layout_binding.negative.image.image2d.tess_evaluation_binding_neg_array
dEQP-GLES31.functional.layout_binding.negative.image.image2d.binding_contradictory
dEQP-GLES31.functional.layout_binding.negative.image.image2d.binding_contradictory_array
dEQP-GLES31.functional.layout_binding.negative.image.image3d.vertex_binding_over_max
dEQP-GLES31.functional.layout_binding.negative.image.image3d.fragment_binding_over_max
+dEQP-GLES31.functional.layout_binding.negative.image.image3d.tess_control_binding_over_max
+dEQP-GLES31.functional.layout_binding.negative.image.image3d.tess_evaluation_binding_over_max
dEQP-GLES31.functional.layout_binding.negative.image.image3d.vertex_binding_neg
dEQP-GLES31.functional.layout_binding.negative.image.image3d.fragment_binding_neg
+dEQP-GLES31.functional.layout_binding.negative.image.image3d.tess_control_binding_neg
+dEQP-GLES31.functional.layout_binding.negative.image.image3d.tess_evaluation_binding_neg
dEQP-GLES31.functional.layout_binding.negative.image.image3d.vertex_binding_over_max_array
dEQP-GLES31.functional.layout_binding.negative.image.image3d.fragment_binding_over_max_array
+dEQP-GLES31.functional.layout_binding.negative.image.image3d.tess_control_binding_over_max_array
+dEQP-GLES31.functional.layout_binding.negative.image.image3d.tess_evaluation_binding_over_max_array
dEQP-GLES31.functional.layout_binding.negative.image.image3d.vertex_binding_neg_array
dEQP-GLES31.functional.layout_binding.negative.image.image3d.fragment_binding_neg_array
+dEQP-GLES31.functional.layout_binding.negative.image.image3d.tess_control_binding_neg_array
+dEQP-GLES31.functional.layout_binding.negative.image.image3d.tess_evaluation_binding_neg_array
dEQP-GLES31.functional.layout_binding.negative.image.image3d.binding_contradictory
dEQP-GLES31.functional.layout_binding.negative.image.image3d.binding_contradictory_array
dEQP-GLES31.functional.primitive_bounding_box.state_query.initial_value
dEQP-GLES31.functional.primitive_bounding_box.triangles.tessellation_set_per_primitive.vertex_tessellation_fragment.fbo
dEQP-GLES31.functional.primitive_bounding_box.triangles.tessellation_set_per_primitive.vertex_tessellation_geometry_fragment.default_framebuffer
dEQP-GLES31.functional.primitive_bounding_box.triangles.tessellation_set_per_primitive.vertex_tessellation_geometry_fragment.fbo
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.default_framebuffer_bbox_smaller
dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.fbo_bbox_equal
dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.fbo_bbox_larger
dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.fbo_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.fbo_bbox_equal
dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.fbo_bbox_larger
dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.fbo_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.fbo_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.fbo_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.fbo_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.fbo_bbox_equal
dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.fbo_bbox_larger
dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.fbo_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.fbo_bbox_equal
dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.fbo_bbox_larger
dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.fbo_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.fbo_bbox_equal
dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.fbo_bbox_larger
dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.fbo_bbox_smaller
dEQP-GLES31.functional.primitive_bounding_box.points.tessellation_set_per_primitive.vertex_tessellation_fragment.fbo
dEQP-GLES31.functional.primitive_bounding_box.points.tessellation_set_per_primitive.vertex_tessellation_geometry_fragment.default_framebuffer
dEQP-GLES31.functional.primitive_bounding_box.points.tessellation_set_per_primitive.vertex_tessellation_geometry_fragment.fbo
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.default_framebuffer_bbox_smaller
dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.fbo_bbox_equal
dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.fbo_bbox_larger
dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.fbo_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.fbo_bbox_equal
dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.fbo_bbox_larger
dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.fbo_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.fbo_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.fbo_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.fbo_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.fbo_bbox_equal
dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.fbo_bbox_larger
dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.fbo_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.fbo_bbox_equal
dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.fbo_bbox_larger
dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.fbo_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.fbo_bbox_equal
dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.fbo_bbox_larger
dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.fbo_bbox_smaller
dEQP-GLES31.functional.draw_buffers_indexed.random.max_implementation_draw_buffers.18
dEQP-GLES31.functional.draw_buffers_indexed.random.max_implementation_draw_buffers.19
dEQP-GLES31.functional.default_vertex_array_object.vertex_attrib_divisor
+dEQP-GLES31.functional.srgb_texture_decode.skip_decode.srgba8.skipped
+dEQP-GLES31.functional.srgb_texture_decode.skip_decode.srgba8.enabled
+dEQP-GLES31.functional.srgb_texture_decode.skip_decode.srgba8.texel_fetch
+dEQP-GLES31.functional.srgb_texture_decode.skip_decode.srgba8.conversion_gpu
+dEQP-GLES31.functional.srgb_texture_decode.skip_decode.srgba8.toggled
+dEQP-GLES31.functional.srgb_texture_decode.skip_decode.srgba8.multiple_textures
+dEQP-GLES31.functional.srgb_texture_decode.skip_decode.srgba8.using_sampler
+dEQP-GLES31.functional.srgb_texture_decode.skip_decode.sr8.skipped
+dEQP-GLES31.functional.srgb_texture_decode.skip_decode.sr8.enabled
+dEQP-GLES31.functional.srgb_texture_decode.skip_decode.sr8.texel_fetch
+dEQP-GLES31.functional.srgb_texture_decode.skip_decode.sr8.conversion_gpu
+dEQP-GLES31.functional.srgb_texture_decode.skip_decode.sr8.toggled
+dEQP-GLES31.functional.srgb_texture_decode.skip_decode.sr8.multiple_textures
+dEQP-GLES31.functional.srgb_texture_decode.skip_decode.sr8.using_sampler
dEQP-GLES31.functional.primitive_bounding_box.triangles.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
dEQP-GLES31.functional.primitive_bounding_box.triangles.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
dEQP-GLES31.functional.primitive_bounding_box.triangles.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
dEQP-GLES31.functional.primitive_bounding_box.points.global_state.vertex_fragment.default_framebuffer_bbox_equal
dEQP-GLES31.functional.primitive_bounding_box.points.global_state.vertex_fragment.default_framebuffer_bbox_larger
dEQP-GLES31.functional.primitive_bounding_box.points.global_state.vertex_fragment.default_framebuffer_bbox_smaller
dEQP-GLES31.functional.primitive_bounding_box.points.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
dEQP-GLES31.functional.primitive_bounding_box.points.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
dEQP-GLES31.functional.primitive_bounding_box.points.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
dEQP-GLES31.functional.primitive_bounding_box.wide_points.global_state.vertex_fragment.default_framebuffer_bbox_equal
dEQP-GLES31.functional.primitive_bounding_box.wide_points.global_state.vertex_fragment.default_framebuffer_bbox_larger
dEQP-GLES31.functional.primitive_bounding_box.wide_points.global_state.vertex_fragment.default_framebuffer_bbox_smaller
dEQP-GLES31.functional.primitive_bounding_box.triangles.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
dEQP-GLES31.functional.primitive_bounding_box.triangles.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
dEQP-GLES31.functional.primitive_bounding_box.triangles.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
dEQP-GLES31.functional.primitive_bounding_box.points.global_state.vertex_fragment.default_framebuffer_bbox_equal
dEQP-GLES31.functional.primitive_bounding_box.points.global_state.vertex_fragment.default_framebuffer_bbox_larger
dEQP-GLES31.functional.primitive_bounding_box.points.global_state.vertex_fragment.default_framebuffer_bbox_smaller
dEQP-GLES31.functional.primitive_bounding_box.points.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
dEQP-GLES31.functional.primitive_bounding_box.points.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
dEQP-GLES31.functional.primitive_bounding_box.points.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
dEQP-GLES31.functional.primitive_bounding_box.wide_points.global_state.vertex_fragment.default_framebuffer_bbox_equal
dEQP-GLES31.functional.primitive_bounding_box.wide_points.global_state.vertex_fragment.default_framebuffer_bbox_larger
dEQP-GLES31.functional.primitive_bounding_box.wide_points.global_state.vertex_fragment.default_framebuffer_bbox_smaller
dEQP-GLES31.functional.primitive_bounding_box.triangles.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
dEQP-GLES31.functional.primitive_bounding_box.triangles.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
dEQP-GLES31.functional.primitive_bounding_box.triangles.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
dEQP-GLES31.functional.primitive_bounding_box.points.global_state.vertex_fragment.default_framebuffer_bbox_equal
dEQP-GLES31.functional.primitive_bounding_box.points.global_state.vertex_fragment.default_framebuffer_bbox_larger
dEQP-GLES31.functional.primitive_bounding_box.points.global_state.vertex_fragment.default_framebuffer_bbox_smaller
dEQP-GLES31.functional.primitive_bounding_box.points.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
dEQP-GLES31.functional.primitive_bounding_box.points.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
dEQP-GLES31.functional.primitive_bounding_box.points.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
dEQP-GLES31.functional.primitive_bounding_box.wide_points.global_state.vertex_fragment.default_framebuffer_bbox_equal
dEQP-GLES31.functional.primitive_bounding_box.wide_points.global_state.vertex_fragment.default_framebuffer_bbox_larger
dEQP-GLES31.functional.primitive_bounding_box.wide_points.global_state.vertex_fragment.default_framebuffer_bbox_smaller
dEQP-GLES31.functional.primitive_bounding_box.triangles.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
dEQP-GLES31.functional.primitive_bounding_box.triangles.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
dEQP-GLES31.functional.primitive_bounding_box.triangles.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
dEQP-GLES31.functional.primitive_bounding_box.points.global_state.vertex_fragment.default_framebuffer_bbox_equal
dEQP-GLES31.functional.primitive_bounding_box.points.global_state.vertex_fragment.default_framebuffer_bbox_larger
dEQP-GLES31.functional.primitive_bounding_box.points.global_state.vertex_fragment.default_framebuffer_bbox_smaller
dEQP-GLES31.functional.primitive_bounding_box.points.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
dEQP-GLES31.functional.primitive_bounding_box.points.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
dEQP-GLES31.functional.primitive_bounding_box.points.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
dEQP-GLES31.functional.primitive_bounding_box.wide_points.global_state.vertex_fragment.default_framebuffer_bbox_equal
dEQP-GLES31.functional.primitive_bounding_box.wide_points.global_state.vertex_fragment.default_framebuffer_bbox_larger
dEQP-GLES31.functional.primitive_bounding_box.wide_points.global_state.vertex_fragment.default_framebuffer_bbox_smaller
dEQP-GLES31.functional.primitive_bounding_box.triangles.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
dEQP-GLES31.functional.primitive_bounding_box.triangles.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
dEQP-GLES31.functional.primitive_bounding_box.triangles.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
dEQP-GLES31.functional.primitive_bounding_box.points.global_state.vertex_fragment.default_framebuffer_bbox_equal
dEQP-GLES31.functional.primitive_bounding_box.points.global_state.vertex_fragment.default_framebuffer_bbox_larger
dEQP-GLES31.functional.primitive_bounding_box.points.global_state.vertex_fragment.default_framebuffer_bbox_smaller
dEQP-GLES31.functional.primitive_bounding_box.points.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
dEQP-GLES31.functional.primitive_bounding_box.points.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
dEQP-GLES31.functional.primitive_bounding_box.points.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
dEQP-GLES31.functional.primitive_bounding_box.wide_points.global_state.vertex_fragment.default_framebuffer_bbox_equal
dEQP-GLES31.functional.primitive_bounding_box.wide_points.global_state.vertex_fragment.default_framebuffer_bbox_larger
dEQP-GLES31.functional.primitive_bounding_box.wide_points.global_state.vertex_fragment.default_framebuffer_bbox_smaller
--- /dev/null
+# OOB robustness tests for manual testing purposes
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds_non_robust.reset_status.reads.uniform_block.vertex
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds_non_robust.reset_status.reads.uniform_block.fragment
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds_non_robust.reset_status.reads.uniform_block.vertex_and_fragment
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds_non_robust.reset_status.reads.uniform_block.compute
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds_non_robust.reset_status.reads.shader_storage_block.vertex
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds_non_robust.reset_status.reads.shader_storage_block.fragment
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds_non_robust.reset_status.reads.shader_storage_block.vertex_and_fragment
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds_non_robust.reset_status.reads.shader_storage_block.compute
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds_non_robust.reset_status.reads.local_array.vertex
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds_non_robust.reset_status.reads.local_array.fragment
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds_non_robust.reset_status.reads.local_array.vertex_and_fragment
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds_non_robust.reset_status.reads.local_array.compute
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds_non_robust.reset_status.writes.uniform_block.vertex
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds_non_robust.reset_status.writes.uniform_block.fragment
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds_non_robust.reset_status.writes.uniform_block.vertex_and_fragment
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds_non_robust.reset_status.writes.uniform_block.compute
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds_non_robust.reset_status.writes.shader_storage_block.vertex
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds_non_robust.reset_status.writes.shader_storage_block.fragment
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds_non_robust.reset_status.writes.shader_storage_block.vertex_and_fragment
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds_non_robust.reset_status.writes.shader_storage_block.compute
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds_non_robust.reset_status.writes.local_array.vertex
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds_non_robust.reset_status.writes.local_array.fragment
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds_non_robust.reset_status.writes.local_array.vertex_and_fragment
+dEQP-EGL.functional.robustness.reset_context.shaders.out_of_bounds_non_robust.reset_status.writes.local_array.compute
+dEQP-EGL.functional.robustness.reset_context.fixed_function_pipeline_non_robust.reset_status.index_buffer_out_of_bounds
+dEQP-EGL.functional.robustness.reset_context.fixed_function_pipeline_non_robust.reset_status.vertex_buffer_out_of_bounds
dEQP-GLES31.functional.shaders.builtin_functions.precision.cos.mediump_*
dEQP-GLES31.functional.shaders.builtin_functions.precision.tan.mediump_*
-# Bug 22713865
-dEQP-GLES31.functional.primitive_bounding_box.*lines*default_framebuffer_bbox*
-dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.fbo_bbox_equal
-dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.fbo_bbox_larger
-dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.fbo_bbox_smaller
-dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.fbo_bbox_equal
-dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.fbo_bbox_larger
-dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.fbo_bbox_smaller
-
# Bug 23288315
dEQP-GLES31.functional.draw_indirect.compute_interop.large.drawelements_separate_grid_1000x1000_drawcount_1
dEQP-GLES31.functional.draw_indirect.compute_interop.large.drawelements_separate_grid_1200x1200_drawcount_1
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_1
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_2
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_3
-dEQP-GLES31.functional.separate_shader.validation.varying.match_different_struct_names
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_name
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_type
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_precision
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_precision
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_different_member_interpolation
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_array_size
-dEQP-GLES31.functional.separate_shader.validation.io_blocks.match_different_member_struct_names
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_name
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_type
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_precision
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_1
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_2
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_3
-dEQP-GLES31.functional.separate_shader.validation.varying.match_different_struct_names
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_name
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_type
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_precision
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_precision
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_different_member_interpolation
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_array_size
-dEQP-GLES31.functional.separate_shader.validation.io_blocks.match_different_member_struct_names
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_name
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_type
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_precision
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_1
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_2
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_3
-dEQP-GLES31.functional.separate_shader.validation.varying.match_different_struct_names
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_name
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_type
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_precision
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_precision
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_different_member_interpolation
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_array_size
-dEQP-GLES31.functional.separate_shader.validation.io_blocks.match_different_member_struct_names
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_name
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_type
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_precision
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_1
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_2
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_3
-dEQP-GLES31.functional.separate_shader.validation.varying.match_different_struct_names
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_name
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_type
dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_precision
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_precision
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_different_member_interpolation
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_array_size
-dEQP-GLES31.functional.separate_shader.validation.io_blocks.match_different_member_struct_names
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_name
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_type
dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_precision
destination.mExcludeFilters = new ArrayList<>(source.mExcludeFilters);
destination.mAbi = source.mAbi;
destination.mLogData = source.mLogData;
+ destination.mCollectTestsOnly = source.mCollectTestsOnly;
}
/**
import re
import sys
import shutil
+import string
import argparse
+import time
import common
print "%-30s : %s" % (entry[0], entry[1])
print " "
+# Return NDK version as [<major>,<minor>] or None if cannot be figured out.
+def getNdkVersion (path):
+ if path == None:
+ return None
+
+ propFilePath = os.path.join(path, "source.properties")
+ try:
+ with open(propFilePath) as propFile:
+ for line in propFile:
+ keyValue = map(lambda x: string.strip(x), line.split("="))
+ if keyValue[0] == "Pkg.Revision":
+ versionParts = keyValue[1].split(".")
+ return tuple(map(int, versionParts[0:2]))
+ except:
+ print("Could not read source prop file '%s'" % propFilePath)
+
+ return None
+
+def checkConfig ():
+ HOST_OS_TO_DOWNLOAD_STRING = {
+ "linux-x86_64" : "linux-x86_64",
+ "windows" : "windows-x86",
+ "windows-x86_64" : "windows-x86_64"
+ }
+
+ version = getNdkVersion(common.ANDROID_NDK_PATH)
+ # Note: NDK currently maintains compatibility between minor
+ # versions. Error out only on major version mismatch.
+ if version == None or version[0] != common.ANDROID_NDK_VERSION[0]:
+ print("**** WARNING! Deqp requires NDK version %s" % common.ANDROID_NDK_VERSION_STRING)
+ print("**** NDK Path %s does not appear to have that version." % common.ANDROID_NDK_PATH)
+
+ # Download hint will use the version encored in common.py, not
+ # the latest minor version available
+ versionString = common.ANDROID_NDK_VERSION_STRING
+ if common.ANDROID_NDK_HOST_OS in HOST_OS_TO_DOWNLOAD_STRING:
+ osString = HOST_OS_TO_DOWNLOAD_STRING[common.ANDROID_NDK_HOST_OS]
+ print("**** Please install from https://dl.google.com/android/repository/android-ndk-%s-%s.zip" % (versionString, osString))
+ else:
+ print("**** Please download version", versionString, "from https://developer.android.com/ndk/downloads/index.html")
+
+ return False
+
+ return True
+
if __name__ == "__main__":
nativeBuildTypes = ['Release', 'Debug', 'MinSizeRel', 'RelWithAsserts', 'RelWithDebInfo']
androidBuildTypes = ['debug', 'release']
parser.add_argument('--dump-config', dest='dumpConfig', action='store_true', help="Print out all configurations variables")
parser.add_argument('--java-api', dest='javaApi', default=common.ANDROID_JAVA_API, help="Set the API signature for the java build.")
parser.add_argument('-p', '--parallel-build', dest='parallelBuild', action="store_true", help="Build native libraries in parallel.")
+ parser.add_argument('--skip-config-check', dest='skipConfigCheck', action="store_true", default=False, help="Skips config check. Warranty void.")
args = parser.parse_args()
if args.dumpConfig:
dumpConfig()
+ if not args.skipConfigCheck and not checkConfig():
+ print "Config check failed, exit"
+ exit(-1)
+
build(buildRoot=os.path.abspath(args.buildRoot), androidBuildType=args.androidBuildType, nativeBuildType=args.nativeBuildType, javaApi=args.javaApi, doParallelBuild=args.parallelBuild)
if retcode != 0:
raise Exception("Failed to execute '%s', got %d" % (str(args), retcode))
-def execArgsInDirectory (args, cwd, linePrefix=""):
+def execArgsInDirectory (args, cwd, linePrefix="", failOnNonZeroExit=True):
def readApplyPrefixAndPrint (source, prefix, sink):
while True:
stdoutJob.start()
stderrJob.start()
retcode = process.wait()
- if retcode != 0:
+ if failOnNonZeroExit and retcode != 0:
raise Exception("Failed to execute '%s', got %d" % (str(args), retcode))
def serialApply(f, argsList):
if proc.returncode != 0:
raise Exception("adb devices -l failed, got %d" % proc.returncode)
- ptrn = re.compile(r'^([a-zA-Z0-9:]+)\s+.*product:([^\s]+)\s+model:([^\s]+)\s+device:([^\s]+)')
+ ptrn = re.compile(r'^([a-zA-Z0-9\.:]+)\s+.*product:([^\s]+)\s+model:([^\s]+)\s+device:([^\s]+)')
devices = []
for line in stdout.splitlines()[1:]:
if len(line.strip()) == 0:
ANDROID_JAVA_API = "android-22"
NATIVE_LIB_NAME = "libdeqp.so"
+def makeNdkVersionString (version):
+ minorVersionString = (chr(ord('a') + version[1]) if version[1] > 0 else "")
+ return "r%d%s" % (version[0], minorVersionString)
+
+ANDROID_NDK_VERSION = (11,0)
+ANDROID_NDK_VERSION_STRING = makeNdkVersionString(ANDROID_NDK_VERSION)
def selectNDKPath ():
candidates = [
- os.path.expanduser("~/android-ndk-r11"),
- "C:/android/android-ndk-r11",
+ os.path.expanduser("~/android-ndk-" + ANDROID_NDK_VERSION_STRING),
+ "C:/android/android-ndk-" + ANDROID_NDK_VERSION_STRING,
os.environ.get("ANDROID_NDK_PATH", None), # If not defined, return None
]
common.execArgsInDirectory([common.ADB_BIN] + extraArgs + [
'uninstall',
'com.drawelements.deqp'
- ], buildRoot, printPrefix)
+ ], buildRoot, printPrefix, failOnNonZeroExit=False)
print printPrefix + "Remove complete\n",
print printPrefix + "Installing dEQP Package from %s...\n" %(buildRoot),
""
end
+ case output_non_array
+ version 310 es
+ desc "Tessellation control output out not an array"
+ require extension { "GL_OES_tessellation_shader" | "GL_EXT_tessellation_shader" } in { tessellation_control, tessellation_evaluation }
+ expect compile_or_link_fail
+ values
+ {
+ input float in0 = 1.0;
+ output float out0 = 1.0;
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ out mediump float tc_in;
+ void main()
+ {
+ tc_in = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ tessellation_control ""
+ #version 310 es
+ ${TESSELLATION_CONTROL_DECLARATIONS}
+ in mediump float tc_in[];
+ out mediump float tc_out; // not an array
+ void main()
+ {
+ tc_out = tc_in[gl_InvocationID];
+ ${TESSELLATION_CONTROL_OUTPUT}
+ }
+ ""
+ tessellation_evaluation ""
+ #version 310 es
+ ${TESSELLATION_EVALUATION_DECLARATIONS}
+ in mediump float tc_out[];
+ out mediump float te_out;
+ void main()
+ {
+ te_out = tc_out[2];
+ ${TESSELLATION_EVALUATION_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float te_out;
+ void main()
+ {
+ out0 = te_out;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
case input_array_size_mismatch
version 310 es
desc "Tessellation control input array size is not gl_MaxPatchVertices"
""
end
+ case invalid_patch_in_usage
+ version 310 es
+ desc "Invalid use of the patch_in qualifier in a non-tessellation shader"
+ expect compile_or_link_fail
+ require extension { "GL_OES_tessellation_shader" | "GL_EXT_tessellation_shader" } in { tessellation_control, tessellation_evaluation }
+ values
+ {
+ input float in0 = 1.0;
+ output float out0 = 1.0;
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ out mediump float frag_in;
+ out mediump float var;
+ void main()
+ {
+ frag_in = in0;
+ var = 2.0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ patch in mediump float var; // invalid use of patch_in
+ in mediump float frag_in;
+ void main()
+ {
+ out0 = frag_in * var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case invalid_patch_out_usage
+ version 310 es
+ desc "Invalid use of the patch_out qualifier in a non-tessellation shader"
+ expect compile_or_link_fail
+ require extension { "GL_OES_tessellation_shader" | "GL_EXT_tessellation_shader" } in { tessellation_control, tessellation_evaluation }
+ values
+ {
+ input float in0 = 1.0;
+ output float out0 = 1.0;
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ out mediump float frag_in;
+ patch out mediump float var;
+ void main()
+ {
+ frag_in = in0;
+ var = 2.0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float var; // invalid use of patch_out
+ in mediump float frag_in;
+ void main()
+ {
+ out0 = frag_in * var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case invalid_per_patch_qualifier_usage
+ version 310 es
+ desc "Invalid use of per-patch qualifier on input variable in tessellation control shader"
+ require extension { "GL_OES_tessellation_shader" | "GL_EXT_tessellation_shader" } in { tessellation_control, tessellation_evaluation }
+ expect compile_or_link_fail
+ values
+ {
+ input float in0 = 1.0;
+ output float out0 = 1.0;
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ out mediump float tc_in;
+ void main()
+ {
+ tc_in = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ tessellation_control ""
+ #version 310 es
+ ${TESSELLATION_CONTROL_DECLARATIONS}
+ patch in mediump float tc_in; // patch in not allowed in TCS
+ patch out mediump float tc_out;
+ void main()
+ {
+ tc_out = tc_in;
+ ${TESSELLATION_CONTROL_OUTPUT}
+ }
+ ""
+ tessellation_evaluation ""
+ #version 310 es
+ ${TESSELLATION_EVALUATION_DECLARATIONS}
+ patch in mediump float tc_out;
+ out mediump float te_out;
+ void main()
+ {
+ te_out = tc_out;
+ ${TESSELLATION_EVALUATION_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float te_out;
+ void main()
+ {
+ out0 = te_out;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
case per_patch_qualifier_mismatch_1
version 310 es
desc "Tessellation control output is per-patch qualified, evaluation input is not"
case input_block_non_array
version 310 es
- desc "Tessellation control shader input block with explicit array"
+ desc "Tessellation control shader input block without explicit array"
require extension { "GL_OES_tessellation_shader" | "GL_EXT_tessellation_shader" } in { tessellation_control, tessellation_evaluation }
require extension { "GL_OES_shader_io_blocks" | "GL_EXT_shader_io_blocks" } in { vertex }
expect compile_or_link_fail
""
end
+ case output_block_non_array
+ version 310 es
+ desc "Tessellation control shader output block without explicit array"
+ require extension { "GL_OES_tessellation_shader" | "GL_EXT_tessellation_shader" } in { tessellation_control, tessellation_evaluation }
+ require extension { "GL_OES_shader_io_blocks" | "GL_EXT_shader_io_blocks" } in { vertex }
+ expect compile_or_link_fail
+ values { output float out0 = 1.0; }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ out mediump float tc_in;
+ void main()
+ {
+ tc_in = 1.0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ tessellation_control ""
+ #version 310 es
+ ${TESSELLATION_CONTROL_DECLARATIONS}
+ in mediump float tc_in[];
+ out IOBlockName
+ {
+ mediump float var;
+ } outputInstanceName; // not an array
+ void main()
+ {
+ outputInstanceName.var = tc_in[gl_InvocationID];
+ ${TESSELLATION_CONTROL_OUTPUT}
+ }
+ ""
+ tessellation_evaluation ""
+ #version 310 es
+ ${TESSELLATION_EVALUATION_DECLARATIONS}
+ in IOBlockName
+ {
+ mediump float var;
+ } outputInstanceName[];
+ out mediump float te_out;
+ void main()
+ {
+ te_out = outputInstanceName[2].var;
+ ${TESSELLATION_EVALUATION_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float te_out;
+ void main()
+ {
+ out0 = te_out;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
case input_block_array_size_mismatch
version 310 es
desc "Tessellation control shader input block array, size not gl_MaxPatchVertices"
import "linkage_tessellation_uniform_types.test"
end
+
+group layout_declarations "Layout linkage"
+ group rules "Rules"
+
+ case primitive_mode_mismatch
+ version 310 es
+ desc "Tessellation evaluation shader primitive mode mismatch"
+ expect compile_or_link_fail
+ require extension { "GL_OES_tessellation_shader" | "GL_EXT_tessellation_shader" } in { tessellation_control, tessellation_evaluation }
+ values
+ {
+ input float in0 = 1.0;
+ output float out0 = 1.0;
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ out mediump float tc_in;
+ void main()
+ {
+ tc_in = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ tessellation_control ""
+ #version 310 es
+ ${TESSELLATION_CONTROL_DECLARATIONS}
+ in mediump float tc_in[];
+ out mediump float tc_out[];
+ void main()
+ {
+ tc_out[gl_InvocationID] = tc_in[gl_InvocationID];
+ ${TESSELLATION_CONTROL_OUTPUT}
+ }
+ ""
+ tessellation_evaluation ""
+ #version 310 es
+ layout (triangles) in;
+ layout (isolines) in;
+ in mediump float tc_out[];
+ out mediump float te_out;
+ void main()
+ {
+ te_out = tc_out[2];
+ ${TESSELLATION_EVALUATION_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float te_out;
+ void main()
+ {
+ out0 = te_out;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case spacing_mode_mismatch
+ version 310 es
+ desc "Tessellation evaluation shader spacing mode mismatch"
+ expect compile_or_link_fail
+ require extension { "GL_OES_tessellation_shader" | "GL_EXT_tessellation_shader" } in { tessellation_control, tessellation_evaluation }
+ values
+ {
+ input float in0 = 1.0;
+ output float out0 = 1.0;
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ out mediump float tc_in;
+ void main()
+ {
+ tc_in = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ tessellation_control ""
+ #version 310 es
+ ${TESSELLATION_CONTROL_DECLARATIONS}
+ in mediump float tc_in[];
+ out mediump float tc_out[];
+ void main()
+ {
+ tc_out[gl_InvocationID] = tc_in[gl_InvocationID];
+ ${TESSELLATION_CONTROL_OUTPUT}
+ }
+ ""
+ tessellation_evaluation ""
+ #version 310 es
+ layout (triangles, equal_spacing) in;
+ layout (triangles, fractional_odd_spacing) in;
+ in mediump float tc_out[];
+ out mediump float te_out;
+ void main()
+ {
+ te_out = tc_out[2];
+ ${TESSELLATION_EVALUATION_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float te_out;
+ void main()
+ {
+ out0 = te_out;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case vertex_order_mismatch
+ version 310 es
+ desc "Tessellation evaluation shader vertex order mismatch"
+ expect compile_or_link_fail
+ require extension { "GL_OES_tessellation_shader" | "GL_EXT_tessellation_shader" } in { tessellation_control, tessellation_evaluation }
+ values
+ {
+ input float in0 = 1.0;
+ output float out0 = 1.0;
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ out mediump float tc_in;
+ void main()
+ {
+ tc_in = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ tessellation_control ""
+ #version 310 es
+ ${TESSELLATION_CONTROL_DECLARATIONS}
+ in mediump float tc_in[];
+ out mediump float tc_out[];
+ void main()
+ {
+ tc_out[gl_InvocationID] = tc_in[gl_InvocationID];
+ ${TESSELLATION_CONTROL_OUTPUT}
+ }
+ ""
+ tessellation_evaluation ""
+ #version 310 es
+ layout (triangles, cw) in;
+ layout (triangles, ccw) in;
+ in mediump float tc_out[];
+ out mediump float te_out;
+ void main()
+ {
+ te_out = tc_out[2];
+ ${TESSELLATION_EVALUATION_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float te_out;
+ void main()
+ {
+ out0 = te_out;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case vertex_count_mismatch
+ version 310 es
+ desc "Tessellation control shader vertex count mismatch"
+ expect compile_or_link_fail
+ require extension { "GL_OES_tessellation_shader" | "GL_EXT_tessellation_shader" } in { tessellation_control, tessellation_evaluation }
+ values
+ {
+ input float in0 = 1.0;
+ output float out0 = 1.0;
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ out mediump float tc_in;
+ void main()
+ {
+ tc_in = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ tessellation_control ""
+ #version 310 es
+ layout (vertices=3) out;
+ layout (vertices=4) out;
+ in mediump float tc_in[];
+ out mediump float tc_out[];
+ void main()
+ {
+ tc_out[gl_InvocationID] = tc_in[gl_InvocationID];
+ ${TESSELLATION_CONTROL_OUTPUT}
+ }
+ ""
+ tessellation_evaluation ""
+ #version 310 es
+ ${TESSELLATION_EVALUATION_DECLARATIONS}
+ in mediump float tc_out[];
+ out mediump float te_out;
+ void main()
+ {
+ te_out = tc_out[2];
+ ${TESSELLATION_EVALUATION_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float te_out;
+ void main()
+ {
+ out0 = te_out;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+ end
+end
+
+group barriers "Barriers"
+ group rules "Rules"
+
+ case invalid_barrier_usage_within_control_flow
+ version 310 es
+ desc "Tessellation control shader invalid barrier usage within control flow statement"
+ expect compile_or_link_fail
+ require extension { "GL_OES_tessellation_shader" | "GL_EXT_tessellation_shader" } in { tessellation_control, tessellation_evaluation }
+ values
+ {
+ input float in0 = 1.0;
+ output float out0 = 1.0;
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ out mediump float tc_in;
+ void main()
+ {
+ tc_in = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ tessellation_control ""
+ #version 310 es
+ ${TESSELLATION_CONTROL_DECLARATIONS}
+ in mediump float tc_in[];
+ out mediump float tc_out[];
+
+ void main()
+ {
+ if (gl_InvocationID == 0)
+ barrier(); // error: within control flow
+
+ tc_out[gl_InvocationID] = tc_in[gl_InvocationID];
+ ${TESSELLATION_CONTROL_OUTPUT}
+ }
+ ""
+ tessellation_evaluation ""
+ #version 310 es
+ ${TESSELLATION_EVALUATION_DECLARATIONS}
+ in mediump float tc_out[];
+ out mediump float te_out;
+ void main()
+ {
+ te_out = tc_out[2];
+ ${TESSELLATION_EVALUATION_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float te_out;
+ void main()
+ {
+ out0 = te_out;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case invalid_barrier_usage_after_return
+ version 310 es
+ desc "Tessellation control shader invalid barrier usage after main() returns"
+ expect compile_or_link_fail
+ require extension { "GL_OES_tessellation_shader" | "GL_EXT_tessellation_shader" } in { tessellation_control, tessellation_evaluation }
+ values
+ {
+ input float in0 = 1.0;
+ output float out0 = 1.0;
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ out mediump float tc_in;
+ void main()
+ {
+ tc_in = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ tessellation_control ""
+ #version 310 es
+ ${TESSELLATION_CONTROL_DECLARATIONS}
+ in mediump float tc_in[];
+ out mediump float tc_out[];
+
+ void main()
+ {
+ tc_out[gl_InvocationID] = tc_in[gl_InvocationID];
+ ${TESSELLATION_CONTROL_OUTPUT}
+
+ return;
+ barrier(); // error: barrier() after return
+ }
+ ""
+ tessellation_evaluation ""
+ #version 310 es
+ ${TESSELLATION_EVALUATION_DECLARATIONS}
+ in mediump float tc_out[];
+ out mediump float te_out;
+ void main()
+ {
+ te_out = tc_out[2];
+ ${TESSELLATION_EVALUATION_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float te_out;
+ void main()
+ {
+ out0 = te_out;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+ end
+end
end
end
- case match_different_struct_names
+ case mismatch_different_struct_names
version 310 es
desc "Variable struct names different but otherwise identical"
- expect pass
+ expect validation_fail
pipeline_program
active_stages {vertex}
end
end
- case match_different_member_struct_names
+ case mismatch_different_member_struct_names
version 310 es
desc "IO-blocks match with structs with different names"
- expect pass
+ expect validation_fail
pipeline_program
active_stages {vertex}
/* WARNING: This is auto-generated file. Do not modify, since changes will
* be lost! Modify the generating script instead.
*
- * Generated from Khronos EGL API description (egl.xml) revision 32725.
+ * Generated from Khronos EGL API description (egl.xml) revision 33315.
*/
eglw::EGLBoolean CallLogWrapper::eglBindAPI (eglw::EGLenum api)
/* WARNING: This is auto-generated file. Do not modify, since changes will
* be lost! Modify the generating script instead.
*
- * Generated from Khronos EGL API description (egl.xml) revision 32725.
+ * Generated from Khronos EGL API description (egl.xml) revision 33315.
*/
eglw::EGLBoolean eglBindAPI (eglw::EGLenum api);
eglw::EGLBoolean eglBindTexImage (eglw::EGLDisplay dpy, eglw::EGLSurface surface, eglw::EGLint buffer);
#include "egluUtil.hpp"
#include "egluConfigInfo.hpp"
#include "eglwEnums.hpp"
+#include "deSTLUtil.hpp"
#include <algorithm>
if (m_type == TYPE_CONFIG_INFO)
return m_cfg.configInfo->getAttribute(attrib);
else
- return getConfigAttribInt(*m_cfg.object.egl, m_cfg.object.display, m_cfg.object.config, attrib);
+ {
+ if (attrib == EGL_COLOR_COMPONENT_TYPE_EXT)
+ {
+ const std::vector<std::string> extensions = getDisplayExtensions(*m_cfg.object.egl, m_cfg.object.display);
+
+ if (de::contains(extensions.begin(), extensions.end(), "EGL_EXT_pixel_format_float"))
+ return getConfigAttribInt(*m_cfg.object.egl, m_cfg.object.display, m_cfg.object.config, attrib);
+ else
+ return EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
+ }
+ else
+ return getConfigAttribInt(*m_cfg.object.egl, m_cfg.object.display, m_cfg.object.config, attrib);
+ }
}
-int CandidateConfig::id (void) const { return get(EGL_CONFIG_ID); }
-int CandidateConfig::redSize (void) const { return get(EGL_RED_SIZE); }
-int CandidateConfig::greenSize (void) const { return get(EGL_GREEN_SIZE); }
-int CandidateConfig::blueSize (void) const { return get(EGL_BLUE_SIZE); }
-int CandidateConfig::alphaSize (void) const { return get(EGL_ALPHA_SIZE); }
-int CandidateConfig::depthSize (void) const { return get(EGL_DEPTH_SIZE); }
-int CandidateConfig::stencilSize (void) const { return get(EGL_STENCIL_SIZE); }
-int CandidateConfig::samples (void) const { return get(EGL_SAMPLES); }
-deUint32 CandidateConfig::renderableType (void) const { return (deUint32)get(EGL_RENDERABLE_TYPE); }
-deUint32 CandidateConfig::surfaceType (void) const { return (deUint32)get(EGL_SURFACE_TYPE); }
+int CandidateConfig::id (void) const { return get(EGL_CONFIG_ID); }
+int CandidateConfig::redSize (void) const { return get(EGL_RED_SIZE); }
+int CandidateConfig::greenSize (void) const { return get(EGL_GREEN_SIZE); }
+int CandidateConfig::blueSize (void) const { return get(EGL_BLUE_SIZE); }
+int CandidateConfig::alphaSize (void) const { return get(EGL_ALPHA_SIZE); }
+int CandidateConfig::depthSize (void) const { return get(EGL_DEPTH_SIZE); }
+int CandidateConfig::stencilSize (void) const { return get(EGL_STENCIL_SIZE); }
+int CandidateConfig::samples (void) const { return get(EGL_SAMPLES); }
+deUint32 CandidateConfig::renderableType (void) const { return (deUint32)get(EGL_RENDERABLE_TYPE); }
+deUint32 CandidateConfig::surfaceType (void) const { return (deUint32)get(EGL_SURFACE_TYPE); }
+deUint32 CandidateConfig::colorComponentType (void) const { return (deUint32)get(EGL_COLOR_COMPONENT_TYPE_EXT); }
FilterList& FilterList::operator<< (ConfigFilter filter)
{
deUint32 renderableType (void) const;
deUint32 surfaceType (void) const;
+ deUint32 colorComponentType (void) const;
tcu::RGBA colorBits (void) const { return tcu::RGBA(redSize(), greenSize(), blueSize(), alphaSize()); }
case EGL_YUV_CSC_STANDARD_EXT: return yuvCscStandard;
case EGL_YUV_PLANE_BPP_EXT: return yuvPlaneBpp;
+ // EGL_EXT_pixel_format_float
+ case EGL_COLOR_COMPONENT_TYPE_EXT: return colorComponentType;
+
default: TCU_THROW(InternalError, "Unknown attribute");
}
}
EGLU_CHECK_MSG(egl, "Failed to query EGL_EXT_yuv_surface config attribs");
}
+
+ if (de::contains(extensions.begin(), extensions.end(), "EGL_EXT_pixel_format_float"))
+ {
+ egl.getConfigAttrib(display, config, EGL_COLOR_COMPONENT_TYPE_EXT, (EGLint*)&dst->colorComponentType);
+
+ EGLU_CHECK_MSG(egl, "Failed to query EGL_EXT_pixel_format_float config attribs");
+ }
+ else
+ dst->colorComponentType = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
}
} // eglu
deUint32 yuvCscStandard;
deInt32 yuvPlaneBpp;
+ // EGL_EXT_pixel_format_float
+ deUint32 colorComponentType;
+
ConfigInfo (void)
: bufferSize (0)
, redSize (0)
, yuvDepthRange (EGL_NONE)
, yuvCscStandard (EGL_NONE)
, yuvPlaneBpp (EGL_YUV_PLANE_BPP_0_EXT)
+ , colorComponentType (EGL_NONE)
{
}
/* WARNING: This is auto-generated file. Do not modify, since changes will
* be lost! Modify the generating script instead.
*
- * Generated from Khronos EGL API description (egl.xml) revision 32725.
+ * Generated from Khronos EGL API description (egl.xml) revision 33315.
*/
const char* getBooleanName (int value)
case EGL_TRANSPARENT_RED_VALUE: return "EGL_TRANSPARENT_RED_VALUE";
case EGL_TRANSPARENT_GREEN_VALUE: return "EGL_TRANSPARENT_GREEN_VALUE";
case EGL_TRANSPARENT_BLUE_VALUE: return "EGL_TRANSPARENT_BLUE_VALUE";
+ case EGL_COLOR_COMPONENT_TYPE_EXT: return "EGL_COLOR_COMPONENT_TYPE_EXT";
default: return DE_NULL;
}
}
}
}
+const char* getColorComponentTypeName (int value)
+{
+ switch (value)
+ {
+ case EGL_COLOR_COMPONENT_TYPE_FIXED_EXT: return "EGL_COLOR_COMPONENT_TYPE_FIXED_EXT";
+ case EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT: return "EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT";
+ default: return DE_NULL;
+ }
+}
+
const char* getSurfaceTargetName (int value)
{
switch (value)
/* WARNING: This is auto-generated file. Do not modify, since changes will
* be lost! Modify the generating script instead.
*
- * Generated from Khronos EGL API description (egl.xml) revision 32725.
+ * Generated from Khronos EGL API description (egl.xml) revision 33315.
*/
const char* getBooleanName (int value);
const char* getBoolDontCareName (int value);
const char* getSurfaceAttribName (int value);
const char* getYuvOrderName (int value);
const char* getYuvPlaneBppName (int value);
+const char* getColorComponentTypeName (int value);
const char* getSurfaceTargetName (int value);
const char* getColorBufferTypeName (int value);
const char* getConfigCaveatName (int value);
inline tcu::Format::Enum<int, 2> getSurfaceAttribStr (int value) { return tcu::Format::Enum<int, 2>(getSurfaceAttribName, value); }
inline tcu::Format::Enum<int, 2> getYuvOrderStr (int value) { return tcu::Format::Enum<int, 2>(getYuvOrderName, value); }
inline tcu::Format::Enum<int, 2> getYuvPlaneBppStr (int value) { return tcu::Format::Enum<int, 2>(getYuvPlaneBppName, value); }
+inline tcu::Format::Enum<int, 2> getColorComponentTypeStr (int value) { return tcu::Format::Enum<int, 2>(getColorComponentTypeName, value); }
inline tcu::Format::Enum<int, 2> getSurfaceTargetStr (int value) { return tcu::Format::Enum<int, 2>(getSurfaceTargetName, value); }
inline tcu::Format::Enum<int, 2> getColorBufferTypeStr (int value) { return tcu::Format::Enum<int, 2>(getColorBufferTypeName, value); }
inline tcu::Format::Enum<int, 2> getConfigCaveatStr (int value) { return tcu::Format::Enum<int, 2>(getConfigCaveatName, value); }
/* WARNING: This is auto-generated file. Do not modify, since changes will
* be lost! Modify the generating script instead.
*
- * Generated from Khronos EGL API description (egl.xml) revision 32725.
+ * Generated from Khronos EGL API description (egl.xml) revision 33315.
*/
#define EGL_PBUFFER_BIT 0x0001
#define EGL_PIXMAP_BIT 0x0002
#define EGL_YUV_PLANE_BPP_0_EXT 0x331B
#define EGL_YUV_PLANE_BPP_8_EXT 0x331C
#define EGL_YUV_PLANE_BPP_10_EXT 0x331D
+#define EGL_COLOR_COMPONENT_TYPE_EXT 0x3339
+#define EGL_COLOR_COMPONENT_TYPE_FIXED_EXT 0x333A
+#define EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT 0x333B
/* WARNING: This is auto-generated file. Do not modify, since changes will
* be lost! Modify the generating script instead.
*
- * Generated from Khronos EGL API description (egl.xml) revision 32725.
+ * Generated from Khronos EGL API description (egl.xml) revision 33315.
*/
EGLBoolean bindAPI (EGLenum api) const;
EGLBoolean bindTexImage (EGLDisplay dpy, EGLSurface surface, EGLint buffer) const;
/* WARNING: This is auto-generated file. Do not modify, since changes will
* be lost! Modify the generating script instead.
*
- * Generated from Khronos EGL API description (egl.xml) revision 32725.
+ * Generated from Khronos EGL API description (egl.xml) revision 33315.
*/
EGLBoolean FuncPtrLibrary::bindAPI (EGLenum api) const
/* WARNING: This is auto-generated file. Do not modify, since changes will
* be lost! Modify the generating script instead.
*
- * Generated from Khronos EGL API description (egl.xml) revision 32725.
+ * Generated from Khronos EGL API description (egl.xml) revision 33315.
*/
typedef EGLW_APICALL EGLBoolean (EGLW_APIENTRY* eglBindAPIFunc) (EGLenum api);
typedef EGLW_APICALL EGLBoolean (EGLW_APIENTRY* eglBindTexImageFunc) (EGLDisplay dpy, EGLSurface surface, EGLint buffer);
/* WARNING: This is auto-generated file. Do not modify, since changes will
* be lost! Modify the generating script instead.
*
- * Generated from Khronos EGL API description (egl.xml) revision 32725.
+ * Generated from Khronos EGL API description (egl.xml) revision 33315.
*/
eglBindAPIFunc bindAPI;
eglBindTexImageFunc bindTexImage;
/* WARNING: This is auto-generated file. Do not modify, since changes will
* be lost! Modify the generating script instead.
*
- * Generated from Khronos EGL API description (egl.xml) revision 32725.
+ * Generated from Khronos EGL API description (egl.xml) revision 33315.
*/
dst->bindAPI = (eglBindAPIFunc) loader->get("eglBindAPI");
dst->bindTexImage = (eglBindTexImageFunc) loader->get("eglBindTexImage");
/* WARNING: This is auto-generated file. Do not modify, since changes will
* be lost! Modify the generating script instead.
*
- * Generated from Khronos EGL API description (egl.xml) revision 32725.
+ * Generated from Khronos EGL API description (egl.xml) revision 33315.
*/
dst->clientWaitSyncKHR = (eglClientWaitSyncKHRFunc) loader->get("eglClientWaitSyncKHR");
dst->createImageKHR = (eglCreateImageKHRFunc) loader->get("eglCreateImageKHR");
/* WARNING: This is auto-generated file. Do not modify, since changes will
* be lost! Modify the generating script instead.
*
- * Generated from Khronos EGL API description (egl.xml) revision 32725.
+ * Generated from Khronos EGL API description (egl.xml) revision 33315.
*/
virtual EGLBoolean bindAPI (EGLenum api) const = 0;
virtual EGLBoolean bindTexImage (EGLDisplay dpy, EGLSurface surface, EGLint buffer) const = 0;
/* WARNING: This is auto-generated file. Do not modify, since changes will
* be lost! Modify the generating script instead.
*
- * Generated from Khronos EGL API description (egl.xml) revision 32725.
+ * Generated from Khronos EGL API description (egl.xml) revision 33315.
*/
{ "eglBindAPI", (deFunctionPtr)eglBindAPI },
{ "eglBindTexImage", (deFunctionPtr)eglBindTexImage },
/* WARNING: This is auto-generated file. Do not modify, since changes will
* be lost! Modify the generating script instead.
*
- * Generated from Khronos EGL API description (egl.xml) revision 32725.
+ * Generated from Khronos EGL API description (egl.xml) revision 33315.
*/
{ "eglBindAPI", (deFunctionPtr)eglBindAPI },
{ "eglBindTexImage", (deFunctionPtr)eglBindTexImage },
case GL_INVALID_OPERATION: return "GL_INVALID_OPERATION";
case GL_OUT_OF_MEMORY: return "GL_OUT_OF_MEMORY";
case GL_INVALID_FRAMEBUFFER_OPERATION: return "GL_INVALID_FRAMEBUFFER_OPERATION";
+ case GL_CONTEXT_LOST: return "GL_CONTEXT_LOST";
default: return DE_NULL;
}
}
}
}
+const char* getGraphicsResetStatusName (int value)
+{
+ switch (value)
+ {
+ case GL_NO_ERROR: return "GL_NO_ERROR";
+ case GL_GUILTY_CONTEXT_RESET: return "GL_GUILTY_CONTEXT_RESET";
+ case GL_INNOCENT_CONTEXT_RESET: return "GL_INNOCENT_CONTEXT_RESET";
+ case GL_UNKNOWN_CONTEXT_RESET: return "GL_UNKNOWN_CONTEXT_RESET";
+ default: return DE_NULL;
+ }
+}
+
tcu::Format::Bitfield<16> getBufferMaskStr (int value)
{
static const tcu::Format::BitDesc s_desc[] =
const char* getPipelineParamName (int value);
const char* getPatchParamName (int value);
const char* getTextureFormatName (int value);
+const char* getGraphicsResetStatusName (int value);
tcu::Format::Bitfield<16> getBufferMaskStr (int value);
tcu::Format::Bitfield<16> getBufferMapFlagsStr (int value);
tcu::Format::Bitfield<16> getMemoryBarrierFlagsStr (int value);
inline tcu::Format::Enum<int, 2> getPipelineParamStr (int value) { return tcu::Format::Enum<int, 2>(getPipelineParamName, value); }
inline tcu::Format::Enum<int, 2> getPatchParamStr (int value) { return tcu::Format::Enum<int, 2>(getPatchParamName, value); }
inline tcu::Format::Enum<int, 2> getTextureFormatStr (int value) { return tcu::Format::Enum<int, 2>(getTextureFormatName, value); }
+inline tcu::Format::Enum<int, 2> getGraphicsResetStatusStr (int value) { return tcu::Format::Enum<int, 2>(getGraphicsResetStatusName, value); }
inline tcu::Format::Enum<int, 1> getBooleanStr (deUint8 value) { return tcu::Format::Enum<int, 1>(getBooleanName, (int)value); }
gl->framebufferTexture = (glFramebufferTextureFunc) loader->get("glFramebufferTextureEXT");
}
+if (de::contains(extSet, "GL_EXT_robustness"))
+{
+ gl->getGraphicsResetStatus = (glGetGraphicsResetStatusFunc) loader->get("glGetGraphicsResetStatusEXT");
+ gl->getnUniformfv = (glGetnUniformfvFunc) loader->get("glGetnUniformfvEXT");
+ gl->getnUniformiv = (glGetnUniformivFunc) loader->get("glGetnUniformivEXT");
+ gl->readnPixels = (glReadnPixelsFunc) loader->get("glReadnPixelsEXT");
+}
+
if (de::contains(extSet, "GL_EXT_texture_buffer"))
{
gl->texBuffer = (glTexBufferFunc) loader->get("glTexBufferEXT");
XCloseDisplay(m_display);
}
+void XlibDisplay::processEvent (XEvent& event)
+{
+ switch (event.type)
+ {
+ case ClientMessage:
+ if ((unsigned)event.xclient.data.l[0] == m_deleteAtom)
+ m_eventState.setQuitFlag(true);
+ break;
+ // note: ConfigureNotify for window is handled in setDimensions()
+ default:
+ break;
+ }
+}
+
void XlibDisplay::processEvents (void)
{
XEvent event;
while (XPending(m_display))
{
XNextEvent(m_display, &event);
-
- // \todo [2010-10-27 pyry] Handle ConfigureNotify?
- if (event.type == ClientMessage && (unsigned)event.xclient.data.l[0] == m_deleteAtom)
- m_eventState.setQuitFlag(true);
+ processEvent(event);
}
}
do
{
- XNextEvent(dpy, &event);
+ XWindowEvent(dpy, m_window, ExposureMask | StructureNotifyMask, &event);
} while (event.type != eventType);
m_visible = visible;
for(;;)
{
XNextEvent(dpy, &myevent);
- if (myevent.type == ConfigureNotify)
- break;
+ if (myevent.type == ConfigureNotify) {
+ XConfigureEvent e = myevent.xconfigure;
+ if (e.width == width && e.height == height)
+ break;
+ }
+ else
+ m_display.processEvent(myevent);
}
}
::Visual* getVisual (VisualID visualID);
bool getVisualInfo (VisualID visualID, XVisualInfo& dst);
void processEvents (void);
+ void processEvent (XEvent& event);
protected:
::Display* m_display;
tcu::Platform* createPlatform (void)
{
+ // From man:XinitThreads(3):
+ //
+ // The XInitThreads function initializes Xlib support for concurrent
+ // threads. This function must be the first Xlib function
+ // a multi-threaded program calls, and it must complete before any other
+ // Xlib call is made.
+ DE_CHECK_RUNTIME_ERR(XInitThreads() != 0);
+
return new tcu::x11::X11Platform();
}
teglConfigList.hpp
teglCreateContextTests.cpp
teglCreateContextTests.hpp
+ teglGetFrameTimestampsTests.cpp
+ teglGetFrameTimestampsTests.hpp
teglQueryContextTests.cpp
teglQueryContextTests.hpp
teglCreateSurfaceTests.cpp
teglMultiContextTests.cpp
teglThreadCleanUpTests.hpp
teglThreadCleanUpTests.cpp
+ teglRobustnessTests.hpp
+ teglRobustnessTests.cpp
)
set(DEQP_EGL_LIBS
}
}
+ static int getColorComponentTypeRank (EGLenum compType)
+ {
+ switch (compType)
+ {
+ case EGL_COLOR_COMPONENT_TYPE_FIXED_EXT: return 0;
+ case EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT: return 1;
+ default:
+ TCU_THROW(TestError, (std::string("Unknown color component type: ") + eglu::getColorComponentTypeStr(compType).toString()).c_str());
+ }
+ }
+
typedef bool (*CompareFunc) (const SurfaceConfig& a, const SurfaceConfig& b);
static bool compareCaveat (const SurfaceConfig& a, const SurfaceConfig& b)
return getYuvOrderRank((EGLenum)a.m_info.yuvOrder) < getYuvOrderRank((EGLenum)b.m_info.yuvOrder);
}
+ static bool compareColorComponentType (const SurfaceConfig& a, const SurfaceConfig& b)
+ {
+ return getColorComponentTypeRank((EGLenum)a.m_info.colorComponentType) < getColorComponentTypeRank((EGLenum)b.m_info.colorComponentType);
+ }
+
static bool compareColorBufferBits (const SurfaceConfig& a, const SurfaceConfig& b, const tcu::BVec4& specifiedRGBColors, const tcu::BVec2& specifiedLuminanceColors, bool yuvPlaneBppSpecified)
{
DE_ASSERT(a.m_info.colorBufferType == b.m_info.colorBufferType);
{
SurfaceConfig::compareCaveat,
SurfaceConfig::compareColorBufferType,
+ SurfaceConfig::compareColorComponentType,
DE_NULL, // SurfaceConfig::compareColorBufferBits,
SurfaceConfig::compareAttributeSmaller<EGL_BUFFER_SIZE>,
SurfaceConfig::compareAttributeSmaller<EGL_SAMPLE_BUFFERS>,
rules[EGL_YUV_CSC_STANDARD_EXT] = AttribRule(EGL_YUV_CSC_STANDARD_EXT, EGL_DONT_CARE, CRITERIA_EXACT, SORTORDER_NONE);
rules[EGL_YUV_PLANE_BPP_EXT] = AttribRule(EGL_YUV_PLANE_BPP_EXT, EGL_DONT_CARE, CRITERIA_AT_LEAST, SORTORDER_SPECIAL); // 3
+ // EGL_EXT_pixel_format_float
+ rules[EGL_COLOR_COMPONENT_TYPE_EXT] = AttribRule(EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT, CRITERIA_EXACT, SORTORDER_SPECIAL); // 2
+
return rules;
}
private:
#include "eglwEnums.hpp"
#include "deRandom.hpp"
#include "deStringUtil.hpp"
+#include "deUniquePtr.hpp"
+#include "deSTLUtil.hpp"
#include <vector>
#include <algorithm>
int m_iterNdx;
};
+class ColorComponentTypeCase : public ChooseConfigCase
+{
+
+public:
+ ColorComponentTypeCase (EglTestContext& eglTestCtx, const char* name, EGLenum value)
+ : ChooseConfigCase (eglTestCtx, name, "", true /* sorting order is validated */)
+ , m_value (value)
+ {
+ }
+
+ TestCase::IterateResult iterate (void)
+ {
+ m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+
+ {
+ const std::vector<std::string> extensions = eglu::getDisplayExtensions(m_eglTestCtx.getLibrary(), m_display);
+
+ if (!de::contains(extensions.begin(), extensions.end(), "EGL_EXT_pixel_format_float"))
+ TCU_THROW(NotSupportedError, "EGL_EXT_pixel_format_float is not supported");
+ }
+
+ {
+ std::vector<std::pair<EGLenum, EGLint> > attributes;
+
+ attributes.push_back(std::pair<EGLenum, EGLint>(EGL_COLOR_COMPONENT_TYPE_EXT, m_value));
+ fillDontCare(attributes);
+
+ executeTest(attributes, m_checkOrder);
+ }
+
+ return STOP;
+ }
+private:
+ const EGLenum m_value;
+};
+
ChooseConfigTests::ChooseConfigTests (EglTestContext& eglTestCtx)
: TestCaseGroup(eglTestCtx, "choose_config", "eglChooseConfig() tests")
{
};
randomGroup->addChild(new ChooseConfigRandomCase(m_eglTestCtx, "all", "All attributes", toSet(allAttribs)));
}
+
+ // EGL_EXT_pixel_format_float
+ {
+ de::MovePtr<tcu::TestCaseGroup> colorComponentTypeGroup (new tcu::TestCaseGroup(m_testCtx, "color_component_type_ext", "EGL_EXT_pixel_format_float tests"));
+
+ colorComponentTypeGroup->addChild(new ColorComponentTypeCase(m_eglTestCtx, "dont_care", EGL_DONT_CARE));
+ colorComponentTypeGroup->addChild(new ColorComponentTypeCase(m_eglTestCtx, "fixed", EGL_COLOR_COMPONENT_TYPE_FIXED_EXT));
+ colorComponentTypeGroup->addChild(new ColorComponentTypeCase(m_eglTestCtx, "float", EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT));
+
+ addChild(colorComponentTypeGroup.release());
+ }
}
} // egl
#include "teglSimpleConfigCase.hpp"
#include "egluStrUtil.hpp"
#include "egluUtil.hpp"
+#include "egluUnique.hpp"
#include "eglwLibrary.hpp"
#include "eglwEnums.hpp"
#include "tcuTestLog.hpp"
+#include "deSTLUtil.hpp"
namespace deqp
{
using tcu::TestLog;
using namespace eglw;
+static const EGLint s_es1Attrs[] = { EGL_CONTEXT_CLIENT_VERSION, 1, EGL_NONE };
+static const EGLint s_es2Attrs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
+static const EGLint s_es3Attrs[] = { EGL_CONTEXT_MAJOR_VERSION_KHR, 3, EGL_NONE };
+
+static const struct
+{
+ const char* name;
+ EGLenum api;
+ EGLint apiBit;
+ const EGLint* ctxAttrs;
+} s_apis[] =
+{
+ { "OpenGL", EGL_OPENGL_API, EGL_OPENGL_BIT, DE_NULL },
+ { "OpenGL ES 1", EGL_OPENGL_ES_API, EGL_OPENGL_ES_BIT, s_es1Attrs },
+ { "OpenGL ES 2", EGL_OPENGL_ES_API, EGL_OPENGL_ES2_BIT, s_es2Attrs },
+ { "OpenGL ES 3", EGL_OPENGL_ES_API, EGL_OPENGL_ES3_BIT_KHR, s_es3Attrs },
+ { "OpenVG", EGL_OPENVG_API, EGL_OPENVG_BIT, DE_NULL }
+};
+
class CreateContextCase : public SimpleConfigCase
{
public:
EGLint id = eglu::getConfigAttribInt(egl, display, config, EGL_CONFIG_ID);
EGLint apiBits = eglu::getConfigAttribInt(egl, display, config, EGL_RENDERABLE_TYPE);
- static const EGLint es1Attrs[] = { EGL_CONTEXT_CLIENT_VERSION, 1, EGL_NONE };
- static const EGLint es2Attrs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
- static const EGLint es3Attrs[] = { EGL_CONTEXT_MAJOR_VERSION_KHR, 3, EGL_NONE };
-
- static const struct
+ for (int apiNdx = 0; apiNdx < (int)DE_LENGTH_OF_ARRAY(s_apis); apiNdx++)
{
- const char* name;
- EGLenum api;
- EGLint apiBit;
- const EGLint* ctxAttrs;
- } apis[] =
- {
- { "OpenGL", EGL_OPENGL_API, EGL_OPENGL_BIT, DE_NULL },
- { "OpenGL ES 1", EGL_OPENGL_ES_API, EGL_OPENGL_ES_BIT, es1Attrs },
- { "OpenGL ES 2", EGL_OPENGL_ES_API, EGL_OPENGL_ES2_BIT, es2Attrs },
- { "OpenGL ES 3", EGL_OPENGL_ES_API, EGL_OPENGL_ES3_BIT_KHR, es3Attrs },
- { "OpenVG", EGL_OPENVG_API, EGL_OPENVG_BIT, DE_NULL }
- };
-
- for (int apiNdx = 0; apiNdx < (int)DE_LENGTH_OF_ARRAY(apis); apiNdx++)
- {
- if ((apiBits & apis[apiNdx].apiBit) == 0)
+ if ((apiBits & s_apis[apiNdx].apiBit) == 0)
continue; // Not supported API
- log << TestLog::Message << "Creating " << apis[apiNdx].name << " context with config ID " << id << TestLog::EndMessage;
+ log << TestLog::Message << "Creating " << s_apis[apiNdx].name << " context with config ID " << id << TestLog::EndMessage;
EGLU_CHECK_MSG(egl, "init");
- EGLU_CHECK_CALL(egl, bindAPI(apis[apiNdx].api));
+ EGLU_CHECK_CALL(egl, bindAPI(s_apis[apiNdx].api));
- EGLContext context = egl.createContext(display, config, EGL_NO_CONTEXT, apis[apiNdx].ctxAttrs);
+ EGLContext context = egl.createContext(display, config, EGL_NO_CONTEXT, s_apis[apiNdx].ctxAttrs);
EGLenum err = egl.getError();
if (context == EGL_NO_CONTEXT || err != EGL_SUCCESS)
}
}
+class CreateContextNoConfigCase : public TestCase
+{
+public:
+ CreateContextNoConfigCase (EglTestContext& eglTestCtx)
+ : TestCase(eglTestCtx, "no_config", "EGL_KHR_no_config_context")
+ {
+ }
+
+ IterateResult iterate (void)
+ {
+ const eglw::Library& egl = m_eglTestCtx.getLibrary();
+ const eglu::UniqueDisplay display (egl, eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay(), DE_NULL));
+ tcu::TestLog& log = m_testCtx.getLog();
+
+ if (!eglu::hasExtension(egl, *display, "EGL_KHR_no_config_context"))
+ TCU_THROW(NotSupportedError, "EGL_KHR_no_config_context is not supported");
+
+ m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "pass");
+
+ for (int apiNdx = 0; apiNdx < (int)DE_LENGTH_OF_ARRAY(s_apis); apiNdx++)
+ {
+ const EGLenum api = s_apis[apiNdx].api;
+
+ if (egl.bindAPI(api) == EGL_FALSE)
+ {
+ TCU_CHECK(egl.getError() == EGL_BAD_PARAMETER);
+ log << TestLog::Message << "eglBindAPI(" << eglu::getAPIStr(api) << ") failed, skipping" << TestLog::EndMessage;
+ continue;
+ }
+
+ log << TestLog::Message << "Creating " << s_apis[apiNdx].name << " context" << TestLog::EndMessage;
+
+ const EGLContext context = egl.createContext(*display, (EGLConfig)0, EGL_NO_CONTEXT, s_apis[apiNdx].ctxAttrs);
+ const EGLenum err = egl.getError();
+
+ if (context == EGL_NO_CONTEXT || err != EGL_SUCCESS)
+ {
+ log << TestLog::Message << " Fail, context: " << tcu::toHex(context) << ", error: " << eglu::getErrorName(err) << TestLog::EndMessage;
+ m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to create context");
+ }
+ else
+ {
+ // Destroy
+ EGLU_CHECK_CALL(egl, destroyContext(*display, context));
+ log << TestLog::Message << " Pass" << TestLog::EndMessage;
+ }
+ }
+
+ return STOP;
+ }
+};
CreateContextTests::CreateContextTests (EglTestContext& eglTestCtx)
: TestCaseGroup(eglTestCtx, "create_context", "Basic eglCreateContext() tests")
for (vector<NamedFilterList>::iterator i = filterLists.begin(); i != filterLists.end(); i++)
addChild(new CreateContextCase(m_eglTestCtx, i->getName(), i->getDescription(), *i));
+
+ addChild(new CreateContextNoConfigCase(m_eglTestCtx));
}
} // egl
--- /dev/null
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program EGL Module
+ * ---------------------------------------
+ *
+ * Copyright 2017 The Android Open Source Project
+ *
+ * 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.
+ *
+ *//*!
+ * \file
+ * \brief Test the EGL_ANDROID_get_frame_timestamps extension.
+ *//*--------------------------------------------------------------------*/
+
+#include "teglGetFrameTimestampsTests.hpp"
+
+#include "teglSimpleConfigCase.hpp"
+
+#include "egluNativeWindow.hpp"
+#include "egluUtil.hpp"
+#include "egluUnique.hpp"
+#include "eglwLibrary.hpp"
+#include "eglwEnums.hpp"
+
+#include "gluDefs.hpp"
+#include "glwEnums.hpp"
+#include "glwFunctions.hpp"
+
+#include "tcuResultCollector.hpp"
+#include "tcuTestLog.hpp"
+#include "tcuSurface.hpp"
+#include "tcuTexture.hpp"
+#include "tcuTextureUtil.hpp"
+#include "tcuImageCompare.hpp"
+#include "tcuVector.hpp"
+#include "tcuVectorUtil.hpp"
+
+#include "deClock.h"
+#include "deMath.h"
+#include "deUniquePtr.hpp"
+#include "deThread.hpp"
+
+#include <algorithm>
+#include <string>
+#include <vector>
+#include <sstream>
+
+// Tentative EGL header definitions for EGL_ANDROID_get_Frame_timestamps.
+// \todo [2017-01-25 brianderson] Remove once defined in the official headers.
+#define EGL_TIMESTAMPS_ANDROID 0x314D
+#define EGL_COMPOSITE_DEADLINE_ANDROID 0x314E
+#define EGL_COMPOSITE_INTERVAL_ANDROID 0x314F
+#define EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID 0x3150
+#define EGL_REQUESTED_PRESENT_TIME_ANDROID 0x3151
+#define EGL_RENDERING_COMPLETE_TIME_ANDROID 0x3152
+#define EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3153
+#define EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3154
+#define EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3155
+#define EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID 0x3156
+#define EGL_DISPLAY_PRESENT_TIME_ANDROID 0x3157
+#define EGL_DEQUEUE_READY_TIME_ANDROID 0x3158
+#define EGL_READS_DONE_TIME_ANDROID 0x3159
+typedef deInt64 EGLnsecsANDROID;
+typedef deUint64 EGLuint64KHR;
+typedef EGLW_APICALL eglw::EGLBoolean (EGLW_APIENTRY* eglGetNextFrameIdANDROIDFunc) (eglw::EGLDisplay dpy, eglw::EGLSurface surface, EGLuint64KHR *frameId);
+typedef EGLW_APICALL eglw::EGLBoolean (EGLW_APIENTRY* eglGetCompositorTimingANDROIDFunc) (eglw::EGLDisplay dpy, eglw::EGLSurface surface, eglw::EGLint numTimestamps, const eglw::EGLint *names, EGLnsecsANDROID *values);
+typedef EGLW_APICALL eglw::EGLBoolean (EGLW_APIENTRY* eglGetCompositorTimingSupportedANDROIDFunc) (eglw::EGLDisplay dpy, eglw::EGLSurface surface, eglw::EGLint name);
+typedef EGLW_APICALL eglw::EGLBoolean (EGLW_APIENTRY* eglGetFrameTimestampsANDROIDFunc) (eglw::EGLDisplay dpy, eglw::EGLSurface surface, EGLuint64KHR frameId, eglw::EGLint numTimestamps, const eglw::EGLint *timestamps, EGLnsecsANDROID *values);
+typedef EGLW_APICALL eglw::EGLBoolean (EGLW_APIENTRY* eglGetFrameTimestampSupportedANDROIDFunc) (eglw::EGLDisplay dpy, eglw::EGLSurface surface, eglw::EGLint timestamp);
+
+#define CHECK_NAKED_EGL_CALL(EGLW, CALL) do { CALL; eglu::checkError((EGLW).getError(), #CALL, __FILE__, __LINE__); } while (deGetFalse())
+
+namespace deqp
+{
+namespace egl
+{
+
+using tcu::TestLog;
+using std::string;
+using std::vector;
+using namespace eglw;
+
+namespace
+{
+
+// Careful: This has microsecond precision, which can cause timestamps to
+// appear non monotonic when compared to the nanosecond precision timestamps
+// we get from the eglGetFrameTimestamps extension.
+// Current test expectations only make sure microsecond precision timestamps
+// are less than the nanosecond precision timestamps, so this is okay.
+EGLnsecsANDROID getNanoseconds (void)
+{
+ return deGetMicroseconds() * 1000;
+}
+
+struct FrameTimes
+{
+ FrameTimes (void)
+ : frameId (-1)
+ , swapBufferBeginNs (-1)
+ , compositeDeadline (-1)
+ , compositeInterval (-1)
+ , compositeToPresentLatency (-1)
+ , requestedPresent (-1)
+ , latch (-1)
+ , firstCompositionStart (-1)
+ , lastCompositionStart (-1)
+ , dequeueReady (-1)
+ , renderingComplete (-1)
+ , firstCompositionGpuFinished (-1)
+ , displayPresent (-1)
+ , readsDone (-1)
+ {
+ }
+
+ EGLuint64KHR frameId;
+
+ // Timestamps sampled by the test.
+ EGLnsecsANDROID swapBufferBeginNs;
+
+ // Compositor info.
+ EGLnsecsANDROID compositeDeadline;
+ EGLnsecsANDROID compositeInterval;
+ EGLnsecsANDROID compositeToPresentLatency;
+
+ // CPU Timeline.
+ EGLnsecsANDROID requestedPresent;
+ EGLnsecsANDROID latch;
+ EGLnsecsANDROID firstCompositionStart;
+ EGLnsecsANDROID lastCompositionStart;
+ EGLnsecsANDROID dequeueReady;
+
+ // GPU Timeline.
+ EGLnsecsANDROID renderingComplete;
+ EGLnsecsANDROID firstCompositionGpuFinished;
+ EGLnsecsANDROID displayPresent;
+ EGLnsecsANDROID readsDone;
+};
+
+bool timestampExists (EGLnsecsANDROID timestamp)
+{
+ return timestamp > 0;
+}
+
+void verifySingleFrame (const FrameTimes& frameTimes, tcu::ResultCollector& result, bool verifyReadsDone)
+{
+ // Verify CPU timeline is monotonic.
+ result.check(frameTimes.swapBufferBeginNs < frameTimes.latch, "Buffer latched before it was swapped.");
+ result.check(frameTimes.latch < frameTimes.firstCompositionStart, "Buffer composited before it was latched.");
+ result.check(frameTimes.firstCompositionStart <= frameTimes.lastCompositionStart, "First composition start after last composition start.");
+ result.check(frameTimes.lastCompositionStart < frameTimes.dequeueReady, "Buffer composited after it was ready to be dequeued.");
+
+ // Verify GPU timeline is monotonic.
+ if (timestampExists(frameTimes.firstCompositionGpuFinished))
+ result.check(frameTimes.renderingComplete < frameTimes.firstCompositionGpuFinished, "Buffer rendering completed after compositor GPU work finished.");
+
+ if (timestampExists(frameTimes.displayPresent))
+ result.check(frameTimes.renderingComplete < frameTimes.displayPresent, "Buffer displayed before rendering completed.");
+
+ if (timestampExists(frameTimes.firstCompositionGpuFinished) && timestampExists(frameTimes.displayPresent))
+ result.check(frameTimes.firstCompositionGpuFinished < frameTimes.displayPresent, "Buffer displayed before compositor GPU work completed");
+
+ // Drivers may maintain shadow copies of the buffer, so the readsDone time
+ // of the real buffer may be earlier than apparent dependencies. We can only
+ // be sure that the readsDone time must be after the renderingComplete time.
+ if (verifyReadsDone)
+ result.check(frameTimes.renderingComplete < frameTimes.readsDone, "Buffer rendering completed after reads completed.");
+
+ // Verify CPU/GPU dependencies
+ result.check(frameTimes.renderingComplete < frameTimes.latch, "Buffer latched before rendering completed.");
+ if (timestampExists(frameTimes.firstCompositionGpuFinished))
+ result.check(frameTimes.firstCompositionStart < frameTimes.firstCompositionGpuFinished, "Composition CPU work started after GPU work finished.");
+
+ if (timestampExists(frameTimes.displayPresent))
+ result.check(frameTimes.firstCompositionStart < frameTimes.displayPresent, "Buffer displayed before it was composited.");
+}
+
+void verifyNeighboringFrames (const FrameTimes& frame1, const FrameTimes& frame2, tcu::ResultCollector& result, bool verifyReadsDone)
+{
+ // CPU timeline.
+ result.check(frame1.swapBufferBeginNs < frame2.swapBufferBeginNs, "Swap begin times not monotonic.");
+ result.check(frame1.latch < frame2.latch, "Latch times not monotonic.");
+ result.check(frame1.lastCompositionStart < frame2.latch, "Old buffer composited after new buffer latched.");
+ result.check(frame1.lastCompositionStart < frame2.firstCompositionStart, "Composition times overlap.");
+ result.check(frame1.dequeueReady < frame2.dequeueReady, "Dequeue ready times not monotonic.");
+
+ // GPU timeline.
+ result.check(frame1.renderingComplete < frame2.renderingComplete, "Rendering complete times not monotonic.");
+
+ if (timestampExists(frame1.firstCompositionGpuFinished) && timestampExists(frame2.firstCompositionGpuFinished))
+ result.check(frame1.firstCompositionGpuFinished < frame2.firstCompositionGpuFinished, "Composition GPU work complete times not monotonic.");
+
+ if (timestampExists(frame1.displayPresent) && timestampExists(frame2.displayPresent))
+ result.check(frame1.displayPresent < frame2.displayPresent, "Display present times not monotonic.");
+
+ if (verifyReadsDone && timestampExists(frame1.readsDone) && timestampExists(frame2.readsDone))
+ result.check(frame1.readsDone < frame2.readsDone, "Reads done times not monotonic.");
+}
+
+EGLContext createGLES2Context (const Library& egl, EGLDisplay display, EGLConfig config)
+{
+ EGLContext context = EGL_NO_CONTEXT;
+ const EGLint attribList[] =
+ {
+ EGL_CONTEXT_CLIENT_VERSION, 2,
+ EGL_NONE
+ };
+
+ EGLU_CHECK_CALL(egl, bindAPI(EGL_OPENGL_ES_API));
+
+ context = egl.createContext(display, config, EGL_NO_CONTEXT, attribList);
+ EGLU_CHECK_MSG(egl, "eglCreateContext() failed");
+ TCU_CHECK(context);
+
+ return context;
+}
+
+class GetFrameTimestampTest : public SimpleConfigCase
+{
+public:
+ GetFrameTimestampTest (EglTestContext& eglTestCtx, const NamedFilterList& filters);
+ ~GetFrameTimestampTest (void);
+
+private:
+ void executeForConfig (EGLDisplay display, EGLConfig config);
+ void initializeExtension (const Library& egl);
+
+ // Not allowed
+ GetFrameTimestampTest (const GetFrameTimestampTest&);
+ GetFrameTimestampTest& operator= (const GetFrameTimestampTest&);
+
+ // TODO: Move these to eglw::Library.
+ eglGetNextFrameIdANDROIDFunc m_eglGetNextFrameIdANDROID;
+ eglGetCompositorTimingANDROIDFunc m_eglGetCompositorTimingANDROID;
+ eglGetCompositorTimingSupportedANDROIDFunc m_eglGetCompositorTimingSupportedANDROID;
+ eglGetFrameTimestampsANDROIDFunc m_eglGetFrameTimestampsANDROID;
+ eglGetFrameTimestampSupportedANDROIDFunc m_eglGetFrameTimestampSupportedANDROID;
+
+ tcu::ResultCollector m_result;
+};
+
+GetFrameTimestampTest::GetFrameTimestampTest (EglTestContext& eglTestCtx, const NamedFilterList& filters)
+ : SimpleConfigCase (eglTestCtx, filters.getName(), filters.getDescription(), filters)
+ , m_eglGetNextFrameIdANDROID (DE_NULL)
+ , m_eglGetCompositorTimingANDROID (DE_NULL)
+ , m_eglGetCompositorTimingSupportedANDROID (DE_NULL)
+ , m_eglGetFrameTimestampsANDROID (DE_NULL)
+ , m_eglGetFrameTimestampSupportedANDROID (DE_NULL)
+ , m_result (m_testCtx.getLog())
+{
+}
+
+GetFrameTimestampTest::~GetFrameTimestampTest (void)
+{
+}
+
+void GetFrameTimestampTest::initializeExtension (const Library& egl)
+{
+ m_eglGetNextFrameIdANDROID = reinterpret_cast<eglGetNextFrameIdANDROIDFunc>(egl.getProcAddress("eglGetNextFrameIdANDROID"));
+ EGLU_CHECK_MSG(egl, "getProcAddress of eglGetNextFrameIdANDROID failed.");
+ m_eglGetCompositorTimingANDROID = reinterpret_cast<eglGetCompositorTimingANDROIDFunc>(egl.getProcAddress("eglGetCompositorTimingANDROID"));
+ EGLU_CHECK_MSG(egl, "getProcAddress of eglGetCompositorTimingANDROID failed.");
+ m_eglGetCompositorTimingSupportedANDROID = reinterpret_cast<eglGetCompositorTimingSupportedANDROIDFunc>(egl.getProcAddress("eglGetCompositorTimingSupportedANDROID"));
+ EGLU_CHECK_MSG(egl, "getProcAddress of eglGetCompositorTimingSupportedANDROID failed.");
+ m_eglGetFrameTimestampsANDROID = reinterpret_cast<eglGetFrameTimestampsANDROIDFunc>(egl.getProcAddress("eglGetFrameTimestampsANDROID"));
+ EGLU_CHECK_MSG(egl, "getProcAddress of eglGetFrameTimestampsANDROID failed.");
+ m_eglGetFrameTimestampSupportedANDROID = reinterpret_cast<eglGetFrameTimestampSupportedANDROIDFunc>(egl.getProcAddress("eglGetFrameTimestampSupportedANDROID"));
+ EGLU_CHECK_MSG(egl, "getProcAddress of eglGetFrameTimestampSupportedANDROID failed.");
+}
+
+
+string getConfigIdString (const Library& egl, EGLDisplay display, EGLConfig config)
+{
+ std::ostringstream stream;
+ EGLint id;
+
+ EGLU_CHECK_CALL(egl, getConfigAttrib(display, config , EGL_CONFIG_ID, &id));
+
+ stream << id;
+
+ return stream.str();
+}
+
+deUint32 createGLES2Program (const glw::Functions& gl, TestLog& log)
+{
+ const char* const vertexShaderSource =
+ "attribute highp vec2 a_pos;\n"
+ "void main (void)\n"
+ "{\n"
+ "\tgl_Position = vec4(a_pos, 0.0, 1.0);\n"
+ "}";
+
+ const char* const fragmentShaderSource =
+ "void main (void)\n"
+ "{\n"
+ "\tgl_FragColor = vec4(0.9, 0.1, 0.4, 1.0);\n"
+ "}";
+
+ deUint32 program = 0;
+ deUint32 vertexShader = 0;
+ deUint32 fragmentShader = 0;
+
+ deInt32 vertexCompileStatus;
+ string vertexInfoLog;
+ deInt32 fragmentCompileStatus;
+ string fragmentInfoLog;
+ deInt32 linkStatus;
+ string programInfoLog;
+
+ try
+ {
+ program = gl.createProgram();
+ vertexShader = gl.createShader(GL_VERTEX_SHADER);
+ fragmentShader = gl.createShader(GL_FRAGMENT_SHADER);
+
+ GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create shaders and program");
+
+ gl.shaderSource(vertexShader, 1, &vertexShaderSource, DE_NULL);
+ gl.compileShader(vertexShader);
+ GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup vertex shader");
+
+ gl.shaderSource(fragmentShader, 1, &fragmentShaderSource, DE_NULL);
+ gl.compileShader(fragmentShader);
+ GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup fragment shader");
+
+ {
+ deInt32 infoLogLength = 0;
+
+ gl.getShaderiv(vertexShader, GL_COMPILE_STATUS, &vertexCompileStatus);
+ gl.getShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &infoLogLength);
+
+ vertexInfoLog.resize(infoLogLength, '\0');
+
+ gl.getShaderInfoLog(vertexShader, (glw::GLsizei)vertexInfoLog.length(), &infoLogLength, &(vertexInfoLog[0]));
+ GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to get vertex shader compile info");
+
+ vertexInfoLog.resize(infoLogLength);
+ }
+
+ {
+ deInt32 infoLogLength = 0;
+
+ gl.getShaderiv(fragmentShader, GL_COMPILE_STATUS, &fragmentCompileStatus);
+ gl.getShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &infoLogLength);
+
+ fragmentInfoLog.resize(infoLogLength, '\0');
+
+ gl.getShaderInfoLog(fragmentShader, (glw::GLsizei)fragmentInfoLog.length(), &infoLogLength, &(fragmentInfoLog[0]));
+ GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to get fragment shader compile info");
+
+ fragmentInfoLog.resize(infoLogLength);
+ }
+
+ gl.attachShader(program, vertexShader);
+ gl.attachShader(program, fragmentShader);
+ gl.linkProgram(program);
+ GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup program");
+
+ {
+ deInt32 infoLogLength = 0;
+
+ gl.getProgramiv(program, GL_LINK_STATUS, &linkStatus);
+ gl.getProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
+
+ programInfoLog.resize(infoLogLength, '\0');
+
+ gl.getProgramInfoLog(program, (glw::GLsizei)programInfoLog.length(), &infoLogLength, &(programInfoLog[0]));
+ GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to get program link info");
+
+ programInfoLog.resize(infoLogLength);
+ }
+
+ if (linkStatus == 0 || vertexCompileStatus == 0 || fragmentCompileStatus == 0)
+ {
+
+ log.startShaderProgram(linkStatus != 0, programInfoLog.c_str());
+
+ log << TestLog::Shader(QP_SHADER_TYPE_VERTEX, vertexShaderSource, vertexCompileStatus != 0, vertexInfoLog);
+ log << TestLog::Shader(QP_SHADER_TYPE_FRAGMENT, fragmentShaderSource, fragmentCompileStatus != 0, fragmentInfoLog);
+
+ log.endShaderProgram();
+ }
+
+ gl.deleteShader(vertexShader);
+ gl.deleteShader(fragmentShader);
+ GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to delete shaders");
+
+ TCU_CHECK(linkStatus != 0 && vertexCompileStatus != 0 && fragmentCompileStatus != 0);
+ }
+ catch (...)
+ {
+ if (program)
+ gl.deleteProgram(program);
+
+ if (vertexShader)
+ gl.deleteShader(vertexShader);
+
+ if (fragmentShader)
+ gl.deleteShader(fragmentShader);
+
+ throw;
+ }
+
+ return program;
+}
+
+void GetFrameTimestampTest::executeForConfig (EGLDisplay display, EGLConfig config)
+{
+ const Library& egl = m_eglTestCtx.getLibrary();
+
+ if (!eglu::hasExtension(egl, display, "EGL_ANDROID_get_frame_timestamps"))
+ TCU_THROW(NotSupportedError, "EGL_ANDROID_get_frame_timestamps is not supported");
+
+ initializeExtension(egl);
+
+ const string configIdStr (getConfigIdString(egl, display, config));
+ tcu::ScopedLogSection logSection (m_testCtx.getLog(), ("Config ID " + configIdStr).c_str(), ("Config ID " + configIdStr).c_str());
+ const eglu::NativeWindowFactory& factory = eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
+
+ {
+ TestLog& log = m_testCtx.getLog();
+
+ log << TestLog::Message << "EGL_RED_SIZE: " << eglu::getConfigAttribInt(egl, display, config, EGL_RED_SIZE) << TestLog::EndMessage;
+ log << TestLog::Message << "EGL_GREEN_SIZE: " << eglu::getConfigAttribInt(egl, display, config, EGL_GREEN_SIZE) << TestLog::EndMessage;
+ log << TestLog::Message << "EGL_BLUE_SIZE: " << eglu::getConfigAttribInt(egl, display, config, EGL_BLUE_SIZE) << TestLog::EndMessage;
+ log << TestLog::Message << "EGL_ALPHA_SIZE: " << eglu::getConfigAttribInt(egl, display, config, EGL_ALPHA_SIZE) << TestLog::EndMessage;
+ log << TestLog::Message << "EGL_DEPTH_SIZE: " << eglu::getConfigAttribInt(egl, display, config, EGL_DEPTH_SIZE) << TestLog::EndMessage;
+ log << TestLog::Message << "EGL_STENCIL_SIZE: " << eglu::getConfigAttribInt(egl, display, config, EGL_STENCIL_SIZE) << TestLog::EndMessage;
+ log << TestLog::Message << "EGL_SAMPLES: " << eglu::getConfigAttribInt(egl, display, config, EGL_SAMPLES) << TestLog::EndMessage;
+ }
+
+ de::UniquePtr<eglu::NativeWindow> window (factory.createWindow(&m_eglTestCtx.getNativeDisplay(), display, config, DE_NULL, eglu::WindowParams(128, 128, eglu::WindowParams::VISIBILITY_VISIBLE)));
+
+ eglu::UniqueSurface surface (egl, display, eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *window, display, config, DE_NULL));
+ eglu::UniqueContext context (egl, display, createGLES2Context(egl, display, config));
+ glw::Functions gl;
+ deUint32 program = 0;
+
+ EGLU_CHECK_CALL(egl, surfaceAttrib(display, *surface, EGL_TIMESTAMPS_ANDROID, EGL_TRUE));
+
+ m_eglTestCtx.initGLFunctions(&gl, glu::ApiType::es(2,0));
+
+ EGLU_CHECK_CALL(egl, makeCurrent(display, *surface, *surface, *context));
+
+ try
+ {
+ const eglw::EGLint frameTimestampNames[] =
+ {
+ EGL_REQUESTED_PRESENT_TIME_ANDROID,
+ EGL_RENDERING_COMPLETE_TIME_ANDROID,
+ EGL_COMPOSITION_LATCH_TIME_ANDROID,
+ EGL_FIRST_COMPOSITION_START_TIME_ANDROID,
+ EGL_LAST_COMPOSITION_START_TIME_ANDROID,
+ EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID,
+ EGL_DISPLAY_PRESENT_TIME_ANDROID,
+ EGL_DEQUEUE_READY_TIME_ANDROID,
+ EGL_READS_DONE_TIME_ANDROID,
+ };
+ const size_t frameTimestampCount = DE_LENGTH_OF_ARRAY(frameTimestampNames);
+
+ const eglw::EGLint invalidTimestampName = EGL_READS_DONE_TIME_ANDROID + 1;
+
+ // Verify required timestamps are supported.
+ for (size_t i = 0; i < frameTimestampCount; i++)
+ {
+ const bool supported = m_eglGetFrameTimestampSupportedANDROID(display, *surface, frameTimestampNames[i]) != EGL_FALSE;
+ EGLU_CHECK_MSG(egl, "eglGetFrameTimestampSupportedANDROID failed.");
+ TCU_CHECK_MSG(supported, "Required timestamp not supported.");
+ }
+
+ // Verify unsupported timestamps are reported properly.
+ const bool invalidSupported = m_eglGetFrameTimestampSupportedANDROID(display, *surface, invalidTimestampName) != EGL_FALSE;
+ EGLU_CHECK_MSG(egl, "eglGetFrameTimestampSupportedANDROID failed.");
+ TCU_CHECK_MSG(!invalidSupported, "Non existant timestamp reports that it is supported.");
+
+ // Verify compositor timings are supported.
+ const bool deadlineSupported = m_eglGetCompositorTimingSupportedANDROID(display, *surface, EGL_COMPOSITE_DEADLINE_ANDROID) != EGL_FALSE;
+ EGLU_CHECK_MSG(egl, "eglGetCompositorTimingSupportedANDROID failed.");
+ TCU_CHECK_MSG(deadlineSupported, "EGL_COMPOSITE_DEADLINE_ANDROID not supported.");
+ const bool intervalSupported = m_eglGetCompositorTimingSupportedANDROID(display, *surface, EGL_COMPOSITE_INTERVAL_ANDROID) != EGL_FALSE;
+ EGLU_CHECK_MSG(egl, "eglGetCompositorTimingSupportedANDROID failed.");
+ TCU_CHECK_MSG(intervalSupported, "EGL_COMPOSITE_INTERVAL_ANDROID not supported.");
+ const bool latencySupported = m_eglGetCompositorTimingSupportedANDROID(display, *surface, EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID) != EGL_FALSE;
+ EGLU_CHECK_MSG(egl, "eglGetCompositorTimingSupportedANDROID failed.");
+ TCU_CHECK_MSG(latencySupported, "EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID not supported.");
+
+ const float positions1[] =
+ {
+ 0.00f, 0.00f,
+ 0.75f, 0.00f,
+ 0.75f, 0.75f,
+
+ 0.75f, 0.75f,
+ 0.00f, 0.75f,
+ 0.00f, 0.00f
+ };
+
+ const float positions2[] =
+ {
+ -0.75f, -0.75f,
+ 0.00f, -0.75f,
+ 0.00f, 0.00f,
+
+ 0.00f, 0.00f,
+ -0.75f, 0.00f,
+ -0.75f, -0.75f
+ };
+
+ deUint32 posLocation;
+
+ program = createGLES2Program(gl, m_testCtx.getLog());
+
+ gl.useProgram(program);
+ posLocation = gl.getAttribLocation(program, "a_pos");
+ gl.enableVertexAttribArray(posLocation);
+ GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup shader program for rendering");
+
+ const size_t frameCount = 120;
+ std::vector<FrameTimes> frameTimes(frameCount);
+ for (size_t i = 0; i < frameCount; i++)
+ {
+ FrameTimes& frame = frameTimes[i];
+
+ const eglw::EGLint compositorTimingNames[] =
+ {
+ EGL_COMPOSITE_DEADLINE_ANDROID,
+ EGL_COMPOSITE_INTERVAL_ANDROID,
+ EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID,
+ };
+ const EGLint compositorTimingCount = DE_LENGTH_OF_ARRAY(compositorTimingNames);
+ EGLnsecsANDROID compositorTimingValues[compositorTimingCount] = { -2 };
+
+ // Get the current time before making any API calls in case "now"
+ // just happens to get sampled near one of the composite deadlines.
+ EGLnsecsANDROID now = getNanoseconds();
+
+ // Get the frame id.
+ EGLuint64KHR nextFrameId = 0;
+ CHECK_NAKED_EGL_CALL(egl, m_eglGetNextFrameIdANDROID(display, *surface, &nextFrameId));
+ frame.frameId = nextFrameId;
+
+ // Get the compositor timing.
+ CHECK_NAKED_EGL_CALL(egl, m_eglGetCompositorTimingANDROID(
+ display, *surface, compositorTimingCount,
+ compositorTimingNames, compositorTimingValues));
+ frame.compositeDeadline = compositorTimingValues[0];
+ frame.compositeInterval = compositorTimingValues[1];
+ frame.compositeToPresentLatency = compositorTimingValues[2];
+
+ // Verify compositor timing is sane.
+ m_result.check(1000000 < frame.compositeInterval, "Reported refresh rate greater than 1kHz.");
+ m_result.check(frame.compositeInterval < 1000000000, "Reported refresh rate less than 1Hz.");
+ m_result.check(0 < frame.compositeToPresentLatency, "Composite to present latency must be greater than 0.");
+ m_result.check(frame.compositeToPresentLatency < frame.compositeInterval * 3, "Composite to present latency is more than 3 vsyncs.");
+ const EGLnsecsANDROID minDeadline = now;
+ m_result.check(minDeadline < frame.compositeDeadline, "Next composite deadline is in the past.");
+ const EGLnsecsANDROID maxDeadline = now + frame.compositeInterval * 2;
+ m_result.check(frame.compositeDeadline < maxDeadline, "Next composite deadline over two intervals away.");
+
+ const float colorAngle = (static_cast<float>(i) / static_cast<float>(frameCount)) * 6.28318f;
+ gl.clearColor((1.0f + deFloatSin(colorAngle)) / 2.0f, 0.7f, (1.0f + deFloatCos(colorAngle)) / 2.0f, 1.0f);
+ gl.clear(GL_COLOR_BUFFER_BIT);
+ GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to clear surface");
+
+ const bool posSelect = ((i % 2) == 0);
+ gl.vertexAttribPointer(posLocation, 2, GL_FLOAT, GL_FALSE, 0, posSelect ? positions1 : positions2);
+ gl.drawArrays(GL_TRIANGLES, 0, 6);
+ GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to render");
+
+ frame.swapBufferBeginNs = getNanoseconds();
+ EGLU_CHECK_CALL(egl, swapBuffers(display, *surface));
+
+ // All timestamps from 5 frames ago should definitely be available.
+ const size_t frameDelay = 5;
+ if (i >= frameDelay)
+ {
+ FrameTimes& frame5ago = frameTimes[i-frameDelay];
+ EGLnsecsANDROID frameTimestampValues[frameTimestampCount] = { 0 };
+ // \todo [2017-01-25 brianderson] Remove this work around once reads done is fixed.
+ const bool verifyReadsDone = i > (frameDelay + 3);
+
+ CHECK_NAKED_EGL_CALL(egl, m_eglGetFrameTimestampsANDROID(
+ display, *surface, frame5ago.frameId, frameTimestampCount,
+ frameTimestampNames, frameTimestampValues));
+
+ frame5ago.requestedPresent = frameTimestampValues[0];
+ frame5ago.renderingComplete = frameTimestampValues[1];
+ frame5ago.latch = frameTimestampValues[2];
+ frame5ago.firstCompositionStart = frameTimestampValues[3];
+ frame5ago.lastCompositionStart = frameTimestampValues[4];
+ frame5ago.firstCompositionGpuFinished = frameTimestampValues[5];
+ frame5ago.displayPresent = frameTimestampValues[6];
+ frame5ago.dequeueReady = frameTimestampValues[7];
+ frame5ago.readsDone = frameTimestampValues[8];
+
+ verifySingleFrame(frame5ago, m_result, verifyReadsDone);
+ if (i >= frameDelay + 1)
+ {
+ FrameTimes& frame6ago = frameTimes[i-frameDelay-1];
+ verifyNeighboringFrames(frame6ago, frame5ago, m_result, verifyReadsDone);
+ }
+ }
+ }
+
+ // All timestamps for the most recently swapped frame should
+ // become available by only polling eglGetFrametimestamps.
+ // No additional swaps should be necessary.
+ FrameTimes& lastFrame = frameTimes.back();
+ const EGLnsecsANDROID pollingDeadline = lastFrame.swapBufferBeginNs + 1000000000;
+ bool finalTimestampAvaiable = false;
+
+ do
+ {
+ EGLnsecsANDROID frameTimestampValues[frameTimestampCount] = { 0 };
+ CHECK_NAKED_EGL_CALL(egl, m_eglGetFrameTimestampsANDROID(
+ display, *surface, lastFrame.frameId, frameTimestampCount,
+ frameTimestampNames, frameTimestampValues));
+
+ lastFrame.requestedPresent = frameTimestampValues[0];
+ lastFrame.renderingComplete = frameTimestampValues[1];
+ lastFrame.latch = frameTimestampValues[2];
+ lastFrame.firstCompositionStart = frameTimestampValues[3];
+ lastFrame.lastCompositionStart = frameTimestampValues[4];
+ lastFrame.firstCompositionGpuFinished = frameTimestampValues[5];
+ lastFrame.displayPresent = frameTimestampValues[6];
+ lastFrame.dequeueReady = frameTimestampValues[7];
+ lastFrame.readsDone = frameTimestampValues[8];
+
+ if (timestampExists(lastFrame.displayPresent))
+ finalTimestampAvaiable = true;
+
+ if (getNanoseconds() > pollingDeadline)
+ break;
+ } while (!finalTimestampAvaiable);
+
+ m_result.check(finalTimestampAvaiable, "Timed out polling for timestamps of last swap.");
+ m_result.check(timestampExists(lastFrame.requestedPresent), "Rendering complete of last swap not avaiable.");
+ m_result.check(timestampExists(lastFrame.renderingComplete), "Rendering complete of last swap not avaiable.");
+ m_result.check(timestampExists(lastFrame.latch), "Latch of last swap not avaiable.");
+ m_result.check(timestampExists(lastFrame.firstCompositionStart), "First composite time of last swap not avaiable.");
+ m_result.check(timestampExists(lastFrame.lastCompositionStart), "Last composite time of last swap not avaiable.");
+
+ window->processEvents();
+ gl.disableVertexAttribArray(posLocation);
+ gl.useProgram(0);
+ GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to release program state");
+
+ gl.deleteProgram(program);
+ program = 0;
+ GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteProgram()");
+
+ m_result.setTestContextResult(m_testCtx);
+ }
+ catch (...)
+ {
+ if (program != 0)
+ gl.deleteProgram(program);
+
+ EGLU_CHECK_CALL(egl, makeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
+ throw;
+ }
+
+ EGLU_CHECK_CALL(egl, makeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
+}
+
+class GetFrameTimestampsTests : public TestCaseGroup
+{
+public:
+ GetFrameTimestampsTests (EglTestContext& eglTestCtx);
+ void init (void);
+
+private:
+ GetFrameTimestampsTests (const GetFrameTimestampsTests&);
+ GetFrameTimestampsTests& operator= (const GetFrameTimestampsTests&);
+};
+
+
+GetFrameTimestampsTests::GetFrameTimestampsTests (EglTestContext& eglTestCtx)
+ : TestCaseGroup(eglTestCtx, "get_frame_timestamps", "Get frame timestamp tests")
+{
+}
+
+bool isWindow (const eglu::CandidateConfig& c)
+{
+ return (c.surfaceType() & EGL_WINDOW_BIT) != 0;
+}
+
+void GetFrameTimestampsTests::init (void)
+{
+ eglu::FilterList baseFilters;
+ baseFilters << isWindow;
+
+ vector<NamedFilterList> filterLists;
+ getDefaultFilterLists(filterLists, baseFilters);
+
+ for (vector<NamedFilterList>::iterator i = filterLists.begin(); i != filterLists.end(); i++)
+ addChild(new GetFrameTimestampTest(m_eglTestCtx, *i));
+}
+
+} // anonymous
+
+TestCaseGroup* createGetFrameTimestampsTests (EglTestContext& eglTestCtx)
+{
+ return new GetFrameTimestampsTests(eglTestCtx);
+}
+
+} // egl
+} // deqp
--- /dev/null
+#ifndef _TEGLGETFRAMETIMESTAMPSTESTS_HPP
+#define _TEGLGETFRAMETIMESTAMPSTESTS_HPP
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program EGL Module
+ * ---------------------------------------
+ *
+ * Copyright 2017 The Android Open Source Project
+ *
+ * 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.
+ *
+ *//*!
+ * \file
+ * \brief Test the EGL_ANDROID_get_frame_timestamps extension.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "teglTestCase.hpp"
+
+namespace deqp
+{
+namespace egl
+{
+
+TestCaseGroup* createGetFrameTimestampsTests (EglTestContext& eglTestCtx);
+
+} // egl
+} // deqp
+
+#endif // _TEGLGETFRAMETIMESTAMPSTESTS_HPP
/* WARNING: This is auto-generated file. Do not modify, since changes will
* be lost! Modify the generating script instead.
*
- * Generated from Khronos EGL API description (egl.xml) revision 32725.
+ * Generated from Khronos EGL API description (egl.xml) revision 33315.
*/
static const char* s_EGL14[] =
"eglSetBlobCacheFuncsANDROID",
};
+static const char* s_EGL_ANDROID_create_native_client_buffer[] =
+{
+ "eglCreateNativeClientBufferANDROID",
+};
+
static const char* s_EGL_ANDROID_native_fence_sync[] =
{
"eglDupNativeFenceFDANDROID",
};
+static const char* s_EGL_ANDROID_presentation_time[] =
+{
+ "eglPresentationTimeANDROID",
+};
+
static const char* s_EGL_ANGLE_query_surface_pointer[] =
{
"eglQuerySurfacePointerANGLE",
"eglQueryDisplayAttribEXT",
};
+static const char* s_EGL_EXT_image_dma_buf_import_modifiers[] =
+{
+ "eglQueryDmaBufFormatsEXT",
+ "eglQueryDmaBufModifiersEXT",
+};
+
static const char* s_EGL_EXT_output_base[] =
{
"eglGetOutputLayersEXT",
"eglStreamAttribKHR",
};
+static const char* s_EGL_KHR_stream_attrib[] =
+{
+ "eglCreateStreamAttribKHR",
+ "eglQueryStreamAttribKHR",
+ "eglSetStreamAttribKHR",
+ "eglStreamConsumerAcquireAttribKHR",
+ "eglStreamConsumerReleaseAttribKHR",
+};
+
static const char* s_EGL_KHR_stream_consumer_gltexture[] =
{
"eglStreamConsumerAcquireKHR",
"eglSetStreamMetadataNV",
};
+static const char* s_EGL_NV_stream_reset[] =
+{
+ "eglResetStreamNV",
+};
+
static const char* s_EGL_NV_stream_sync[] =
{
"eglCreateStreamSyncNV",
} s_extensions[] =
{
{ "EGL_ANDROID_blob_cache", DE_LENGTH_OF_ARRAY(s_EGL_ANDROID_blob_cache), s_EGL_ANDROID_blob_cache },
+ { "EGL_ANDROID_create_native_client_buffer", DE_LENGTH_OF_ARRAY(s_EGL_ANDROID_create_native_client_buffer), s_EGL_ANDROID_create_native_client_buffer },
{ "EGL_ANDROID_native_fence_sync", DE_LENGTH_OF_ARRAY(s_EGL_ANDROID_native_fence_sync), s_EGL_ANDROID_native_fence_sync },
+ { "EGL_ANDROID_presentation_time", DE_LENGTH_OF_ARRAY(s_EGL_ANDROID_presentation_time), s_EGL_ANDROID_presentation_time },
{ "EGL_ANGLE_query_surface_pointer", DE_LENGTH_OF_ARRAY(s_EGL_ANGLE_query_surface_pointer), s_EGL_ANGLE_query_surface_pointer },
{ "EGL_EXT_device_base", DE_LENGTH_OF_ARRAY(s_EGL_EXT_device_base), s_EGL_EXT_device_base },
{ "EGL_EXT_device_enumeration", DE_LENGTH_OF_ARRAY(s_EGL_EXT_device_enumeration), s_EGL_EXT_device_enumeration },
{ "EGL_EXT_device_query", DE_LENGTH_OF_ARRAY(s_EGL_EXT_device_query), s_EGL_EXT_device_query },
+ { "EGL_EXT_image_dma_buf_import_modifiers", DE_LENGTH_OF_ARRAY(s_EGL_EXT_image_dma_buf_import_modifiers), s_EGL_EXT_image_dma_buf_import_modifiers },
{ "EGL_EXT_output_base", DE_LENGTH_OF_ARRAY(s_EGL_EXT_output_base), s_EGL_EXT_output_base },
{ "EGL_EXT_platform_base", DE_LENGTH_OF_ARRAY(s_EGL_EXT_platform_base), s_EGL_EXT_platform_base },
{ "EGL_EXT_stream_consumer_egloutput", DE_LENGTH_OF_ARRAY(s_EGL_EXT_stream_consumer_egloutput), s_EGL_EXT_stream_consumer_egloutput },
{ "EGL_KHR_partial_update", DE_LENGTH_OF_ARRAY(s_EGL_KHR_partial_update), s_EGL_KHR_partial_update },
{ "EGL_KHR_reusable_sync", DE_LENGTH_OF_ARRAY(s_EGL_KHR_reusable_sync), s_EGL_KHR_reusable_sync },
{ "EGL_KHR_stream", DE_LENGTH_OF_ARRAY(s_EGL_KHR_stream), s_EGL_KHR_stream },
+ { "EGL_KHR_stream_attrib", DE_LENGTH_OF_ARRAY(s_EGL_KHR_stream_attrib), s_EGL_KHR_stream_attrib },
{ "EGL_KHR_stream_consumer_gltexture", DE_LENGTH_OF_ARRAY(s_EGL_KHR_stream_consumer_gltexture), s_EGL_KHR_stream_consumer_gltexture },
{ "EGL_KHR_stream_cross_process_fd", DE_LENGTH_OF_ARRAY(s_EGL_KHR_stream_cross_process_fd), s_EGL_KHR_stream_cross_process_fd },
{ "EGL_KHR_stream_fifo", DE_LENGTH_OF_ARRAY(s_EGL_KHR_stream_fifo), s_EGL_KHR_stream_fifo },
{ "EGL_NV_post_sub_buffer", DE_LENGTH_OF_ARRAY(s_EGL_NV_post_sub_buffer), s_EGL_NV_post_sub_buffer },
{ "EGL_NV_stream_consumer_gltexture_yuv", DE_LENGTH_OF_ARRAY(s_EGL_NV_stream_consumer_gltexture_yuv), s_EGL_NV_stream_consumer_gltexture_yuv },
{ "EGL_NV_stream_metadata", DE_LENGTH_OF_ARRAY(s_EGL_NV_stream_metadata), s_EGL_NV_stream_metadata },
+ { "EGL_NV_stream_reset", DE_LENGTH_OF_ARRAY(s_EGL_NV_stream_reset), s_EGL_NV_stream_reset },
{ "EGL_NV_stream_sync", DE_LENGTH_OF_ARRAY(s_EGL_NV_stream_sync), s_EGL_NV_stream_sync },
{ "EGL_NV_sync", DE_LENGTH_OF_ARRAY(s_EGL_NV_sync), s_EGL_NV_sync },
{ "EGL_NV_system_time", DE_LENGTH_OF_ARRAY(s_EGL_NV_system_time), s_EGL_NV_system_time },
using namespace eglw;
using namespace eglu;
- static const EGLint s_emptyAttribList[] = { EGL_NONE };
- static const EGLint s_es1ContextAttribList[] = { EGL_CONTEXT_CLIENT_VERSION, 1, EGL_NONE };
- static const EGLint s_es2ContextAttribList[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
+ static const EGLint s_emptyAttribList[] = { EGL_NONE };
+ static const EGLint s_es1ContextAttribList[] = { EGL_CONTEXT_CLIENT_VERSION, 1, EGL_NONE };
+ static const EGLint s_es2ContextAttribList[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
- static const EGLenum s_renderAPIs[] = { EGL_OPENGL_API, EGL_OPENGL_ES_API, EGL_OPENVG_API };
+ static const EGLenum s_renderAPIs[] = { EGL_OPENGL_API, EGL_OPENGL_ES_API, EGL_OPENVG_API };
+ static const eglu::ConfigFilter s_renderAPIFilters[] = { renderable<EGL_OPENGL_BIT>, renderable<EGL_OPENGL_ES_BIT>, renderable<EGL_OPENVG_BIT> };
TEGL_ADD_API_CASE(bind_api, "eglBindAPI() negative tests",
{
log << TestLog::EndSection;
- log << TestLog::Section("Test2", "EGL_BAD_PARAMETER is generated if the specified client API is not supported by the EGL implementation");
+ log << TestLog::Section("Test2", "EGL_BAD_PARAMETER is generated if the specified client API is not supported by the EGL display, or no configuration is provided for the specified API.");
for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_renderAPIs); ndx++)
{
if (!isAPISupported(s_renderAPIs[ndx]))
{
- expectFalse(eglBindAPI(s_renderAPIs[ndx]));
- expectError(EGL_BAD_PARAMETER);
+ if (!eglBindAPI(s_renderAPIs[ndx]))
+ expectError(EGL_BAD_PARAMETER);
+ else
+ {
+ EGLConfig eglConfig;
+ expectFalse(getConfig(&eglConfig, FilterList() << s_renderAPIFilters[ndx]));
+ }
}
}
return c.get(EGL_CONFIG_CAVEAT) != EGL_NON_CONFORMANT_CONFIG;
}
+static bool notFloat (const eglu::CandidateConfig& c)
+{
+ return c.colorComponentType() != EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT;
+}
+
void getDefaultRenderFilterLists (vector<RenderFilterList>& filterLists, const eglu::FilterList& baseFilters)
{
static const struct
<< notColorBits<4, 4, 4, 4>
<< notColorBits<5, 5, 5, 1>
<< notColorBits<8, 8, 8, 8>
- << isConformant;
+ << isConformant
+ << notFloat;
filterLists.push_back(filters);
}
--- /dev/null
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program EGL Module
+ * ---------------------------------------
+ *
+ * Copyright 2017 The Android Open Source Project
+ *
+ * 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.
+ *
+ *//*!
+ * \file
+ * \brief Robustness tests for KHR_robustness.
+ *//*--------------------------------------------------------------------*/
+
+#include "teglRobustnessTests.hpp"
+
+#include "tcuTestLog.hpp"
+#include "tcuStringTemplate.hpp"
+
+#include "egluConfigFilter.hpp"
+#include "egluStrUtil.hpp"
+#include "egluUtil.hpp"
+#include "eglwLibrary.hpp"
+
+#include "gluStrUtil.hpp"
+#include "gluShaderProgram.hpp"
+#include "gluDrawUtil.hpp"
+
+#include "glwFunctions.hpp"
+#include "glwEnums.hpp"
+
+#include "deSTLUtil.hpp"
+#include "deThread.hpp"
+#include "deSharedPtr.hpp"
+
+#include <set>
+
+using std::string;
+using std::vector;
+using std::set;
+using tcu::TestLog;
+
+using namespace eglw;
+
+DE_STATIC_ASSERT(GL_RESET_NOTIFICATION_STRATEGY == 0x8256);
+DE_STATIC_ASSERT(GL_LOSE_CONTEXT_ON_RESET == 0x8252);
+DE_STATIC_ASSERT(GL_NO_RESET_NOTIFICATION == 0x8261);
+
+namespace deqp
+{
+namespace egl
+{
+namespace
+{
+
+enum ContextResetType
+{
+ CONTEXTRESETTYPE_INFINITE_LOOP,
+ CONTEXTRESETTYPE_SHADER_OOB,
+ CONTEXTRESETTYPE_FIXED_FUNC_OOB,
+};
+
+enum ShaderType
+{
+ SHADERTYPE_VERT,
+ SHADERTYPE_FRAG,
+ SHADERTYPE_COMPUTE,
+ SHADERTYPE_VERT_AND_FRAG,
+};
+
+enum ReadWriteType
+{
+ READWRITETYPE_READ,
+ READWRITETYPE_WRITE,
+};
+
+enum ResourceType
+{
+ RESOURCETYPE_UBO,
+ RESOURCETYPE_SSBO,
+ RESOURCETYPE_LOCAL_ARRAY,
+};
+
+enum FixedFunctionType
+{
+ FIXEDFUNCTIONTYPE_INDICES,
+ FIXEDFUNCTIONTYPE_VERTICES,
+};
+
+enum RobustAccessType
+{
+ ROBUSTACCESS_TRUE,
+ ROBUSTACCESS_FALSE,
+};
+
+void requireEGLExtension (const Library& egl, EGLDisplay eglDisplay, const char* requiredExtension)
+{
+ if (!eglu::hasExtension(egl, eglDisplay, requiredExtension))
+ TCU_THROW(NotSupportedError, (string(requiredExtension) + " not supported").c_str());
+}
+
+bool isWindow (const eglu::CandidateConfig& c)
+{
+ return (c.surfaceType() & EGL_WINDOW_BIT) == EGL_WINDOW_BIT;
+}
+
+template <deUint32 Type>
+bool renderable (const eglu::CandidateConfig& c)
+{
+ return (c.renderableType() & Type) == Type;
+}
+
+eglu::ConfigFilter getRenderableFilter (deUint32 bits)
+{
+ switch (bits)
+ {
+ case EGL_OPENGL_ES2_BIT: return renderable<EGL_OPENGL_ES2_BIT>;
+ case EGL_OPENGL_ES3_BIT: return renderable<EGL_OPENGL_ES3_BIT>;
+ case EGL_OPENGL_BIT: return renderable<EGL_OPENGL_BIT>;
+ default:
+ DE_FATAL("Unknown EGL bitfied value");
+ return renderable<0>;
+ }
+}
+
+const char* eglResetNotificationStrategyToString (EGLint strategy)
+{
+ switch (strategy)
+ {
+ case EGL_NO_RESET_NOTIFICATION_KHR: return "EGL_NO_RESET_NOTIFICATION_KHR";
+ case EGL_LOSE_CONTEXT_ON_RESET_KHR: return "EGL_LOSE_CONTEXT_ON_RESET_KHR";
+ default:
+ return "<Unknown>";
+ }
+}
+
+void logAttribList (const EglTestContext& eglTestCtx, const EGLint* attribList)
+{
+ const EGLint* iter = &(attribList[0]);
+ std::ostringstream attribListString;
+
+ while ((*iter) != EGL_NONE)
+ {
+ switch (*iter)
+ {
+ // case EGL_CONTEXT_CLIENT_VERSION:
+ case EGL_CONTEXT_MAJOR_VERSION_KHR:
+ iter++;
+ attribListString << "EGL_CONTEXT_CLIENT_VERSION, " << (*iter) << ", ";
+ iter++;
+ break;
+
+ case EGL_CONTEXT_MINOR_VERSION_KHR:
+ iter++;
+ attribListString << "EGL_CONTEXT_MINOR_VERSION_KHR, " << (*iter) << ", ";
+ iter++;
+ break;
+
+ case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
+ iter++;
+ attribListString << "EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, "
+ << eglResetNotificationStrategyToString(*iter) << ", ";
+ iter++;
+ break;
+
+ case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
+ iter++;
+ attribListString << "EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, ";
+
+ if (*iter == EGL_FALSE || *iter == EGL_TRUE)
+ attribListString << (*iter ? "EGL_TRUE" : "EGL_FALSE") << ", ";
+ else
+ attribListString << (*iter) << ", ";
+ iter++;
+ break;
+
+ default:
+ DE_FATAL("Unsupported attribute");
+ }
+ }
+
+ attribListString << "EGL_NONE";
+ eglTestCtx.getTestContext().getLog() << TestLog::Message
+ << "EGL attrib list: { " << attribListString.str() << " }\n\n"
+ << TestLog::EndMessage;
+}
+
+void parseAttributeValues (const EGLint* attribList, EGLint& majorVersion, EGLint& minorVersion, EGLint& robustAccessExt)
+{
+ const EGLint* iter = attribList;
+
+ while ((*iter) != EGL_NONE)
+ {
+ switch (*iter)
+ {
+ case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
+ iter++;
+ robustAccessExt = *iter;
+ iter++;
+ break;
+
+ case EGL_CONTEXT_MAJOR_VERSION_KHR:
+ iter++;
+ majorVersion = (*iter);
+ iter++;
+ break;
+
+ case EGL_CONTEXT_MINOR_VERSION_KHR:
+ iter++;
+ minorVersion = (*iter);
+ iter++;
+ break;
+
+ case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
+ iter++;
+ iter++;
+ break;
+
+ default:
+ DE_FATAL("Unsupported EGL attribute");
+ }
+ }
+}
+
+glu::ContextType attribListToContextType (const EGLint* attribList)
+{
+ EGLint majorVersion = 1;
+ EGLint minorVersion = 0;
+ EGLint robustAccessExt = 0;
+
+ glu::ContextFlags flags = glu::ContextFlags(0);
+ const glu::Profile profile = glu::PROFILE_ES;
+ parseAttributeValues(attribList, majorVersion, minorVersion, robustAccessExt);
+
+ return glu::ContextType(majorVersion, minorVersion, profile, flags);
+}
+
+void checkRequiredGLRobustnessExtension (const EGLint* attribList, const glw::Functions& gl)
+{
+ EGLint majorVersion = 1;
+ EGLint minorVersion = 0;
+ EGLint robustAccessExt = 0;
+ parseAttributeValues(attribList, majorVersion, minorVersion, robustAccessExt);
+
+ glu::ApiType apiType = glu::ApiType::es(majorVersion, minorVersion);
+
+ if (!glu::hasExtension(gl, apiType, "GL_KHR_robustness") && !glu::hasExtension(gl, apiType, "GL_EXT_robustness"))
+ TCU_THROW(NotSupportedError, (string("GL_KHR_robustness and GL_EXT_robustness") + " not supported").c_str());
+}
+
+class RobustnessTestCase: public TestCase
+{
+public:
+ class Params
+ {
+ public:
+ Params (void) {};
+
+ Params (const string& name,
+ const string& description,
+ const RobustAccessType& robustAccessType,
+ const ContextResetType& contextResetType,
+ const FixedFunctionType& fixedFunctionType);
+
+ Params (const string& name,
+ const string& description,
+ const ContextResetType& contextResetType,
+ const ShaderType& shaderType);
+
+ Params (const string& name,
+ const string& description,
+ const RobustAccessType& robustAccessType,
+ const ContextResetType& contextResetType,
+ const ShaderType& shaderType,
+ const ResourceType& resourceType,
+ const ReadWriteType& readWriteType);
+
+ const string& getName (void) const { return m_name; }
+ const string& getDescription (void) const { return m_description; }
+ const ContextResetType& getContextResetType (void) const { return m_contextResetType; }
+ const ShaderType& getShaderType (void) const { return m_shaderType; }
+ const ResourceType& getResourceType (void) const { return m_resourceType; }
+ const ReadWriteType& getReadWriteType (void) const { return m_readWriteType; }
+ const FixedFunctionType& getFixedFunctionType (void) const { return m_fixedFunctionType; }
+ const RobustAccessType& getRobustAccessType (void) const { return m_robustAccessType; }
+
+ private:
+ string m_name;
+ string m_description;
+ RobustAccessType m_robustAccessType;
+ ContextResetType m_contextResetType;
+ ShaderType m_shaderType;
+ ResourceType m_resourceType;
+ ReadWriteType m_readWriteType;
+ FixedFunctionType m_fixedFunctionType;
+ };
+
+ RobustnessTestCase (EglTestContext& eglTestCtx, const char* name, const char* description);
+ RobustnessTestCase (EglTestContext& eglTestCtx, const char* name, const char* description, Params params);
+ ~RobustnessTestCase (void);
+
+ void checkRequiredEGLExtensions (const EGLint* attribList);
+
+protected:
+ Params m_params;
+ EGLDisplay m_eglDisplay;
+ EGLConfig m_eglConfig;
+ EGLSurface m_eglSurface;
+
+private:
+ void init (void);
+ void deinit (void);
+ void initEGLSurface (void);
+ EGLConfig getEGLConfig (void);
+
+ eglu::NativeWindow* m_window;
+ glu::ContextType m_glContextType;
+
+};
+
+RobustnessTestCase::Params::Params (const string& name,
+ const string& description,
+ const RobustAccessType& robustAccessType,
+ const ContextResetType& contextResetType,
+ const FixedFunctionType& fixedFunctionType)
+ : m_name (name)
+ , m_description (description)
+ , m_robustAccessType (robustAccessType)
+ , m_contextResetType (contextResetType)
+ , m_fixedFunctionType (fixedFunctionType)
+{
+}
+
+RobustnessTestCase::Params::Params (const string& name,
+ const string& description,
+ const ContextResetType& contextResetType,
+ const ShaderType& shaderType)
+ : m_name (name)
+ , m_description (description)
+ , m_contextResetType (contextResetType)
+ , m_shaderType (shaderType)
+{
+}
+
+RobustnessTestCase::Params::Params (const string& name,
+ const string& description,
+ const RobustAccessType& robustAccessType,
+ const ContextResetType& contextResetType,
+ const ShaderType& shaderType,
+ const ResourceType& resourceType,
+ const ReadWriteType& readWriteType)
+ : m_name (name)
+ , m_description (description)
+ , m_robustAccessType (robustAccessType)
+ , m_contextResetType (contextResetType)
+ , m_shaderType (shaderType)
+ , m_resourceType (resourceType)
+ , m_readWriteType (readWriteType)
+{
+}
+
+RobustnessTestCase::RobustnessTestCase (EglTestContext& eglTestCtx, const char* name, const char* description)
+ : TestCase (eglTestCtx, name, description)
+ , m_eglDisplay (EGL_NO_DISPLAY)
+ , m_eglConfig (0)
+ , m_eglSurface (EGL_NO_SURFACE)
+ , m_window (DE_NULL)
+{
+}
+
+RobustnessTestCase::RobustnessTestCase (EglTestContext& eglTestCtx, const char* name, const char* description, Params params)
+ : TestCase (eglTestCtx, name, description)
+ , m_params (params)
+ , m_eglDisplay (EGL_NO_DISPLAY)
+ , m_eglConfig (0)
+ , m_eglSurface (EGL_NO_SURFACE)
+ , m_window (DE_NULL)
+{
+}
+
+RobustnessTestCase::~RobustnessTestCase (void)
+{
+ deinit();
+}
+
+void RobustnessTestCase::init (void)
+{
+ m_eglDisplay = eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay());
+ m_eglConfig = getEGLConfig();
+
+ initEGLSurface();
+}
+
+void RobustnessTestCase::deinit (void)
+{
+ const Library& egl = m_eglTestCtx.getLibrary();
+
+ if (m_eglSurface != EGL_NO_SURFACE)
+ {
+ egl.destroySurface(m_eglDisplay, m_eglSurface);
+ m_eglSurface = EGL_NO_SURFACE;
+ }
+ if (m_eglDisplay != EGL_NO_DISPLAY)
+ {
+ egl.terminate(m_eglDisplay);
+ m_eglDisplay = EGL_NO_DISPLAY;
+ }
+
+ delete m_window;
+ m_window = DE_NULL;
+}
+
+EGLConfig RobustnessTestCase::getEGLConfig (void)
+{
+ eglu::FilterList filters;
+ filters << isWindow << getRenderableFilter(EGL_OPENGL_ES3_BIT);
+ return eglu::chooseSingleConfig(m_eglTestCtx.getLibrary(), m_eglDisplay, filters);
+}
+
+void RobustnessTestCase::initEGLSurface (void)
+{
+ EGLU_CHECK_CALL(m_eglTestCtx.getLibrary(), bindAPI(EGL_OPENGL_ES_API));
+
+ const eglu::NativeWindowFactory& factory = eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
+
+ const eglu::WindowParams windowParams = eglu::WindowParams(256, 256, eglu::parseWindowVisibility(m_testCtx.getCommandLine()));
+ m_window = factory.createWindow(&m_eglTestCtx.getNativeDisplay(), m_eglDisplay, m_eglConfig, DE_NULL, windowParams);
+ m_eglSurface = eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *m_window, m_eglDisplay, m_eglConfig, DE_NULL);
+}
+
+void RobustnessTestCase::checkRequiredEGLExtensions (const EGLint* attribList)
+{
+ set<string> requiredExtensions;
+ vector<string> extensions = eglu::getDisplayExtensions(m_eglTestCtx.getLibrary(), m_eglDisplay);
+
+ {
+ const EGLint* iter = attribList;
+
+ while ((*iter) != EGL_NONE)
+ {
+ switch (*iter)
+ {
+ case EGL_CONTEXT_MAJOR_VERSION_KHR: iter++;
+ iter++;
+ break;
+
+ case EGL_CONTEXT_MINOR_VERSION_KHR:
+ iter++;
+ requiredExtensions.insert("EGL_KHR_create_context");
+ iter++;
+ break;
+
+ case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
+ case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
+ iter++;
+ requiredExtensions.insert("EGL_EXT_create_context_robustness");
+ iter++;
+ break;
+
+ default:
+ DE_ASSERT(DE_FALSE);
+ }
+ }
+ }
+
+ for (std::set<string>::const_iterator reqExt = requiredExtensions.begin(); reqExt != requiredExtensions.end(); ++reqExt)
+ {
+ if (!de::contains(extensions.begin(), extensions.end(), *reqExt))
+ {
+ const char* const extension = reqExt->c_str();
+ requireEGLExtension(m_eglTestCtx.getLibrary(), m_eglDisplay, extension);
+ }
+ }
+}
+
+
+class RenderingContext
+{
+public:
+ RenderingContext (const EglTestContext& eglTestCtx,
+ const EGLint* attribList,
+ const EGLConfig& config,
+ const EGLDisplay& display,
+ const EGLContext& sharedContext);
+ ~RenderingContext (void);
+
+ void initGLFunctions (glw::Functions* gl);
+ void makeCurrent (const EGLSurface& surface);
+ EGLContext getContext (void);
+
+private:
+ const EglTestContext& m_eglTestCtx;
+ const EGLint* m_attribList;
+ const EGLConfig& m_config;
+ const EGLDisplay& m_display;
+ const Library& m_egl;
+
+ EGLContext m_context;
+
+ void createContext (const EGLConfig& sharedConfig);
+ void destroyContext (void);
+
+ RenderingContext (const RenderingContext&);
+ RenderingContext& operator= (const RenderingContext&);
+};
+
+RenderingContext::RenderingContext (const EglTestContext& eglTestCtx,
+ const EGLint* attribList,
+ const EGLConfig& config,
+ const EGLDisplay& display,
+ const EGLContext& sharedContext)
+ : m_eglTestCtx (eglTestCtx)
+ , m_attribList (attribList)
+ , m_config (config)
+ , m_display (display)
+ , m_egl (eglTestCtx.getLibrary())
+ , m_context (EGL_NO_CONTEXT)
+{
+ logAttribList(eglTestCtx, m_attribList);
+ createContext(sharedContext);
+}
+
+RenderingContext::~RenderingContext (void)
+{
+ destroyContext();
+}
+
+void RenderingContext::createContext (const EGLConfig& sharedContext)
+{
+ m_context = m_egl.createContext(m_display, m_config, sharedContext, m_attribList);
+ EGLU_CHECK_MSG(m_egl, "eglCreateContext()");
+}
+
+void RenderingContext::destroyContext (void)
+{
+ EGLU_CHECK_CALL(m_eglTestCtx.getLibrary(), makeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
+
+ if (m_context != EGL_NO_CONTEXT)
+ m_egl.destroyContext(m_display, m_context);
+}
+
+void RenderingContext::makeCurrent (const EGLSurface& surface)
+{
+ EGLU_CHECK_CALL(m_egl, makeCurrent(m_display, surface, surface, m_context));
+}
+
+void RenderingContext::initGLFunctions (glw::Functions *gl)
+{
+ // \todo [2017-03-23 pyry] Current version has 2 somewhat ugly hacks:
+ //
+ // 1) Core functions are loaded twice. We need glGetString(i) to query supported
+ // extensions to determine if we need to load EXT or KHR-suffixed robustness
+ // functions. This could be fixed by exposing glw::FunctionLoader in EglTestContext
+ // for example.
+ //
+ // 2) We assume that calling code will check for KHR_robustness or EXT_robustness
+ // support after calling initGLFunctions(). We could move the check here.
+
+ const glu::ApiType apiType = attribListToContextType(m_attribList).getAPI();
+
+ m_eglTestCtx.initGLFunctions(gl, apiType);
+
+ {
+ const char* const robustnessExt = glu::hasExtension(*gl, apiType, "GL_KHR_robustness") ? "GL_KHR_robustness" : "GL_EXT_robustness";
+ const char* const extensions[] = { robustnessExt };
+
+ m_eglTestCtx.initGLFunctions(gl, apiType, DE_LENGTH_OF_ARRAY(extensions), &extensions[0]);
+ }
+}
+
+EGLContext RenderingContext::getContext (void)
+{
+ return m_context;
+}
+
+class ContextReset
+{
+public:
+ ContextReset (glw::Functions& gl, tcu::TestLog& log, FixedFunctionType fixedFunctionType);
+ ContextReset (glw::Functions& gl, tcu::TestLog& log, ShaderType shaderType);
+ ContextReset (glw::Functions& gl, tcu::TestLog& log, ShaderType shaderType, ResourceType resourceType, ReadWriteType readWriteType);
+
+ virtual ~ContextReset (void) {};
+
+ virtual void setup (void) = 0;
+ virtual void draw (void) = 0;
+ virtual void teardown (void) = 0;
+
+ void finish (void);
+ void createSyncObject (void);
+ glw::GLint getSyncStatus (void);
+
+ void beginQuery (void);
+ void endQuery (void);
+ glw::GLint getError (void);
+ glw::GLint getGraphicsResetStatus (void);
+ glw::GLuint getQueryAvailability (void);
+
+ glw::GLsync getSyncObject (void) const { return m_sync; }
+ glw::GLuint getQueryID (void) const { return m_queryID; }
+
+ glw::Functions& m_gl;
+ tcu::TestLog& m_log;
+ ShaderType m_shaderType;
+ ResourceType m_resourceType;
+ ReadWriteType m_readWriteType;
+ FixedFunctionType m_fixedFunctionType;
+
+private:
+ ContextReset (const ContextReset&);
+ ContextReset& operator= (const ContextReset&);
+
+ glw::GLuint m_queryID;
+ glw::GLsync m_sync;
+};
+
+ContextReset::ContextReset (glw::Functions& gl, tcu::TestLog& log, FixedFunctionType fixedFunctionType)
+ : m_gl (gl)
+ , m_log (log)
+ , m_fixedFunctionType (fixedFunctionType)
+{
+}
+
+ContextReset::ContextReset (glw::Functions& gl, tcu::TestLog& log, ShaderType shaderType, ResourceType resourceType, ReadWriteType readWriteType)
+ : m_gl (gl)
+ , m_log (log)
+ , m_shaderType (shaderType)
+ , m_resourceType (resourceType)
+ , m_readWriteType (readWriteType)
+{
+}
+
+ContextReset::ContextReset (glw::Functions& gl, tcu::TestLog& log, ShaderType shaderType)
+ : m_gl (gl)
+ , m_log (log)
+ , m_shaderType (shaderType)
+{
+}
+
+void ContextReset::finish (void)
+{
+ GLU_CHECK_GLW_CALL(m_gl, finish());
+}
+
+void ContextReset::createSyncObject (void)
+{
+ m_sync = m_gl.fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+ GLU_EXPECT_NO_ERROR(m_gl.getError(), "glFenceSync()");
+}
+
+glw::GLint ContextReset::getError (void)
+{
+ glw::GLint error;
+ error = m_gl.getError();
+
+ return error;
+}
+
+glw::GLint ContextReset::getGraphicsResetStatus (void)
+{
+ glw::GLint resetStatus;
+ resetStatus = m_gl.getGraphicsResetStatus();
+
+ return resetStatus;
+}
+
+glw::GLint ContextReset::getSyncStatus (void)
+{
+ glw::GLint syncStatus;
+ m_gl.getSynciv(m_sync, GL_SYNC_STATUS, sizeof(glw::GLint), NULL, &syncStatus);
+
+ return syncStatus;
+}
+
+void ContextReset::beginQuery (void)
+{
+ GLU_CHECK_GLW_CALL(m_gl, genQueries(1, &m_queryID));
+ GLU_CHECK_GLW_CALL(m_gl, beginQuery(GL_ANY_SAMPLES_PASSED, m_queryID));
+}
+
+void ContextReset::endQuery (void)
+{
+ GLU_CHECK_GLW_CALL(m_gl, endQuery(GL_ANY_SAMPLES_PASSED));
+}
+
+glw::GLuint ContextReset::getQueryAvailability (void)
+{
+ glw::GLuint queryReady = GL_FALSE;
+ m_gl.getQueryObjectuiv(m_queryID, GL_QUERY_RESULT_AVAILABLE, &queryReady);
+
+ return queryReady;
+}
+
+class InfiniteLoop : public ContextReset
+{
+public:
+ InfiniteLoop (glw::Functions& gl, tcu::TestLog& log, ShaderType shaderType);
+ ~InfiniteLoop (void);
+
+ virtual void setup (void);
+ virtual void draw (void);
+ virtual void teardown (void);
+
+private:
+ glu::ProgramSources genComputeSource (void);
+ glu::ProgramSources genNonComputeSource (void);
+ glu::ProgramSources genSources (void);
+
+ glw::GLuint m_outputBuffer;
+ glw::GLuint m_coordinatesBuffer;
+ glw::GLint m_coordLocation;
+};
+
+InfiniteLoop::InfiniteLoop (glw::Functions& gl, tcu::TestLog& log, ShaderType shaderType)
+ : ContextReset(gl, log, shaderType)
+ , m_outputBuffer (0)
+ , m_coordinatesBuffer (0)
+ , m_coordLocation (0)
+{
+}
+
+InfiniteLoop::~InfiniteLoop (void)
+{
+ try
+ {
+ // Reset GL_CONTEXT_LOST error before destroying resources
+ m_gl.getGraphicsResetStatus();
+ teardown();
+ }
+ catch (...)
+ {
+ // Ignore GL errors from teardown()
+ }
+}
+
+glu::ProgramSources InfiniteLoop::genSources(void)
+{
+ if (m_shaderType == SHADERTYPE_COMPUTE)
+ return genComputeSource();
+ else
+ return genNonComputeSource();
+}
+
+glu::ProgramSources InfiniteLoop::genComputeSource(void)
+{
+ const char* const computeSource =
+ "#version 310 es\n"
+ "layout(local_size_x = 1, local_size_y = 1) in;\n"
+ "uniform highp int u_iterCount;\n"
+ "writeonly buffer Output { highp int b_output_int; };\n"
+ "void main ()\n"
+ "{\n"
+ " for (highp int i = 0; i < u_iterCount || u_iterCount < 0; ++i)\n"
+ " b_output_int = u_iterCount;\n"
+ "}\n";
+
+ return glu::ProgramSources() << glu::ComputeSource(computeSource);
+}
+
+glu::ProgramSources InfiniteLoop::genNonComputeSource (void)
+{
+ const bool isVertCase = m_shaderType == SHADERTYPE_VERT;
+ const bool isFragCase = m_shaderType == SHADERTYPE_FRAG;
+ const bool isVertAndFragment = m_shaderType == SHADERTYPE_VERT_AND_FRAG;
+
+ std::ostringstream vert, frag;
+
+ vert << "#version 300 es\n"
+ << "in highp vec2 a_position;\n";
+
+ frag << "#version 300 es\n";
+
+ vert << "uniform highp int u_iterCount;\n";
+ if (isFragCase || isVertAndFragment)
+ {
+ vert << "flat out highp int v_iterCount;\n";
+ frag << "flat in highp int v_iterCount;\n";
+ }
+
+ if (isVertCase || isVertAndFragment)
+ {
+ vert << "out mediump vec4 v_color;\n";
+ frag << "in mediump vec4 v_color;\n";
+ }
+
+ frag << "out mediump vec4 o_color;\n";
+
+ vert << "\nvoid main (void)\n{\n"
+ << " gl_Position = vec4(a_position, 0.0, 1.0);\n"
+ << " gl_PointSize = 1.0;\n";
+
+ if (isFragCase || isVertAndFragment)
+ vert << " v_iterCount = u_iterCount;\n";
+
+ frag << "\nvoid main (void)\n{\n";
+
+ const std::string iterCount = (isVertCase ? "u_iterCount" : "v_iterCount");
+ const std::string loopHeader = " for (highp int i = 0; i < " + iterCount + " || " + iterCount + " < 0; ++i)\n";
+ const char* const body = "color = cos(sin(color*1.25)*0.8);";
+
+ if (isVertAndFragment)
+ {
+ vert << " mediump vec4 color = " << "a_position.xyxy" << ";\n";
+ vert << loopHeader << " " << body << "\n";
+
+ frag << " mediump vec4 color = " << "gl_FragCoord" << ";\n";
+ frag << loopHeader << " " << body << "\n";
+ }
+ else
+ {
+ std::ostringstream& op = isVertCase ? vert : frag;
+ op << " mediump vec4 color = " << (isVertCase ? "a_position.xyxy" : "gl_FragCoord") << ";\n";
+ op << loopHeader << " " << body << "\n";
+ }
+
+ if (isVertCase || isVertAndFragment)
+ {
+ vert << " v_color = color;\n";
+ frag << " o_color = v_color;\n";
+ }
+ else
+ frag << " o_color = color;\n";
+
+ vert << "}\n";
+ frag << "}\n";
+
+ return glu::ProgramSources() << glu::VertexSource(vert.str()) << glu::FragmentSource(frag.str());
+}
+
+void InfiniteLoop::setup (void)
+{
+ glu::ShaderProgram program (m_gl, genSources());
+ m_log << program;
+
+ if (!program.isOk())
+ TCU_FAIL("Failed to compile shader program");
+
+ GLU_CHECK_GLW_CALL(m_gl, useProgram(program.getProgram()));
+
+ if (m_shaderType == SHADERTYPE_COMPUTE)
+ {
+ // Output buffer setup
+ m_outputBuffer = 0;
+ GLU_CHECK_GLW_CALL(m_gl, genBuffers(1, &m_outputBuffer));
+ GLU_CHECK_GLW_CALL(m_gl, bindBuffer(GL_SHADER_STORAGE_BUFFER, m_outputBuffer));
+ GLU_CHECK_GLW_CALL(m_gl, bufferData(GL_SHADER_STORAGE_BUFFER, sizeof(int), DE_NULL, GL_DYNAMIC_DRAW));
+ GLU_CHECK_GLW_CALL(m_gl, bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_outputBuffer));
+ }
+ else
+ {
+ const glw::GLfloat coords[] =
+ {
+ -1.0f, -1.0f,
+ +1.0f, -1.0f,
+ +1.0f, +1.0f,
+ -1.0f, +1.0f
+ };
+
+ m_coordLocation = m_gl.getAttribLocation(program.getProgram(), "a_position");
+ GLU_CHECK_GLW_MSG(m_gl, "glGetAttribLocation()");
+ TCU_CHECK(m_coordLocation != (glw::GLint)-1);
+
+ // Load the vertex data
+ m_coordinatesBuffer = 0;
+ GLU_CHECK_GLW_CALL(m_gl, genBuffers(1, &m_coordinatesBuffer));
+ GLU_CHECK_GLW_CALL(m_gl, bindBuffer(GL_ARRAY_BUFFER, m_coordinatesBuffer));
+ GLU_CHECK_GLW_CALL(m_gl, bufferData(GL_ARRAY_BUFFER, (glw::GLsizeiptr)sizeof(coords), coords, GL_STATIC_DRAW));
+ GLU_CHECK_GLW_CALL(m_gl, enableVertexAttribArray(m_coordLocation));
+ GLU_CHECK_GLW_CALL(m_gl, vertexAttribPointer(m_coordLocation, 2, GL_FLOAT, GL_FALSE, 0, DE_NULL));
+ }
+
+ glw::GLint iterCountLocation = m_gl.getUniformLocation(program.getProgram(), "u_iterCount");
+ GLU_CHECK_GLW_MSG(m_gl, "glGetUniformLocation()");
+ TCU_CHECK(iterCountLocation != (glw::GLint)-1);
+
+ // Set the iteration count (infinite)
+ glw::GLint iterCount = -1;
+ GLU_CHECK_GLW_CALL(m_gl, uniform1i(iterCountLocation, iterCount));
+}
+
+void InfiniteLoop::draw (void)
+{
+ if (m_shaderType == SHADERTYPE_COMPUTE)
+ m_gl.dispatchCompute(1, 1, 1);
+ else
+ {
+ const glw::GLushort indices[] = { 0, 1, 2, 2, 3, 0 };
+ m_gl.drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
+ }
+}
+
+void InfiniteLoop::teardown (void)
+{
+ if (m_shaderType != SHADERTYPE_COMPUTE)
+ {
+ if (m_coordLocation)
+ {
+ GLU_CHECK_GLW_CALL(m_gl, disableVertexAttribArray(m_coordLocation));
+ m_coordLocation = 0;
+ }
+ }
+
+ if (m_outputBuffer)
+ {
+ GLU_CHECK_GLW_CALL(m_gl, deleteBuffers(1, &m_outputBuffer));
+ m_outputBuffer = 0;
+ }
+
+ if (m_coordinatesBuffer)
+ {
+ GLU_CHECK_GLW_CALL(m_gl, deleteBuffers(1, &m_coordinatesBuffer));
+ m_coordinatesBuffer = 0;
+ }
+
+ GLU_CHECK_GLW_CALL(m_gl, useProgram(0));
+}
+
+class FixedFunctionOOB : public ContextReset
+{
+public:
+ FixedFunctionOOB (glw::Functions& gl, tcu::TestLog& log, FixedFunctionType fixedFunctionType);
+ ~FixedFunctionOOB (void);
+
+ struct TestConfig
+ {
+ int textureWidth;
+ int textureHeight;
+ };
+
+ virtual void setup (void);
+ virtual void draw (void);
+ virtual void teardown (void);
+
+private:
+ glu::ProgramSources genSources (void);
+ glw::GLuint m_coordinatesBuffer;
+ glw::GLint m_coordLocation;
+};
+
+FixedFunctionOOB::FixedFunctionOOB (glw::Functions& gl, tcu::TestLog& log, FixedFunctionType fixedFunctionType)
+ : ContextReset(gl, log, fixedFunctionType)
+ , m_coordinatesBuffer (0)
+ , m_coordLocation (0)
+{
+}
+
+FixedFunctionOOB::~FixedFunctionOOB (void)
+{
+ try
+ {
+ // Reset GL_CONTEXT_LOST error before destroying resources
+ m_gl.getGraphicsResetStatus();
+ teardown();
+ }
+ catch (...)
+ {
+ // Ignore GL errors from teardown()
+ }
+}
+
+glu::ProgramSources FixedFunctionOOB::genSources (void)
+{
+ const char* const vert =
+ "#version 310 es\n"
+ "in highp vec4 a_position;\n"
+ "void main (void)\n"
+ "{\n"
+ " gl_Position = a_position;\n"
+ "}\n";
+
+ const char* const frag =
+ "#version 310 es\n"
+ "layout(location = 0) out highp vec4 fragColor;\n"
+ "void main (void)\n"
+ "{\n"
+ " fragColor = vec4(1.0f);\n"
+ "}\n";
+
+ return glu::ProgramSources() << glu::VertexSource(vert) << glu::FragmentSource(frag);
+}
+
+void FixedFunctionOOB::setup (void)
+{
+ glu::ShaderProgram program(m_gl, genSources());
+
+ m_log << program;
+
+ if (!program.isOk())
+ TCU_FAIL("Failed to compile shader program");
+
+ GLU_CHECK_GLW_CALL(m_gl, useProgram(program.getProgram()));
+
+ const glw::GLfloat coords[] =
+ {
+ -1.0f, -1.0f,
+ 1.0f, -1.0f,
+ 1.0f, 1.0f,
+ -1.0f, 1.0f
+ };
+
+ m_coordLocation = m_gl.getAttribLocation(program.getProgram(), "a_position");
+ GLU_CHECK_GLW_MSG(m_gl, "glGetAttribLocation()");
+ TCU_CHECK(m_coordLocation != (glw::GLint)-1);
+
+ // Load the vertex data
+ m_coordinatesBuffer = 0;
+ GLU_CHECK_GLW_CALL(m_gl, genBuffers(1, &m_coordinatesBuffer));
+ GLU_CHECK_GLW_CALL(m_gl, bindBuffer(GL_ARRAY_BUFFER, m_coordinatesBuffer));
+ GLU_CHECK_GLW_CALL(m_gl, bufferData(GL_ARRAY_BUFFER, (glw::GLsizeiptr)sizeof(coords), coords, GL_STATIC_DRAW));
+ GLU_CHECK_GLW_CALL(m_gl, enableVertexAttribArray(m_coordLocation));
+ GLU_CHECK_GLW_CALL(m_gl, vertexAttribPointer(m_coordLocation, 2, GL_FLOAT, GL_FALSE, 0, DE_NULL));
+}
+
+void FixedFunctionOOB::draw (void)
+{
+ const glw::GLint bad_indices[] = {0, 10, 100, 1000, 10000, 100000};
+
+ if (m_fixedFunctionType == FIXEDFUNCTIONTYPE_INDICES)
+ m_gl.drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, bad_indices);
+ else if (m_fixedFunctionType == FIXEDFUNCTIONTYPE_VERTICES)
+ m_gl.drawArrays(GL_TRIANGLES, 0, 1000);
+ else
+ DE_FATAL("Unknown fixed function type");
+}
+
+void FixedFunctionOOB::teardown (void)
+{
+ if (m_coordLocation)
+ {
+ GLU_CHECK_GLW_CALL(m_gl, disableVertexAttribArray(m_coordLocation));
+ m_coordLocation = 0;
+ }
+
+ if (m_coordinatesBuffer)
+ {
+ GLU_CHECK_GLW_CALL(m_gl, deleteBuffers(1, &m_coordinatesBuffer));
+ m_coordinatesBuffer = 0;
+ }
+
+ GLU_CHECK_GLW_CALL(m_gl, useProgram(0));
+}
+
+class ShadersOOB : public ContextReset
+{
+public:
+ ShadersOOB (glw::Functions& gl, tcu::TestLog& log, ShaderType shaderType, ResourceType resourceType, ReadWriteType readWriteType);
+ ~ShadersOOB (void);
+
+ virtual void setup (void);
+ virtual void draw (void);
+ virtual void teardown (void);
+
+private:
+ static const int s_numBindings = 3;
+
+ glw::GLuint m_coordinatesBuffer;
+ glw::GLint m_coordLocation;
+
+ bool m_isUBO;
+ bool m_isRead;
+ bool m_isLocalArray;
+ std::vector<glw::GLuint> m_buffers;
+
+ std::string genVertexShader (const std::string& shaderDecl, const std::string& shaderBody);
+ std::string genFragmentShader (const std::string& shaderDecl, const std::string& shaderBody);
+ std::string genComputeShader (const std::string& shaderDecl, const std::string& shaderBody);
+
+ glu::ProgramSources genNonComputeSource (void);
+ glu::ProgramSources genComputeSource (void);
+ glu::ProgramSources genSources (void);
+};
+
+ShadersOOB::ShadersOOB (glw::Functions& gl, tcu::TestLog& log, ShaderType shaderType, ResourceType resourceType, ReadWriteType readWriteType)
+ : ContextReset(gl, log, shaderType, resourceType, readWriteType)
+ , m_coordinatesBuffer (0)
+ , m_coordLocation (0)
+ , m_buffers (s_numBindings, 0)
+{
+ m_isUBO = (m_resourceType == RESOURCETYPE_UBO);
+ m_isLocalArray = (m_resourceType == RESOURCETYPE_LOCAL_ARRAY);
+ m_isRead = (m_readWriteType == READWRITETYPE_READ);
+}
+
+ShadersOOB::~ShadersOOB (void)
+{
+ try
+ {
+ // Reset GL_CONTEXT_LOST error before destroying resources
+ m_gl.getGraphicsResetStatus();
+ teardown();
+ }
+ catch (...)
+ {
+ // Ignore GL errors from teardown()
+ }
+}
+
+std::string ShadersOOB::genVertexShader (const std::string& shaderDecl, const std::string& shaderBody)
+{
+ static const char* const s_simpleVertexShaderSource =
+ "#version 310 es\n"
+ "in highp vec4 a_position;\n"
+ "void main (void)\n"
+ "{\n"
+ " gl_Position = a_position;\n"
+ "}\n";
+
+ switch (m_shaderType)
+ {
+ case SHADERTYPE_VERT:
+ case SHADERTYPE_VERT_AND_FRAG:
+ {
+ std::ostringstream vertexShaderSource;
+ vertexShaderSource << "#version 310 es\n"
+ << "in highp vec4 a_position;\n"
+ << "out highp vec4 v_color;\n"
+ << shaderDecl << "\n"
+ << "void main (void)\n"
+ << "{\n"
+ << " highp vec4 color;\n"
+ << shaderBody << "\n"
+ << " v_color = color;\n"
+ << " gl_Position = a_position;\n"
+ << "}\n";
+
+ return vertexShaderSource.str();
+ }
+
+ case SHADERTYPE_FRAG:
+ return s_simpleVertexShaderSource;
+
+ default:
+ DE_FATAL("Unknown shader type");
+ return "";
+ }
+}
+
+std::string ShadersOOB::genFragmentShader (const std::string& shaderDecl, const std::string& shaderBody)
+{
+ static const char* const s_simpleFragmentShaderSource =
+ "#version 310 es\n"
+ "in highp vec4 v_color;\n"
+ "layout(location = 0) out highp vec4 fragColor;\n"
+ "void main (void)\n"
+ "{\n"
+ " fragColor = v_color;\n"
+ "}\n";
+
+ switch (m_shaderType)
+ {
+ case SHADERTYPE_VERT:
+ return s_simpleFragmentShaderSource;
+
+ case SHADERTYPE_FRAG:
+ {
+ std::ostringstream fragmentShaderSource;
+ fragmentShaderSource << "#version 310 es\n"
+ << "layout(location = 0) out highp vec4 fragColor;\n"
+ << shaderDecl << "\n"
+ << "void main (void)\n"
+ << "{\n"
+ << " highp vec4 color = vec4(0.0f);\n"
+ << shaderBody << "\n"
+ << " fragColor = color;\n"
+ << "}\n";
+
+ return fragmentShaderSource.str();
+ }
+ case SHADERTYPE_VERT_AND_FRAG:
+ {
+ std::ostringstream fragmentShaderSource;
+ fragmentShaderSource << "#version 310 es\n"
+ << "in highp vec4 v_color;\n"
+ << "layout(location = 0) out highp vec4 fragColor;\n"
+ << shaderDecl << "\n"
+ << "void main (void)\n"
+ << "{\n"
+ << " highp vec4 color = vec4(0.0f);\n"
+ << shaderBody << "\n"
+ << " fragColor = color;\n"
+ << "}\n";
+
+ return fragmentShaderSource.str();
+ }
+
+ default:
+ DE_FATAL("Unknown shader type");
+ return "";
+ }
+}
+
+std::string ShadersOOB::genComputeShader (const std::string& shaderDecl, const std::string& shaderBody)
+{
+ std::ostringstream computeShaderSource;
+
+ computeShaderSource << "#version 310 es\n"
+ << "layout(local_size_x = 1, local_size_y = 1) in;\n"
+ << "\n"
+ << "layout(binding = 0) buffer Output {\n"
+ << " highp vec4 values;\n"
+ << "} sb_out;\n"
+ << "\n"
+ << shaderDecl
+ << "void main ()\n"
+ << "{\n"
+ << shaderBody
+ << "}\n";
+
+ return computeShaderSource.str();
+}
+
+glu::ProgramSources ShadersOOB::genNonComputeSource (void)
+{
+ std::ostringstream shaderDecl;
+ std::ostringstream shaderBody;
+
+ shaderDecl << "uniform highp int u_index;\n";
+
+ if (m_isLocalArray)
+ {
+ const char* const readWriteStatement = (m_isRead)
+ ? " color.x = color_out[u_index];\n"
+ : " color[u_index] = color_out.x;\n";
+
+ shaderBody << " highp vec4 color_out = vec4(1.0f);\n"
+ << readWriteStatement;
+ }
+ else
+ {
+ const std::string resName = (m_isUBO) ? "ub_in" : "sb_in";
+
+ shaderDecl << "layout(std140, binding = 0) " << ((m_isUBO) ? "uniform" : "buffer") << " Block\n"
+ << "{\n"
+ << " highp vec4 color_out;\n"
+ << "} " << resName << "[" << s_numBindings << "];\n";
+
+ const std::string readWriteStatement = (m_isRead)
+ ? " color.x = " + resName + "[0].color_out[u_index];\n"
+ : " color[u_index] = " + resName + "[0].color_out.x;\n";
+
+ shaderBody << readWriteStatement;
+ }
+
+ return glu::ProgramSources() << glu::VertexSource(genVertexShader(shaderDecl.str(), shaderBody.str()))
+ << glu::FragmentSource(genFragmentShader(shaderDecl.str(), shaderBody.str()));
+}
+
+glu::ProgramSources ShadersOOB::genComputeSource (void)
+{
+ std::ostringstream shaderDecl;
+ std::ostringstream shaderBody;
+
+ shaderDecl << "uniform highp int u_index;\n";
+
+ shaderBody << " uvec3 size = gl_NumWorkGroups * gl_WorkGroupSize;\n"
+ << " uint groupNdx = size.x*gl_GlobalInvocationID.y + gl_GlobalInvocationID.x;\n";
+
+ if (m_isLocalArray)
+ {
+ const char* const readWriteStatement = (m_isRead)
+ ? " sb_out.values.x = values[u_index];\n"
+ : " sb_out.values[u_index] = values.x;\n";
+
+ shaderBody << " highp vec4 values = vec4(1.0f) * float(groupNdx);\n"
+ << readWriteStatement;
+ }
+ else
+ {
+ const std::string resName = (m_isUBO) ? "ub_in" : "sb_in";
+
+ shaderDecl << "layout(std140, binding = 1) " << ((m_isUBO) ? "uniform" : "buffer") << " Input\n"
+ << "{\n"
+ << " highp vec4 values;\n"
+ << "} " << resName << "[" << s_numBindings << "];\n";
+
+ std::string readWriteStatement = (m_isRead)
+ ? " sb_out.values.x = " + resName + "[0].values[u_index] * float(groupNdx);\n"
+ : " sb_out.values[u_index] = " + resName + "[0].values.x * float(groupNdx);\n";
+
+ shaderBody << readWriteStatement;
+ }
+
+ return glu::ProgramSources() << glu::ComputeSource(genComputeShader(shaderDecl.str(), shaderBody.str()));
+}
+
+glu::ProgramSources ShadersOOB::genSources (void)
+{
+ if (m_shaderType == SHADERTYPE_COMPUTE)
+ return genComputeSource();
+ else
+ return genNonComputeSource();
+}
+
+void ShadersOOB::setup (void)
+{
+ glu::ShaderProgram program(m_gl, genSources());
+
+ m_log << program;
+
+ if (!program.isOk())
+ TCU_FAIL("Failed to compile shader program");
+
+ GLU_CHECK_GLW_CALL(m_gl, useProgram(program.getProgram()));
+
+ const glw::GLint indexLocation = m_gl.getUniformLocation(program.getProgram(), "u_index");
+ GLU_CHECK_GLW_MSG(m_gl, "glGetUniformLocation()");
+ TCU_CHECK(indexLocation != (glw::GLint)-1);
+
+ const glw::GLint index = -1;
+ GLU_CHECK_GLW_CALL(m_gl, uniform1i(indexLocation, index));
+
+ if (m_shaderType != SHADERTYPE_COMPUTE)
+ {
+ const glw::GLfloat coords[] =
+ {
+ -1.0f, -1.0f,
+ +1.0f, -1.0f,
+ +1.0f, +1.0f,
+ -1.0f, +1.0f
+ };
+
+ // Setup vertices position
+ m_coordLocation = m_gl.getAttribLocation(program.getProgram(), "a_position");
+ GLU_CHECK_GLW_MSG(m_gl, "glGetAttribLocation()");
+ TCU_CHECK(m_coordLocation != (glw::GLint)-1);
+
+ // Load the vertex data
+ m_coordinatesBuffer = 0;
+ GLU_CHECK_GLW_CALL(m_gl, genBuffers(1, &m_coordinatesBuffer));
+ GLU_CHECK_GLW_CALL(m_gl, bindBuffer(GL_ARRAY_BUFFER, m_coordinatesBuffer));
+ GLU_CHECK_GLW_CALL(m_gl, bufferData(GL_ARRAY_BUFFER, (glw::GLsizeiptr)sizeof(coords), coords, GL_STATIC_DRAW));
+ GLU_CHECK_GLW_CALL(m_gl, enableVertexAttribArray(m_coordLocation));
+ GLU_CHECK_GLW_CALL(m_gl, vertexAttribPointer(m_coordLocation, 2, GL_FLOAT, GL_FALSE, 0, DE_NULL));
+ }
+
+ // Create dummy data for filling buffer objects
+ const std::vector<tcu::Vec4> refValues(s_numBindings, tcu::Vec4(0.0f, 1.0f, 1.0f, 1.0f));
+ glw::GLenum resType = (m_isUBO) ? GL_UNIFORM_BUFFER : GL_SHADER_STORAGE_BUFFER;
+
+ if (!m_isLocalArray)
+ {
+ // Set up interface block of buffer bindings
+ GLU_CHECK_GLW_CALL(m_gl, genBuffers((glw::GLsizei)m_buffers.size(), &m_buffers[0]));
+
+ for (int bufNdx = 0; bufNdx < (int)m_buffers.size(); ++bufNdx)
+ {
+ GLU_CHECK_GLW_CALL(m_gl, bindBuffer(resType, m_buffers[bufNdx]));
+ GLU_CHECK_GLW_CALL(m_gl, bufferData(resType, sizeof(tcu::Vec4), &(refValues[bufNdx]), GL_STATIC_DRAW));
+ GLU_CHECK_GLW_CALL(m_gl, bindBufferBase(resType, bufNdx, m_buffers[bufNdx]));
+ }
+ }
+}
+
+void ShadersOOB::draw (void)
+{
+ if (m_shaderType == SHADERTYPE_COMPUTE)
+ m_gl.dispatchCompute(1, 1, 1);
+ else
+ {
+ const glw::GLuint indices[] = {0, 1, 2, 2, 3, 0};
+ m_gl.drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, indices);
+ }
+}
+
+void ShadersOOB::teardown (void)
+{
+ if (m_shaderType != SHADERTYPE_COMPUTE)
+ {
+ if (m_coordLocation)
+ {
+ GLU_CHECK_GLW_CALL(m_gl, disableVertexAttribArray(m_coordLocation));
+ m_coordLocation = 0;
+ }
+ }
+
+ if (m_coordinatesBuffer)
+ {
+ GLU_CHECK_GLW_CALL(m_gl, deleteBuffers(1, &m_coordinatesBuffer));
+ m_coordinatesBuffer = 0;
+ }
+
+ if (!m_isLocalArray)
+ {
+ if (!m_buffers.empty())
+ {
+ GLU_CHECK_GLW_CALL(m_gl, deleteBuffers((glw::GLsizei)m_buffers.size(), &m_buffers[0]));
+ m_buffers.clear();
+ }
+ }
+
+ GLU_CHECK_GLW_CALL(m_gl, useProgram(0));
+}
+
+class QueryRobustAccessCase : public RobustnessTestCase
+{
+public:
+ QueryRobustAccessCase (EglTestContext& eglTestCtx, const char* name, const char* description)
+ : RobustnessTestCase (eglTestCtx, name, description) {}
+
+ TestCase::IterateResult iterate (void)
+ {
+ TestLog& log = m_testCtx.getLog();
+
+ log << tcu::TestLog::Message
+ << "Check that after successfully creating a robust context the robust access query returned by glBooleanv() equals GL_TRUE\n\n"
+ << tcu::TestLog::EndMessage;
+
+ const EGLint attribList[] =
+ {
+ EGL_CONTEXT_CLIENT_VERSION, 3,
+ EGL_CONTEXT_MINOR_VERSION_KHR, 1,
+ EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_TRUE,
+ EGL_NONE
+ };
+
+ checkRequiredEGLExtensions(attribList);
+
+ RenderingContext context(m_eglTestCtx, attribList, m_eglConfig, m_eglDisplay, EGL_NO_CONTEXT);
+ context.makeCurrent(m_eglSurface);
+
+ glw::Functions gl;
+ context.initGLFunctions(&gl);
+ checkRequiredGLRobustnessExtension(attribList, gl);
+
+ deUint8 robustAccessGL;
+ gl.getBooleanv(GL_CONTEXT_ROBUST_ACCESS_EXT, &robustAccessGL);
+ GLU_EXPECT_NO_ERROR(gl.getError(), "glGetBooleanv()");
+
+ if (robustAccessGL != GL_TRUE)
+ {
+ log << TestLog::Message
+ << "Invalid GL_CONTEXT_ROBUST_ACCESS returned by glGetBooleanv(). Got '" << robustAccessGL << "' expected GL_TRUE."
+ << TestLog::EndMessage;
+
+ m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+ return STOP;
+ }
+
+ m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+ return STOP;
+ }
+};
+
+class NoResetNotificationCase : public RobustnessTestCase
+{
+public:
+ NoResetNotificationCase (EglTestContext& eglTestCtx, const char* name, const char* description)
+ : RobustnessTestCase (eglTestCtx, name, description) {}
+
+ TestCase::IterateResult iterate (void)
+ {
+ TestLog& log = m_testCtx.getLog();
+
+ log << tcu::TestLog::Message
+ << "Check the reset notification strategy returned by glGetIntegerv() equals GL_NO_RESET_NOTIFICATION\n\n"
+ << tcu::TestLog::EndMessage;
+
+ const EGLint attribList[] =
+ {
+ EGL_CONTEXT_CLIENT_VERSION, 3,
+ EGL_CONTEXT_MINOR_VERSION_KHR, 1,
+ EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_TRUE,
+ EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, EGL_NO_RESET_NOTIFICATION,
+ EGL_NONE
+ };
+
+ checkRequiredEGLExtensions(attribList);
+
+ RenderingContext context(m_eglTestCtx, attribList, m_eglConfig, m_eglDisplay, EGL_NO_CONTEXT);
+ context.makeCurrent(m_eglSurface);
+
+ glw::Functions gl;
+ context.initGLFunctions(&gl);
+ checkRequiredGLRobustnessExtension(attribList, gl);
+
+ deUint8 robustAccessGL;
+ gl.getBooleanv(GL_CONTEXT_ROBUST_ACCESS_EXT, &robustAccessGL);
+ GLU_EXPECT_NO_ERROR(gl.getError(), "glGetBooleanv()");
+
+ glw::GLint reset = 0;
+ gl.getIntegerv(GL_RESET_NOTIFICATION_STRATEGY, &reset);
+ GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv()");
+
+ if (reset != GL_NO_RESET_NOTIFICATION)
+ {
+ log << tcu::TestLog::Message
+ << "Test failed! glGetIntegerv() returned wrong value. [" << glu::getErrorStr(reset) << ", expected " << glu::getErrorStr(GL_NO_RESET_NOTIFICATION) << "]"
+ << tcu::TestLog::EndMessage;
+
+ m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+ return STOP;
+ }
+
+ GLU_CHECK_GLW_CALL(gl, getGraphicsResetStatus());
+
+ m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+ return STOP;
+ }
+};
+
+class LoseContextOnResetCase : public RobustnessTestCase
+{
+public:
+ LoseContextOnResetCase (EglTestContext& eglTestCtx, const char* name, const char* description)
+ : RobustnessTestCase(eglTestCtx, name, description) {}
+
+ TestCase::IterateResult iterate (void)
+ {
+ TestLog& log = m_testCtx.getLog();
+
+ log << tcu::TestLog::Message
+ << "Check the reset notification strategy returned by glGetIntegerv() equals GL_LOSE_CONTEXT_ON_RESET\n\n"
+ << tcu::TestLog::EndMessage;
+
+ const EGLint attribList[] =
+ {
+ EGL_CONTEXT_CLIENT_VERSION, 3,
+ EGL_CONTEXT_MINOR_VERSION_KHR, 1,
+ EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_TRUE,
+ EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, EGL_LOSE_CONTEXT_ON_RESET,
+ EGL_NONE
+ };
+
+ checkRequiredEGLExtensions(attribList);
+
+ RenderingContext context(m_eglTestCtx, attribList, m_eglConfig, m_eglDisplay, EGL_NO_CONTEXT);
+ context.makeCurrent(m_eglSurface);
+
+ glw::Functions gl;
+ context.initGLFunctions(&gl);
+ checkRequiredGLRobustnessExtension(attribList, gl);
+
+ glw::GLint reset = 0;
+ gl.getIntegerv(GL_RESET_NOTIFICATION_STRATEGY, &reset);
+ GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv()");
+
+ if (reset != GL_LOSE_CONTEXT_ON_RESET)
+ {
+ log << tcu::TestLog::Message
+ << "Test failed! glGetIntegerv() returned wrong value. [" << reset << ", expected " << glu::getErrorStr(GL_LOSE_CONTEXT_ON_RESET) << "]"
+ << tcu::TestLog::EndMessage;
+
+ m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+ return STOP;
+ }
+
+ log << tcu::TestLog::Message
+ << "Check the graphics reset status returned by glGetGraphicsResetStatus() "
+ << "equals GL_NO_ERROR\n"
+ << tcu::TestLog::EndMessage;
+
+ GLU_CHECK_GLW_CALL(gl, getGraphicsResetStatus());
+
+ m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+ return STOP;
+ }
+};
+
+de::SharedPtr<ContextReset> contextResetFactory (const RobustnessTestCase::Params params, glw::Functions& gl, tcu::TestLog& log)
+{
+ if (params.getContextResetType() == CONTEXTRESETTYPE_INFINITE_LOOP)
+ return de::SharedPtr<ContextReset>(new InfiniteLoop(gl, log, params.getShaderType()));
+
+ if (params.getContextResetType() == CONTEXTRESETTYPE_FIXED_FUNC_OOB)
+ return de::SharedPtr<ContextReset>(new FixedFunctionOOB(gl, log, params.getFixedFunctionType()));
+
+ if (params.getContextResetType() == CONTEXTRESETTYPE_SHADER_OOB)
+ return de::SharedPtr<ContextReset>(new ShadersOOB(gl, log, params.getShaderType(), params.getResourceType(), params.getReadWriteType()));
+ else
+ {
+ DE_FATAL("Unknown context reset type");
+ return de::SharedPtr<ContextReset>(DE_NULL);
+ }
+}
+
+class ContextResetCase : public RobustnessTestCase
+{
+
+public:
+ ContextResetCase (EglTestContext& eglTestCtx, const char* name, const char* description, Params params);
+ virtual ~ContextResetCase (void) {};
+
+ virtual void provokeReset (de::SharedPtr<ContextReset>& contextReset) = 0;
+ virtual void waitForReset (de::SharedPtr<ContextReset>& contextReset) = 0;
+ virtual void passAndLog (de::SharedPtr<ContextReset>& contextReset) = 0;
+
+ TestCase::IterateResult iterate (void);
+ void execute (glw::Functions& gl);
+
+private:
+ ContextResetCase (const ContextResetCase&);
+ ContextResetCase& operator= (const ContextResetCase&);
+};
+
+ContextResetCase::ContextResetCase (EglTestContext& eglTestCtx, const char* name, const char* description, Params params)
+ : RobustnessTestCase (eglTestCtx, name, description, params) {}
+
+TestCase::IterateResult ContextResetCase::iterate (void)
+{
+ glw::Functions gl;
+
+ const EGLint attribList[] =
+ {
+ EGL_CONTEXT_CLIENT_VERSION, 3,
+ EGL_CONTEXT_MINOR_VERSION_KHR, 1,
+ EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, (m_params.getRobustAccessType() == ROBUSTACCESS_TRUE) ? EGL_TRUE : EGL_FALSE,
+ EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, EGL_LOSE_CONTEXT_ON_RESET,
+ EGL_NONE
+ };
+
+ checkRequiredEGLExtensions(attribList);
+
+ RenderingContext context(m_eglTestCtx, attribList, m_eglConfig, m_eglDisplay, EGL_NO_CONTEXT);
+ context.makeCurrent(m_eglSurface);
+
+ context.initGLFunctions(&gl);
+ checkRequiredGLRobustnessExtension(attribList, gl);
+
+ execute(gl);
+
+ return STOP;
+}
+
+void ContextResetCase::execute (glw::Functions& gl)
+{
+ de::SharedPtr<ContextReset> contextReset = contextResetFactory(m_params, gl, m_testCtx.getLog());
+ glw::GLboolean isContextRobust = GL_FALSE;
+
+ GLU_CHECK_GLW_CALL(gl, getBooleanv(GL_CONTEXT_ROBUST_ACCESS_EXT, &isContextRobust));
+ provokeReset(contextReset);
+
+ if (m_params.getContextResetType() == CONTEXTRESETTYPE_INFINITE_LOOP)
+ {
+ try
+ {
+ waitForReset(contextReset);
+
+ const glw::GLenum status = gl.getGraphicsResetStatus();
+
+ if (status == GL_NO_ERROR)
+ m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Context was NOT lost");
+ else
+ {
+ m_testCtx.getLog() << tcu::TestLog::Message << "glGetGraphicsResetStatus() returned " << glu::getGraphicsResetStatusStr(status) << tcu::TestLog::EndMessage;
+ m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Context was lost");
+ }
+ }
+ catch (const glu::Error& error)
+ {
+ if (error.getError() == GL_CONTEXT_LOST)
+ passAndLog(contextReset);
+ else
+ {
+ m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+
+ m_testCtx.getLog() << tcu::TestLog::Message
+ << "Warning: glGetError() returned wrong value [" << error.what() << ", expected " << glu::getErrorStr(GL_CONTEXT_LOST) << "]"
+ << tcu::TestLog::EndMessage;
+ }
+ }
+ }
+ else if (m_params.getContextResetType() == CONTEXTRESETTYPE_SHADER_OOB || m_params.getContextResetType() == CONTEXTRESETTYPE_FIXED_FUNC_OOB)
+ {
+ try
+ {
+ waitForReset(contextReset);
+ m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Context was NOT lost. Test skipped");
+ }
+ catch (const glu::Error& error)
+ {
+ if (error.getError() == GL_CONTEXT_LOST)
+ {
+ if (isContextRobust)
+ m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "No context reset should of occurred GL_CONTEXT_ROBUST_ACCESS == TRUE");
+ else
+ passAndLog(contextReset);
+ }
+ else if (isContextRobust)
+ m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got unknown error.");
+ else
+ {
+ m_testCtx.setTestResult(QP_TEST_RESULT_QUALITY_WARNING, "Warning: glGetError() returned wrong value. Expected GL_CONTEXT_LOST");
+
+ m_testCtx.getLog() << tcu::TestLog::Message
+ << "Warning: glGetError() returned wrong value [" << error.what() << ", expected " << glu::getErrorStr(GL_CONTEXT_LOST) << "]"
+ << tcu::TestLog::EndMessage;
+ }
+ }
+ }
+ else
+ DE_FATAL("Unknown context reset type");
+}
+
+class BasicResetCase : public ContextResetCase
+{
+public:
+
+ BasicResetCase (EglTestContext& eglTestCtx, const char* name, const char* description, Params params)
+ : ContextResetCase (eglTestCtx, name, description, params) {}
+
+ virtual void provokeReset (de::SharedPtr<ContextReset>& contextReset)
+ {
+ m_testCtx.getLog() << tcu::TestLog::Message
+ << "Check the graphics reset status returned by glGetGraphicsResetStatus() equals "
+ << "GL_GUILTY_CONTEXT_RESET after a context reset\n\n"
+ << tcu::TestLog::EndMessage;
+
+ contextReset->setup();
+ contextReset->draw();
+ }
+
+ virtual void waitForReset (de::SharedPtr<ContextReset>& contextReset)
+ {
+ contextReset->teardown();
+ contextReset->finish();
+ }
+
+ virtual void passAndLog (de::SharedPtr<ContextReset>& contextReset)
+ {
+ const glw::GLint status = contextReset->getGraphicsResetStatus();
+
+ if (status == GL_NO_ERROR)
+ {
+ m_testCtx.getLog() << tcu::TestLog::Message
+ << "Test failed! glGetGraphicsResetStatus() returned wrong value [" << glu::getGraphicsResetStatusStr(status) << ", expected " << glu::getGraphicsResetStatusStr(GL_GUILTY_CONTEXT_RESET) << "]"
+ << tcu::TestLog::EndMessage;
+
+ m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+ }
+ else
+ {
+ if (contextReset->getError() != GL_NO_ERROR)
+ m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Error flag not reset after calling getGraphicsResetStatus()");
+ else
+ m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+ }
+ }
+};
+
+class SyncObjectResetCase : public ContextResetCase
+{
+public:
+ SyncObjectResetCase (EglTestContext& eglTestCtx, const char* name, const char* description, Params params)
+ : ContextResetCase (eglTestCtx, name, description, params) {}
+
+ virtual void provokeReset (de::SharedPtr<ContextReset>& contextReset)
+ {
+ m_testCtx.getLog() << tcu::TestLog::Message
+ << "Check the status of a sync object after a context reset returned by glGetSynciv() equals GL_SIGNALED\n\n"
+ << tcu::TestLog::EndMessage;
+
+ contextReset->setup();
+ contextReset->draw();
+ }
+
+ virtual void waitForReset (de::SharedPtr<ContextReset>& contextReset)
+ {
+ contextReset->createSyncObject();
+ contextReset->teardown();
+ contextReset->finish();
+ }
+
+ virtual void passAndLog (de::SharedPtr<ContextReset>& contextReset)
+ {
+ const glw::GLint status = contextReset->getSyncStatus();
+ if (status != GL_SIGNALED)
+ {
+ m_testCtx.getLog() << tcu::TestLog::Message
+ << "Test failed! glGetSynciv() returned wrong value [" << glu::getErrorStr(status) << ", expected " << glu::getErrorStr(GL_SIGNALED) << "]"
+ << tcu::TestLog::EndMessage;
+
+ m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+ }
+ else
+ m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+ }
+};
+
+class QueryObjectResetCase : public ContextResetCase
+{
+public:
+ QueryObjectResetCase (EglTestContext& eglTestCtx, const char* name, const char* description, Params params)
+ : ContextResetCase (eglTestCtx, name, description, params) {}
+
+ virtual void provokeReset (de::SharedPtr<ContextReset>& contextReset)
+ {
+ m_testCtx.getLog() << tcu::TestLog::Message
+ << "Check the status of a query object after a context reset returned by glGetQueryObjectuiv() equals GL_TRUE\n\n"
+ << tcu::TestLog::EndMessage;
+
+ contextReset->setup();
+ contextReset->beginQuery();
+ contextReset->draw();
+ }
+
+ virtual void waitForReset (de::SharedPtr<ContextReset>& contextReset)
+ {
+ contextReset->endQuery();
+ contextReset->teardown();
+ contextReset->finish();
+ }
+
+ virtual void passAndLog (de::SharedPtr<ContextReset>& contextReset)
+ {
+ const glw::GLuint queryReady = contextReset->getQueryAvailability();
+ if (queryReady != GL_TRUE)
+ {
+ m_testCtx.getLog() << tcu::TestLog::Message
+ << "Test failed! glGetQueryObjectuiv() returned wrong value [" << glu::getErrorStr(queryReady) << ", expected " << glu::getErrorStr(GL_TRUE) << "]"
+ << tcu::TestLog::EndMessage;
+
+ m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+ }
+ else
+ {
+ m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+ }
+ }
+};
+
+class InvalidShareContextCase : public RobustnessTestCase
+{
+public:
+ InvalidShareContextCase (EglTestContext& eglTestCtx, const char* name, const char* description)
+ : RobustnessTestCase (eglTestCtx, name, description) {}
+
+ TestCase::IterateResult iterate (void)
+ {
+ TestLog& log = m_testCtx.getLog();
+ const Library& egl = m_eglTestCtx.getLibrary();
+ bool isOk = true;
+
+ log << tcu::TestLog::Message
+ << "EGL_BAD_MATCH is generated if reset notification strategies do not match when creating shared contexts\n\n"
+ << tcu::TestLog::EndMessage;
+
+ const EGLint attribListA[] =
+ {
+ EGL_CONTEXT_CLIENT_VERSION, 3,
+ EGL_CONTEXT_MINOR_VERSION_KHR, 1,
+ EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_TRUE,
+ EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, EGL_NO_RESET_NOTIFICATION,
+ EGL_NONE
+ };
+
+ const EGLint attribListB[] =
+ {
+ EGL_CONTEXT_CLIENT_VERSION, 3,
+ EGL_CONTEXT_MINOR_VERSION_KHR, 1,
+ EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_TRUE,
+ EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, EGL_LOSE_CONTEXT_ON_RESET,
+ EGL_NONE
+ };
+
+ checkRequiredEGLExtensions(attribListA);
+
+ log << tcu::TestLog::Message << "Create context A (share_context = EGL_NO_CONTEXT)" << tcu::TestLog::EndMessage;
+ RenderingContext contextA(m_eglTestCtx, attribListA, m_eglConfig, m_eglDisplay, EGL_NO_CONTEXT);
+
+ log << tcu::TestLog::Message << "Create context B (share_context = context A)" << tcu::TestLog::EndMessage;
+ logAttribList(m_eglTestCtx, attribListB);
+
+ EGLContext contextB = egl.createContext(m_eglDisplay, m_eglConfig, contextA.getContext(), attribListB);
+
+ const EGLenum error = egl.getError();
+ if (error != EGL_BAD_MATCH)
+ {
+ log << TestLog::Message
+ << "Test failed! eglCreateContext() returned with error [" << eglu::getErrorStr(error) << ", expected " << eglu::getErrorStr(EGL_BAD_MATCH) << "]"
+ << TestLog::EndMessage;
+
+ isOk = false;
+ }
+
+ if (contextB != EGL_NO_CONTEXT)
+ egl.destroyContext(m_eglDisplay, contextB);
+
+ if (isOk)
+ m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+ else
+ m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+
+ return STOP;
+ }
+};
+
+class SharedContextResetCase : public RobustnessTestCase
+{
+public:
+ SharedContextResetCase (EglTestContext& eglTestCtx, const char* name, const char* description, Params params)
+ : RobustnessTestCase (eglTestCtx, name, description, params) {}
+
+ TestCase::IterateResult iterate (void)
+ {
+ TestLog& log = m_testCtx.getLog();
+
+ log << tcu::TestLog::Message
+ << "A reset in one context will result in a reset in all other contexts in its share group\n\n"
+ << tcu::TestLog::EndMessage;
+
+ // Create two share contexts with the same reset notification strategies
+ const EGLint attribListShared[] =
+ {
+ EGL_CONTEXT_CLIENT_VERSION, 3,
+ EGL_CONTEXT_MINOR_VERSION_KHR, 1,
+ EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_TRUE,
+ EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, EGL_LOSE_CONTEXT_ON_RESET,
+ EGL_NONE
+ };
+
+ checkRequiredEGLExtensions(attribListShared);
+
+ log << tcu::TestLog::Message << "Create context A (share_context = EGL_NO_CONTEXT)" << tcu::TestLog::EndMessage;
+ RenderingContext contextA(m_eglTestCtx, attribListShared, m_eglConfig, m_eglDisplay, EGL_NO_CONTEXT);
+
+ log << tcu::TestLog::Message << "Create context B (share_context = context A)" << tcu::TestLog::EndMessage;
+ RenderingContext contextB(m_eglTestCtx, attribListShared, m_eglConfig, m_eglDisplay, contextA.getContext());
+
+ contextA.makeCurrent(m_eglSurface);
+
+ glw::Functions gl;
+ contextA.initGLFunctions(&gl);
+ checkRequiredGLRobustnessExtension(attribListShared, gl);
+
+ DE_ASSERT(m_params.getContextResetType() == CONTEXTRESETTYPE_INFINITE_LOOP);
+ de::UniquePtr<ContextReset> contextReset(new InfiniteLoop(gl, log, m_params.getShaderType()));
+
+ contextReset->setup();
+ contextReset->draw();
+
+ try
+ {
+ contextReset->teardown();
+ contextReset->finish();
+ }
+ catch (const glu::Error& error)
+ {
+ if (error.getError() == GL_CONTEXT_LOST)
+ {
+ contextB.makeCurrent(m_eglSurface);
+
+ contextB.initGLFunctions(&gl);
+ gl.getString(GL_VERSION); // arbitrary gl call
+
+ if (gl.getError() != GL_CONTEXT_LOST)
+ {
+ m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Test failed! glGetError() returned wrong value. Expected GL_CONTEXT_LOST in context B");
+ return STOP;
+ }
+ }
+ else
+ {
+ m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Test failed! glGetError() returned wrong value. Expected GL_CONTEXT_LOST in context A");
+ return STOP;
+ }
+ }
+
+ m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+ return STOP;
+ }
+};
+
+class InvalidContextCase : public RobustnessTestCase
+{
+public:
+ InvalidContextCase (EglTestContext& eglTestCtx, const char* name, const char* description)
+ : RobustnessTestCase (eglTestCtx, name, description) {}
+
+ TestCase::IterateResult iterate (void)
+ {
+ const Library& egl = m_eglTestCtx.getLibrary();
+ TestLog& log = m_testCtx.getLog();
+ bool isOk = true;
+
+ log << tcu::TestLog::Message
+ << "EGL_BAD_ATTRIBUTE is generated if EXT_create_context_robustness is NOT supported but EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT is specified\n\n"
+ << tcu::TestLog::EndMessage;
+
+ const EGLint attribList[] =
+ {
+ EGL_CONTEXT_CLIENT_VERSION, 3,
+ EGL_CONTEXT_MINOR_VERSION_KHR, 1,
+ EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, EGL_LOSE_CONTEXT_ON_RESET,
+ EGL_NONE
+ };
+
+ if (eglu::hasExtension(egl, m_eglDisplay, "EGL_EXT_create_context_robustness"))
+ {
+ m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Test requires EGL_EXT_create_context_robustness to be unsupported");
+ return STOP;
+ }
+
+ logAttribList(m_eglTestCtx, attribList);
+ EGLContext context = egl.createContext(m_eglDisplay, m_eglConfig, EGL_NO_CONTEXT, attribList);
+
+ const EGLenum error = egl.getError();
+ if (error != EGL_BAD_ATTRIBUTE)
+ {
+ log << TestLog::Message
+ << "Test failed! eglCreateContext() returned with error [" << eglu::getErrorStr(error) << ", expected " << eglu::getErrorStr(EGL_BAD_ATTRIBUTE) << "]"
+ << TestLog::EndMessage;
+
+ isOk = false;
+ }
+
+ if (context != EGL_NO_CONTEXT)
+ egl.destroyContext(m_eglDisplay, context);
+
+ if (isOk)
+ m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+ else
+ m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+
+ return STOP;
+ }
+};
+
+class RecoverFromResetCase : public RobustnessTestCase
+{
+public:
+ RecoverFromResetCase (EglTestContext& eglTestCtx, const char* name, const char* description, Params params)
+ : RobustnessTestCase (eglTestCtx, name, description, params) {}
+
+ TestCase::IterateResult iterate (void)
+ {
+ TestLog& log = m_testCtx.getLog();
+
+ log << tcu::TestLog::Message
+ << "Provoke a context reset and wait for glGetGraphicsResetStatus() to return NO_ERROR_KHR.\n"
+ << "Destroy the old context and successfully create a new context.\n\n"
+ << tcu::TestLog::EndMessage;
+
+ const EGLint attribList[] =
+ {
+ EGL_CONTEXT_CLIENT_VERSION, 3,
+ EGL_CONTEXT_MINOR_VERSION_KHR, 1,
+ EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_TRUE,
+ EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, EGL_LOSE_CONTEXT_ON_RESET,
+ EGL_NONE
+ };
+
+ checkRequiredEGLExtensions(attribList);
+
+ log << tcu::TestLog::Message << "Create context A" << tcu::TestLog::EndMessage;
+ RenderingContext contextA(m_eglTestCtx, attribList, m_eglConfig, m_eglDisplay, EGL_NO_CONTEXT);
+ contextA.makeCurrent(m_eglSurface);
+
+ glw::Functions gl;
+ contextA.initGLFunctions(&gl);
+ checkRequiredGLRobustnessExtension(attribList, gl);
+
+ DE_ASSERT(m_params.getContextResetType() == CONTEXTRESETTYPE_INFINITE_LOOP);
+ de::UniquePtr<ContextReset> contextReset(new InfiniteLoop(gl, log, m_params.getShaderType()));
+
+ contextReset->setup();
+ contextReset->draw();
+
+ try
+ {
+ contextReset->teardown();
+ contextReset->finish();
+ }
+ catch (const glu::Error& error)
+ {
+ if (error.getError() == GL_CONTEXT_LOST)
+ {
+ const glw::GLint status = gl.getGraphicsResetStatus();
+ if (status == GL_NO_ERROR)
+ {
+ log << tcu::TestLog::Message
+ << "Test failed! glGetGraphicsResetStatus() returned wrong value [" << glu::getErrorStr(status) << ", expected " << glu::getErrorStr(GL_GUILTY_CONTEXT_RESET) << "]"
+ << tcu::TestLog::EndMessage;
+
+ m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+ return STOP;
+ }
+
+ const int sleepTimeMs = 1000; // (1 second)
+ int timeout = sleepTimeMs * 10; // (10 seconds)
+ int reset_status = -1;
+
+ // wait for context to reset
+ while ((reset_status = gl.getGraphicsResetStatus() != GL_NO_ERROR) && timeout > 0)
+ {
+ deSleep(sleepTimeMs);
+ timeout -= sleepTimeMs;
+ }
+
+ if (reset_status != GL_NO_ERROR)
+ {
+ log << tcu::TestLog::Message
+ << "Test failed! Context did not reset. glGetGraphicsResetStatus() returned wrong value [" << glu::getErrorStr(reset_status) << ", expected " << glu::getErrorStr(GL_NO_ERROR) << "]"
+ << tcu::TestLog::EndMessage;
+
+ m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+ return STOP;
+ }
+ }
+ else
+ {
+ m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Test failed! glGetError() returned wrong value. Expected GL_CONTEXT_LOST in context A");
+ return STOP;
+ }
+ }
+
+ try
+ {
+ log << tcu::TestLog::Message << "Create context B" << tcu::TestLog::EndMessage;
+ RenderingContext contextB(m_eglTestCtx, attribList, m_eglConfig, m_eglDisplay, EGL_NO_CONTEXT);
+ }
+ catch (const glu::Error&)
+ {
+ m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Test failed! Could not create new context. glGetError() returned wrong value. Expected GL_NO_ERROR");
+ return STOP;
+ }
+
+ m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+ return STOP;
+ }
+};
+
+} // anonymous
+
+// Note: Tests limited to openGLES 3.1 contexts only
+TestCaseGroup* createRobustnessTests (EglTestContext& eglTestCtx)
+{
+ de::MovePtr<TestCaseGroup> group (new TestCaseGroup(eglTestCtx, "robustness", "KHR_robustness tests"));
+
+ tcu::TestCaseGroup* const contextCreationTestGroup = new TestCaseGroup(eglTestCtx, "create_context", "Test valid context_creation attributes");
+ tcu::TestCaseGroup* const contextResetTestGroup = new TestCaseGroup(eglTestCtx, "reset_context", "Test context resets scenarios");
+ tcu::TestCaseGroup* const negativeContextTestGroup = new TestCaseGroup(eglTestCtx, "negative_context", "Test invalid context creation attributes");
+
+ tcu::TestCaseGroup* const shadersTestGroup = new TestCaseGroup(eglTestCtx, "shaders", "Shader specific context reset tests");
+ tcu::TestCaseGroup* const fixedFunctionTestGroup = new TestCaseGroup(eglTestCtx, "fixed_function_pipeline", "Fixed function pipeline context reset tests with robust context");
+ tcu::TestCaseGroup* const fixedFunctionNonRobustTestGroup = new TestCaseGroup(eglTestCtx, "fixed_function_pipeline_non_robust", "Fixed function pipeline context reset tests with non-robust context");
+
+ tcu::TestCaseGroup* const infiniteLoopTestGroup = new TestCaseGroup(eglTestCtx, "infinite_loop", "Infinite loop scenarios");
+ tcu::TestCaseGroup* const outOfBoundsTestGroup = new TestCaseGroup(eglTestCtx, "out_of_bounds", "Out of bounds access scenarios with robust context");
+
+ tcu::TestCaseGroup* const outOfBoundsNonRobustTestGroup = new TestCaseGroup(eglTestCtx, "out_of_bounds_non_robust", "Out of bounds access scenarios with non-robust context");
+
+ const string resetScenarioDescription = "query error states and reset notifications";
+ const string syncScenarioDescription = "query sync status with getSynciv()";
+ const string queryScenarioDescription = "check availability of query result with getQueryObjectiv()";
+ const string sharedScenarioDescription = "check reset notification is propagated to shared context";
+ const string recoverScenarioDescription = "delete the old context and create a new one";
+
+ // infinite loop test cases
+ {
+ tcu::TestCaseGroup* const infiniteLoopResetTestGroup = new TestCaseGroup(eglTestCtx, "reset_status", "Tests that query the reset status after a context reset has occurred");
+ tcu::TestCaseGroup* const infiniteLoopSyncTestGroup = new TestCaseGroup(eglTestCtx, "sync_status", "Tests that query the sync status after a context reset has occurred");
+ tcu::TestCaseGroup* const infiniteLoopQueryTestGroup = new TestCaseGroup(eglTestCtx, "query_status", "Tests that query the state of a query object after a context reset has occurred");
+ tcu::TestCaseGroup* const infiniteLoopSharedTestGroup = new TestCaseGroup(eglTestCtx, "shared_context_status", "Tests that query the state of a shared context after a reset has occurred");
+ tcu::TestCaseGroup* const infiniteLoopRecoverTestGroup = new TestCaseGroup(eglTestCtx, "recover_from_reset", "Tests that attempt to create a new context after a context has occurred");
+
+ static const RobustnessTestCase::Params s_infiniteLoopCases[] =
+ {
+ RobustnessTestCase::Params("vertex", "Provoke a context reset in vertex shader and ", CONTEXTRESETTYPE_INFINITE_LOOP, SHADERTYPE_VERT),
+ RobustnessTestCase::Params("fragment", "Provoke a context reset in fragment shader and ", CONTEXTRESETTYPE_INFINITE_LOOP, SHADERTYPE_FRAG),
+ RobustnessTestCase::Params("vertex_and_fragment", "Provoke a context reset in vertex and fragment shader and ", CONTEXTRESETTYPE_INFINITE_LOOP, SHADERTYPE_VERT_AND_FRAG),
+ RobustnessTestCase::Params("compute", "Provoke a context reset in compute shader and ", CONTEXTRESETTYPE_INFINITE_LOOP, SHADERTYPE_COMPUTE),
+ };
+
+ for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(s_infiniteLoopCases); ++testNdx)
+ {
+ const RobustnessTestCase::Params& test = s_infiniteLoopCases[testNdx];
+ infiniteLoopResetTestGroup->addChild (new BasicResetCase (eglTestCtx, test.getName().c_str(), (test.getDescription() + resetScenarioDescription).c_str(), test));
+ infiniteLoopSyncTestGroup->addChild (new SyncObjectResetCase (eglTestCtx, test.getName().c_str(), (test.getDescription() + syncScenarioDescription).c_str(), test));
+ infiniteLoopQueryTestGroup->addChild (new QueryObjectResetCase (eglTestCtx, test.getName().c_str(), (test.getDescription() + queryScenarioDescription).c_str(), test));
+ infiniteLoopSharedTestGroup->addChild (new SharedContextResetCase (eglTestCtx, test.getName().c_str(), (test.getDescription() + sharedScenarioDescription).c_str(), test));
+ infiniteLoopRecoverTestGroup->addChild (new RecoverFromResetCase (eglTestCtx, test.getName().c_str(), (test.getDescription() + recoverScenarioDescription).c_str(), test));
+ }
+
+ infiniteLoopTestGroup->addChild(infiniteLoopResetTestGroup);
+ infiniteLoopTestGroup->addChild(infiniteLoopSyncTestGroup);
+ infiniteLoopTestGroup->addChild(infiniteLoopQueryTestGroup);
+ infiniteLoopTestGroup->addChild(infiniteLoopSharedTestGroup);
+ infiniteLoopTestGroup->addChild(infiniteLoopRecoverTestGroup);
+ }
+
+ // out-of-bounds test cases
+ {
+ // robust context
+ tcu::TestCaseGroup* const uboReadArrayResetTestGroup = new TestCaseGroup(eglTestCtx, "uniform_block", "Uniform Block Accesses");
+ tcu::TestCaseGroup* const uboWriteArrayResetTestGroup = new TestCaseGroup(eglTestCtx, "uniform_block", "Uniform Block Accesses");
+ tcu::TestCaseGroup* const ssboWriteArrayResetTestGroup = new TestCaseGroup(eglTestCtx, "shader_storage_block", "Shader Storage Block accesses");
+ tcu::TestCaseGroup* const ssboReadArrayResetTestGroup = new TestCaseGroup(eglTestCtx, "shader_storage_block", "Shader Storage Block accesses");
+ tcu::TestCaseGroup* const localWriteArrayResetTestGroup = new TestCaseGroup(eglTestCtx, "local_array", "Local array accesses");
+ tcu::TestCaseGroup* const localReadArrayResetTestGroup = new TestCaseGroup(eglTestCtx, "local_array", "Local array accesses");
+
+ // non-robust context (internal use only)
+ tcu::TestCaseGroup* const uboReadArrayResetNonRobustTestGroup = new TestCaseGroup(eglTestCtx, "uniform_block", "Uniform Block Accesses");
+ tcu::TestCaseGroup* const uboWriteArrayResetNonRobustTestGroup = new TestCaseGroup(eglTestCtx, "uniform_block", "Uniform Block Accesses");
+ tcu::TestCaseGroup* const ssboWriteArrayResetNonRobustTestGroup = new TestCaseGroup(eglTestCtx, "shader_storage_block", "Shader Storage Block accesses");
+ tcu::TestCaseGroup* const ssboReadArrayResetNonRobustTestGroup = new TestCaseGroup(eglTestCtx, "shader_storage_block", "Shader Storage Block accesses");
+ tcu::TestCaseGroup* const localWriteArrayResetNonRobustTestGroup = new TestCaseGroup(eglTestCtx, "local_array", "Local array accesses");
+ tcu::TestCaseGroup* const localReadArrayResetNonRobustTestGroup = new TestCaseGroup(eglTestCtx, "local_array", "Local array accesses");
+
+ static const RobustnessTestCase::Params s_outOfBoundReadCases[] =
+ {
+ // ubo read only
+ RobustnessTestCase::Params ("vertex", "Provoke a context reset in vertex shader and ", ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT, RESOURCETYPE_UBO, READWRITETYPE_READ),
+ RobustnessTestCase::Params ("fragment", "Provoke a context reset in fragment shader and ", ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_FRAG, RESOURCETYPE_UBO, READWRITETYPE_READ),
+ RobustnessTestCase::Params ("vertex_and_fragment", "Provoke a context reset in vertex and fragment shader and ", ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT_AND_FRAG, RESOURCETYPE_UBO, READWRITETYPE_READ),
+ RobustnessTestCase::Params ("compute", "Provoke a context reset in compute shader and ", ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_COMPUTE, RESOURCETYPE_UBO, READWRITETYPE_READ),
+
+ // ssbo read only
+ RobustnessTestCase::Params ("vertex", "Provoke a context reset in vertex shader and ", ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT, RESOURCETYPE_SSBO, READWRITETYPE_READ),
+ RobustnessTestCase::Params ("fragment", "Provoke a context reset in fragment shader and ", ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_FRAG, RESOURCETYPE_SSBO, READWRITETYPE_READ),
+ RobustnessTestCase::Params ("vertex_and_fragment", "Provoke a context reset in vertex and fragment shader and ", ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT_AND_FRAG, RESOURCETYPE_SSBO, READWRITETYPE_READ),
+ RobustnessTestCase::Params ("compute", "Provoke a context reset in compute shader and ", ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_COMPUTE, RESOURCETYPE_SSBO, READWRITETYPE_READ),
+
+ // local array read only
+ RobustnessTestCase::Params ("vertex", "Provoke a context reset in vertex shader and ", ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT, RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_READ),
+ RobustnessTestCase::Params ("fragment", "Provoke a context reset in fragment shader and ", ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_FRAG, RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_READ),
+ RobustnessTestCase::Params ("vertex_and_fragment", "Provoke a context reset in vertex and fragment shader and ", ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT_AND_FRAG, RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_READ),
+ RobustnessTestCase::Params ("compute", "Provoke a context reset in compute shader and ", ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_COMPUTE, RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_READ),
+
+ // ubo read only (non-robust)
+ RobustnessTestCase::Params ("vertex", "Provoke a context reset in vertex shader and ", ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT, RESOURCETYPE_UBO, READWRITETYPE_READ),
+ RobustnessTestCase::Params ("fragment", "Provoke a context reset in fragment shader and ", ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_FRAG, RESOURCETYPE_UBO, READWRITETYPE_READ),
+ RobustnessTestCase::Params ("vertex_and_fragment", "Provoke a context reset in vertex and fragment shader and ", ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT_AND_FRAG, RESOURCETYPE_UBO, READWRITETYPE_READ),
+ RobustnessTestCase::Params ("compute", "Provoke a context reset in compute shader and ", ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_COMPUTE, RESOURCETYPE_UBO, READWRITETYPE_READ),
+
+ // ssbo read only (non-robust)
+ RobustnessTestCase::Params ("vertex", "Provoke a context reset in vertex shader and ", ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT, RESOURCETYPE_SSBO, READWRITETYPE_READ),
+ RobustnessTestCase::Params ("fragment", "Provoke a context reset in fragment shader and ", ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_FRAG, RESOURCETYPE_SSBO, READWRITETYPE_READ),
+ RobustnessTestCase::Params ("vertex_and_fragment", "Provoke a context reset in vertex and fragment shader and ", ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT_AND_FRAG, RESOURCETYPE_SSBO, READWRITETYPE_READ),
+ RobustnessTestCase::Params ("compute", "Provoke a context reset in compute shader and ", ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_COMPUTE, RESOURCETYPE_SSBO, READWRITETYPE_READ),
+
+ // local array read only (non-robust)
+ RobustnessTestCase::Params ("vertex", "Provoke a context reset in vertex shader and ", ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT, RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_READ),
+ RobustnessTestCase::Params ("fragment", "Provoke a context reset in fragment shader and ", ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_FRAG, RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_READ),
+ RobustnessTestCase::Params ("vertex_and_fragment", "Provoke a context reset in vertex and fragment shader and ", ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT_AND_FRAG, RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_READ),
+ RobustnessTestCase::Params ("compute", "Provoke a context reset in compute shader and ", ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_COMPUTE, RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_READ),
+ };
+
+ for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(s_outOfBoundReadCases); ++testNdx)
+ {
+ const RobustnessTestCase::Params& test = s_outOfBoundReadCases[testNdx];
+
+ if (test.getResourceType() == RESOURCETYPE_UBO && test.getRobustAccessType() == ROBUSTACCESS_TRUE)
+ uboReadArrayResetTestGroup->addChild (new BasicResetCase(eglTestCtx, test.getName().c_str(), (test.getDescription() + resetScenarioDescription).c_str(), test));
+
+ if (test.getResourceType() == RESOURCETYPE_UBO && test.getRobustAccessType() == ROBUSTACCESS_FALSE)
+ uboReadArrayResetNonRobustTestGroup->addChild (new BasicResetCase(eglTestCtx, test.getName().c_str(), (test.getDescription() + resetScenarioDescription).c_str(), test));
+
+ if (test.getResourceType() == RESOURCETYPE_SSBO && test.getRobustAccessType() == ROBUSTACCESS_TRUE)
+ ssboReadArrayResetTestGroup->addChild (new BasicResetCase(eglTestCtx, test.getName().c_str(), (test.getDescription() + resetScenarioDescription).c_str(), test));
+
+ if (test.getResourceType() == RESOURCETYPE_SSBO && test.getRobustAccessType() == ROBUSTACCESS_FALSE)
+ ssboReadArrayResetNonRobustTestGroup->addChild (new BasicResetCase(eglTestCtx, test.getName().c_str(), (test.getDescription() + resetScenarioDescription).c_str(), test));
+
+ if (test.getResourceType() == RESOURCETYPE_LOCAL_ARRAY && test.getRobustAccessType() == ROBUSTACCESS_TRUE)
+ localReadArrayResetTestGroup->addChild (new BasicResetCase(eglTestCtx, test.getName().c_str(), (test.getDescription() + resetScenarioDescription).c_str(), test));
+
+ if (test.getResourceType() == RESOURCETYPE_LOCAL_ARRAY && test.getRobustAccessType() == ROBUSTACCESS_FALSE)
+ localReadArrayResetNonRobustTestGroup->addChild (new BasicResetCase(eglTestCtx, test.getName().c_str(), (test.getDescription() + resetScenarioDescription).c_str(), test));
+ }
+
+ static const RobustnessTestCase::Params s_outOfBoundWriteCases[] =
+ {
+ // ubo write only
+ RobustnessTestCase::Params ("vertex", "Provoke a context reset in vertex shader and ", ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT, RESOURCETYPE_UBO, READWRITETYPE_WRITE),
+ RobustnessTestCase::Params ("fragment", "Provoke a context reset in fragment shader and ", ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_FRAG, RESOURCETYPE_UBO, READWRITETYPE_WRITE),
+ RobustnessTestCase::Params ("vertex_and_fragment", "Provoke a context reset in vertex and fragment shader and ", ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT_AND_FRAG, RESOURCETYPE_UBO, READWRITETYPE_WRITE),
+ RobustnessTestCase::Params ("compute", "Provoke a context reset in compute shader and ", ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_COMPUTE, RESOURCETYPE_UBO, READWRITETYPE_WRITE),
+
+ // ssbo write only
+ RobustnessTestCase::Params ("vertex", "Provoke a context reset in vertex shader and ", ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT, RESOURCETYPE_SSBO, READWRITETYPE_WRITE),
+ RobustnessTestCase::Params ("fragment", "Provoke a context reset in fragment shader and ", ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_FRAG, RESOURCETYPE_SSBO, READWRITETYPE_WRITE),
+ RobustnessTestCase::Params ("vertex_and_fragment", "Provoke a context reset in vertex and fragment shader and ", ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT_AND_FRAG, RESOURCETYPE_SSBO, READWRITETYPE_WRITE),
+ RobustnessTestCase::Params ("compute", "Provoke a context reset in compute shader and ", ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_COMPUTE, RESOURCETYPE_SSBO, READWRITETYPE_WRITE),
+
+ // local array write only
+ RobustnessTestCase::Params ("vertex", "Provoke a context reset in vertex shader and ", ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT, RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_WRITE),
+ RobustnessTestCase::Params ("fragment", "Provoke a context reset in fragment shader and ", ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_FRAG, RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_WRITE),
+ RobustnessTestCase::Params ("vertex_and_fragment", "Provoke a context reset in vertex and fragment shader and ", ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT_AND_FRAG, RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_WRITE),
+ RobustnessTestCase::Params ("compute", "Provoke a context reset in compute shader and ", ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_COMPUTE, RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_WRITE),
+
+ // ubo write only (non-robust)
+ RobustnessTestCase::Params ("vertex", "Provoke a context reset in vertex shader and ", ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT, RESOURCETYPE_UBO, READWRITETYPE_WRITE),
+ RobustnessTestCase::Params ("fragment", "Provoke a context reset in fragment shader and ", ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_FRAG, RESOURCETYPE_UBO, READWRITETYPE_WRITE),
+ RobustnessTestCase::Params ("vertex_and_fragment", "Provoke a context reset in vertex and fragment shader and ", ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT_AND_FRAG, RESOURCETYPE_UBO, READWRITETYPE_WRITE),
+ RobustnessTestCase::Params ("compute", "Provoke a context reset in compute shader and ", ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_COMPUTE, RESOURCETYPE_UBO, READWRITETYPE_WRITE),
+
+ // ssbo write only (non-robust)
+ RobustnessTestCase::Params ("vertex", "Provoke a context reset in vertex shader and ", ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT, RESOURCETYPE_SSBO, READWRITETYPE_WRITE),
+ RobustnessTestCase::Params ("fragment", "Provoke a context reset in fragment shader and ", ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_FRAG, RESOURCETYPE_SSBO, READWRITETYPE_WRITE),
+ RobustnessTestCase::Params ("vertex_and_fragment", "Provoke a context reset in vertex and fragment shader and ", ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT_AND_FRAG, RESOURCETYPE_SSBO, READWRITETYPE_WRITE),
+ RobustnessTestCase::Params ("compute", "Provoke a context reset in compute shader and ", ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_COMPUTE, RESOURCETYPE_SSBO, READWRITETYPE_WRITE),
+
+ // local array write only (non-robust)
+ RobustnessTestCase::Params ("vertex", "Provoke a context reset in vertex shader and ", ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT, RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_WRITE),
+ RobustnessTestCase::Params ("fragment", "Provoke a context reset in fragment shader and ", ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_FRAG, RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_WRITE),
+ RobustnessTestCase::Params ("vertex_and_fragment", "Provoke a context reset in vertex and fragment shader and ", ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT_AND_FRAG, RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_WRITE),
+ RobustnessTestCase::Params ("compute", "Provoke a context reset in compute shader and ", ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_COMPUTE, RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_WRITE),
+ };
+
+ for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(s_outOfBoundWriteCases); ++testNdx)
+ {
+ const RobustnessTestCase::Params& test = s_outOfBoundWriteCases[testNdx];
+
+ if (test.getResourceType() == RESOURCETYPE_UBO && test.getRobustAccessType() == ROBUSTACCESS_TRUE)
+ uboWriteArrayResetTestGroup->addChild (new BasicResetCase(eglTestCtx, test.getName().c_str(), (test.getDescription() + resetScenarioDescription).c_str(), test));
+
+ if (test.getResourceType() == RESOURCETYPE_UBO && test.getRobustAccessType() == ROBUSTACCESS_FALSE)
+ uboWriteArrayResetNonRobustTestGroup->addChild (new BasicResetCase(eglTestCtx, test.getName().c_str(), (test.getDescription() + resetScenarioDescription).c_str(), test));
+
+ if (test.getResourceType() == RESOURCETYPE_SSBO && test.getRobustAccessType() == ROBUSTACCESS_TRUE)
+ ssboWriteArrayResetTestGroup->addChild (new BasicResetCase(eglTestCtx, test.getName().c_str(), (test.getDescription() + resetScenarioDescription).c_str(), test));
+
+ if (test.getResourceType() == RESOURCETYPE_SSBO && test.getRobustAccessType() == ROBUSTACCESS_FALSE)
+ ssboWriteArrayResetNonRobustTestGroup->addChild (new BasicResetCase(eglTestCtx, test.getName().c_str(), (test.getDescription() + resetScenarioDescription).c_str(), test));
+
+ if (test.getResourceType() == RESOURCETYPE_LOCAL_ARRAY && test.getRobustAccessType() == ROBUSTACCESS_TRUE)
+ localWriteArrayResetTestGroup->addChild (new BasicResetCase(eglTestCtx, test.getName().c_str(), (test.getDescription() + resetScenarioDescription).c_str(), test));
+
+ if (test.getResourceType() == RESOURCETYPE_LOCAL_ARRAY && test.getRobustAccessType() == ROBUSTACCESS_FALSE)
+ localWriteArrayResetNonRobustTestGroup->addChild (new BasicResetCase(eglTestCtx, test.getName().c_str(), (test.getDescription() + resetScenarioDescription).c_str(), test));
+ }
+
+ // robust Context
+ tcu::TestCaseGroup* const outOfBoundsResetReadAccessTestGroup = new TestCaseGroup(eglTestCtx, "reads", "Out of bounds read accesses");
+ tcu::TestCaseGroup* const outOfBoundsResetWriteAccessTestGroup = new TestCaseGroup(eglTestCtx, "writes", "Out of bounds write accesses");
+
+ outOfBoundsResetReadAccessTestGroup->addChild(uboReadArrayResetTestGroup);
+ outOfBoundsResetReadAccessTestGroup->addChild(ssboReadArrayResetTestGroup);
+ outOfBoundsResetReadAccessTestGroup->addChild(localReadArrayResetTestGroup);
+
+ outOfBoundsResetWriteAccessTestGroup->addChild(uboWriteArrayResetTestGroup);
+ outOfBoundsResetWriteAccessTestGroup->addChild(ssboWriteArrayResetTestGroup);
+ outOfBoundsResetWriteAccessTestGroup->addChild(localWriteArrayResetTestGroup);
+
+ tcu::TestCaseGroup* const outOfBoundsResetTestGroup = new TestCaseGroup(eglTestCtx, "reset_status", "Tests that query the reset status after a context reset has occurred");
+
+ outOfBoundsResetTestGroup->addChild(outOfBoundsResetReadAccessTestGroup);
+ outOfBoundsResetTestGroup->addChild(outOfBoundsResetWriteAccessTestGroup);
+
+ outOfBoundsTestGroup->addChild(outOfBoundsResetTestGroup);
+
+ // non-robust Context (internal use only)
+ tcu::TestCaseGroup* const outOfBoundsResetReadAccessNonRobustTestGroup = new TestCaseGroup(eglTestCtx, "reads", "Out of bounds read accesses");
+ tcu::TestCaseGroup* const outOfBoundsResetWriteAccessNonRobustTestGroup = new TestCaseGroup(eglTestCtx, "writes", "Out of bounds write accesses");
+
+ outOfBoundsResetReadAccessNonRobustTestGroup->addChild(uboReadArrayResetNonRobustTestGroup);
+ outOfBoundsResetReadAccessNonRobustTestGroup->addChild(ssboReadArrayResetNonRobustTestGroup);
+ outOfBoundsResetReadAccessNonRobustTestGroup->addChild(localReadArrayResetNonRobustTestGroup);
+
+ outOfBoundsResetWriteAccessNonRobustTestGroup->addChild(uboWriteArrayResetNonRobustTestGroup);
+ outOfBoundsResetWriteAccessNonRobustTestGroup->addChild(ssboWriteArrayResetNonRobustTestGroup);
+ outOfBoundsResetWriteAccessNonRobustTestGroup->addChild(localWriteArrayResetNonRobustTestGroup);
+
+ tcu::TestCaseGroup* const outOfBoundsResetNonRobustTestGroup = new TestCaseGroup(eglTestCtx, "reset_status", "Tests that query the reset status after a context reset has occurred");
+
+ outOfBoundsResetNonRobustTestGroup->addChild(outOfBoundsResetReadAccessNonRobustTestGroup);
+ outOfBoundsResetNonRobustTestGroup->addChild(outOfBoundsResetWriteAccessNonRobustTestGroup);
+
+ outOfBoundsNonRobustTestGroup->addChild(outOfBoundsResetNonRobustTestGroup);
+ }
+
+ // fixed function test cases
+ {
+ // robust context
+ tcu::TestCaseGroup* const fixedFunctionResetStatusTestGroup = new TestCaseGroup(eglTestCtx, "reset_status", "Tests that query the reset status after a context reset has occurred");
+
+ // non-robust context (internal use only)
+ tcu::TestCaseGroup* const fixedFunctionResetStatusNonRobustTestGroup = new TestCaseGroup(eglTestCtx, "reset_status", "Tests that query the reset status after a context reset has occurred");
+
+ static const RobustnessTestCase::Params s_fixedFunctionPipelineCases[] =
+ {
+ RobustnessTestCase::Params( "index_buffer_out_of_bounds", "Provoke context reset and query error states and reset notifications", ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_FIXED_FUNC_OOB, FIXEDFUNCTIONTYPE_INDICES),
+ RobustnessTestCase::Params( "vertex_buffer_out_of_bounds", "Provoke context reset and query error states and reset notifications", ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_FIXED_FUNC_OOB, FIXEDFUNCTIONTYPE_VERTICES),
+
+ RobustnessTestCase::Params( "index_buffer_out_of_bounds", "Provoke context reset and query error states and reset notifications", ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_FIXED_FUNC_OOB, FIXEDFUNCTIONTYPE_INDICES),
+ RobustnessTestCase::Params( "vertex_buffer_out_of_bounds", "Provoke context reset and query error states and reset notifications", ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_FIXED_FUNC_OOB, FIXEDFUNCTIONTYPE_VERTICES),
+ };
+
+ for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(s_fixedFunctionPipelineCases); ++testNdx)
+ {
+ const RobustnessTestCase::Params& test = s_fixedFunctionPipelineCases[testNdx];
+ if (test.getRobustAccessType() == ROBUSTACCESS_TRUE)
+ fixedFunctionResetStatusTestGroup->addChild(new BasicResetCase(eglTestCtx, test.getName().c_str(), test.getDescription().c_str(), test));
+ else
+ fixedFunctionResetStatusNonRobustTestGroup->addChild(new BasicResetCase(eglTestCtx, test.getName().c_str(), test.getDescription().c_str(), test));
+ }
+
+ fixedFunctionTestGroup->addChild(fixedFunctionResetStatusTestGroup);
+ fixedFunctionNonRobustTestGroup->addChild(fixedFunctionResetStatusNonRobustTestGroup);
+ }
+
+ // context creation query cases
+ {
+ contextCreationTestGroup->addChild(new QueryRobustAccessCase (eglTestCtx, "query_robust_access", "Query robust access after successfully creating a robust context"));
+ contextCreationTestGroup->addChild(new NoResetNotificationCase (eglTestCtx, "no_reset_notification", "Query reset notification strategy after specifying GL_NO_RESET_NOTIFICATION"));
+ contextCreationTestGroup->addChild(new LoseContextOnResetCase (eglTestCtx, "lose_context_on_reset", "Query reset notification strategy after specifying GL_LOSE_CONTEXT_ON_RESET"));
+ }
+
+ // invalid context creation cases
+ {
+ negativeContextTestGroup->addChild(new InvalidContextCase (eglTestCtx, "invalid_robust_context_creation", "Create a non-robust context but specify a reset notification strategy"));
+ negativeContextTestGroup->addChild(new InvalidShareContextCase (eglTestCtx, "invalid_robust_shared_context_creation", "Create a context share group with conflicting reset notification strategies"));
+ }
+
+ shadersTestGroup->addChild(infiniteLoopTestGroup);
+ shadersTestGroup->addChild(outOfBoundsTestGroup);
+ shadersTestGroup->addChild(outOfBoundsNonRobustTestGroup);
+
+ contextResetTestGroup->addChild(shadersTestGroup);
+ contextResetTestGroup->addChild(fixedFunctionTestGroup);
+ contextResetTestGroup->addChild(fixedFunctionNonRobustTestGroup);
+
+ group->addChild(contextCreationTestGroup);
+ group->addChild(contextResetTestGroup);
+ group->addChild(negativeContextTestGroup);
+
+ return group.release();
+}
+
+} // egl
+} // deqp
--- /dev/null
+#ifndef _TEGLROBUSTNESSTESTS_HPP
+#define _TEGLROBUSTNESSTESTS_HPP
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program EGL Module
+ * ---------------------------------------
+ *
+ * Copyright 2017 The Android Open Source Project
+ *
+ * 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.
+ *
+ *//*!
+ * \file
+ * \brief Robustness tests for KHR_robustness
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "teglTestCase.hpp"
+
+namespace deqp
+{
+namespace egl
+{
+
+TestCaseGroup* createRobustnessTests (EglTestContext& eglTestCtx);
+
+} // egl
+} // deqp
+
+#endif // _TEGLROBUSTNESSTESTS_HPP
return c.get(EGL_CONFIG_CAVEAT) != EGL_NON_CONFORMANT_CONFIG;
}
+static bool notFloat (const eglu::CandidateConfig& c)
+{
+ return c.colorComponentType() != EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT;
+}
+
void getDefaultFilterLists (vector<NamedFilterList>& lists, const FilterList& baseFilters)
{
static const struct
<< notColorBits<4, 4, 4, 4>
<< notColorBits<5, 5, 5, 1>
<< notColorBits<8, 8, 8, 8>
- << isConformant;
+ << isConformant
+ << notFloat;
lists.push_back(filters);
}
#include "teglMultiContextTests.hpp"
#include "teglThreadCleanUpTests.hpp"
#include "teglMutableRenderBufferTests.hpp"
+#include "teglGetFrameTimestampsTests.hpp"
+#include "teglRobustnessTests.hpp"
namespace deqp
{
addChild(createMultiContextTests (m_eglTestCtx));
addChild(createThreadCleanUpTest (m_eglTestCtx));
addChild(new MutableRenderBufferTests (m_eglTestCtx));
+ addChild(createGetFrameTimestampsTests (m_eglTestCtx));
+ addChild(createRobustnessTests (m_eglTestCtx));
}
};
translateCommand(testCmd, refTestCmd, m_renderTarget);
// Base clears.
- renderReference(m_baseClears, m_refColorBuffer->getAccess(), m_refStencilBuffer->getAccess(), m_renderTarget.depthBits);
+ renderReference(m_baseClears, m_refColorBuffer->getAccess(), m_refStencilBuffer->getAccess(), m_renderTarget.stencilBits);
// Base depths.
for (vector<RefRenderCommand>::const_iterator cmd = m_refBaseDepthRenders.begin(); cmd != m_refBaseDepthRenders.end(); ++cmd)
de::Random rnd(0xabcdef);
GLint maxViewportDimensions[2] = {0};
+ GLfloat viewportBoundsRange[2] = {0.0f};
+ GLboolean hasViewportArray = false;
glGetIntegerv(GL_MAX_VIEWPORT_DIMS, maxViewportDimensions);
+ hasViewportArray = m_context.getContextInfo().isExtensionSupported("GL_OES_viewport_array") ||
+ m_context.getContextInfo().isExtensionSupported("GL_NV_viewport_array");
+ if (hasViewportArray)
+ {
+ glGetFloatv(GL_VIEWPORT_BOUNDS_RANGE, viewportBoundsRange);
+ }
// verify initial value of first two values
m_verifier->verifyInteger4(m_testCtx, GL_VIEWPORT, 0, 0, m_context.getRenderTarget().getWidth(), m_context.getRenderTarget().getHeight());
GLsizei height = rnd.getInt(0, maxViewportDimensions[1]);
glViewport(x, y, width, height);
- m_verifier->verifyInteger4(m_testCtx, GL_VIEWPORT, x, y, width, height);
+
+ if (hasViewportArray)
+ {
+ m_verifier->verifyInteger4(m_testCtx, GL_VIEWPORT,
+ de::clamp(x, deFloorFloatToInt32(viewportBoundsRange[0]), deFloorFloatToInt32(viewportBoundsRange[1])),
+ de::clamp(y, deFloorFloatToInt32(viewportBoundsRange[0]), deFloorFloatToInt32(viewportBoundsRange[1])),
+ width, height);
+ }
+ else
+ {
+ m_verifier->verifyInteger4(m_testCtx, GL_VIEWPORT, x, y, width, height);
+ }
+
expectError(GL_NO_ERROR);
}
}
retVal.x() = rnd.getFloat(-1, 1);
retVal.y() = rnd.getFloat(-1, 1);
- retVal.z() = rnd.getFloat(-0.9f, 0.9f);
+ retVal.z() = 0.5f;
retVal.w() = 1.0f + rnd.getFloat();
return retVal;
// Create texture and render.
- glu::Texture2D texture (renderCtx, m_context.getContextInfo(), 1, &compressed, tcu::TexDecompressionParams((m_renderer->getASTCSupport() == ASTCSUPPORTLEVEL_LDR ? tcu::TexDecompressionParams::ASTCMODE_LDR : tcu::TexDecompressionParams::ASTCMODE_HDR)));
- Surface renderedFrame (imageWidth, imageHeight);
- Surface referenceFrame (imageWidth, imageHeight);
+ const tcu::TexDecompressionParams::AstcMode decompressionMode = (m_renderer->getASTCSupport() == ASTCSUPPORTLEVEL_LDR || tcu::isAstcSRGBFormat(m_format))
+ ? tcu::TexDecompressionParams::ASTCMODE_LDR
+ : tcu::TexDecompressionParams::ASTCMODE_HDR;
+ glu::Texture2D texture (renderCtx, m_context.getContextInfo(), 1, &compressed, tcu::TexDecompressionParams(decompressionMode));
+ Surface renderedFrame (imageWidth, imageHeight);
+ Surface referenceFrame (imageWidth, imageHeight);
m_renderer->render(referenceFrame, renderedFrame, texture, getUncompressedFormat(compressed.getFormat()));
// Create texture and render.
- Surface renderedFrame (imageWidth, imageHeight);
- Surface referenceFrame (imageWidth, imageHeight);
- glu::Texture2D texture (renderCtx, m_context.getContextInfo(), 1, &compressed, tcu::TexDecompressionParams(m_renderer->getASTCSupport() == ASTCSUPPORTLEVEL_LDR ? tcu::TexDecompressionParams::ASTCMODE_LDR : tcu::TexDecompressionParams::ASTCMODE_HDR));
+ const tcu::TexDecompressionParams::AstcMode decompressionMode = (m_renderer->getASTCSupport() == ASTCSUPPORTLEVEL_LDR || tcu::isAstcSRGBFormat(m_format))
+ ? tcu::TexDecompressionParams::ASTCMODE_LDR
+ : tcu::TexDecompressionParams::ASTCMODE_HDR;
+ Surface renderedFrame (imageWidth, imageHeight);
+ Surface referenceFrame (imageWidth, imageHeight);
+ glu::Texture2D texture (renderCtx, m_context.getContextInfo(), 1, &compressed, tcu::TexDecompressionParams(decompressionMode));
m_renderer->render(referenceFrame, renderedFrame, texture, getUncompressedFormat(compressed.getFormat()));
translateCommand(testCmd, refTestCmd, m_renderTarget);
// Base clears.
- renderReference(m_baseClears, m_refColorBuffer->getAccess(), m_refStencilBuffer->getAccess(), m_renderTarget.depthBits);
+ renderReference(m_baseClears, m_refColorBuffer->getAccess(), m_refStencilBuffer->getAccess(), m_renderTarget.stencilBits);
// Base depths.
for (vector<RefRenderCommand>::const_iterator cmd = m_refBaseDepthRenders.begin(); cmd != m_refBaseDepthRenders.end(); ++cmd)
de::Random rnd(0xabcdef);
GLint maxViewportDimensions[2] = {0};
+ GLfloat viewportBoundsRange[2] = {0.0f};
+ GLboolean hasViewportArray = false;
glGetIntegerv(GL_MAX_VIEWPORT_DIMS, maxViewportDimensions);
+ hasViewportArray = m_context.getContextInfo().isExtensionSupported("GL_OES_viewport_array") ||
+ m_context.getContextInfo().isExtensionSupported("GL_NV_viewport_array");
+ if (hasViewportArray)
+ {
+ glGetFloatv(GL_VIEWPORT_BOUNDS_RANGE, viewportBoundsRange);
+ }
// verify initial value of first two values
m_verifier->verifyInteger4(m_testCtx, GL_VIEWPORT, 0, 0, m_context.getRenderTarget().getWidth(), m_context.getRenderTarget().getHeight());
GLsizei height = rnd.getInt(0, maxViewportDimensions[1]);
glViewport(x, y, width, height);
- m_verifier->verifyInteger4(m_testCtx, GL_VIEWPORT, x, y, width, height);
+
+ if (hasViewportArray)
+ {
+ m_verifier->verifyInteger4(m_testCtx, GL_VIEWPORT,
+ de::clamp(x, deFloorFloatToInt32(viewportBoundsRange[0]), deFloorFloatToInt32(viewportBoundsRange[1])),
+ de::clamp(y, deFloorFloatToInt32(viewportBoundsRange[0]), deFloorFloatToInt32(viewportBoundsRange[1])),
+ width, height);
+ }
+ else
+ {
+ m_verifier->verifyInteger4(m_testCtx, GL_VIEWPORT, x, y, width, height);
+ }
+
expectError(GL_NO_ERROR);
}
}
m_log << TestLog::EndSection;
m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if target is GL_TEXTURE_3D and format is GL_DEPTH_COMPONENT, or GL_DEPTH_STENCIL.");
- glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 1, 1, 1, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_BYTE, 0);
+ glTexImage3D(GL_TEXTURE_3D, 0, GL_DEPTH_STENCIL, 1, 1, 1, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 0);
expectError(GL_INVALID_OPERATION);
- glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 1, 1, 1, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
+ glTexImage3D(GL_TEXTURE_3D, 0, GL_DEPTH_COMPONENT, 1, 1, 1, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
expectError(GL_INVALID_OPERATION);
m_log << TestLog::EndSection;
retVal.x() = rnd.getFloat(-1, 1);
retVal.y() = rnd.getFloat(-1, 1);
- retVal.z() = rnd.getFloat(-0.9f, 0.9f);
+ retVal.z() = 0.5f;
retVal.w() = 1.0f + rnd.getFloat();
return retVal;
IterateResult iterate (void);
protected:
- bool compare (float in0, float in1, double reference, float result)
-#if (DE_COMPILER == DE_COMPILER_GCC) && (DE_CPU == DE_CPU_ARM_64)
-# if (__GNUC__ == 4) && (__GNUC_MINOR__ == 9) && (__GNUC_PATCHLEVEL__ == 0)
- // Some prerelease GCC 4.9 versions have a bug in shift right when
- // targeting ARMv8.
- //
- // If compiler wants to perform logical shift by variable/register
- // in fp/vector registers it uses USHL that selects shift direction
- // based on shift operand value. Thus for right shifts the shift
- // operand needs to be negated.
- //
- // The bug is in right shift pattern; it doesn't mark shift operand
- // as clobbered and thus later code using that same register may
- // see the negated value.
- //
- // Workaround is to disable optimization for this function.
- //
- // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61633
- __attribute__((optimize(0)))
-# endif
-#endif
- ;
+ bool compare (float in0, float in1, double reference, float result);
private:
ShaderFloatPrecisionCase (const ShaderFloatPrecisionCase& other);
int pixelSize = m_texFormat.getPixelSize();
int rowLength = m_rowLength > 0 ? m_rowLength : m_width;
int rowPitch = deAlign32(rowLength*pixelSize, m_alignment);
- int height = m_height + m_skipRows;
deUint32 tex = 0;
vector<deUint8> data;
DE_ASSERT(m_numLevels == 1);
// Fill data with grid.
- data.resize(rowPitch*height);
+ data.resize(pixelSize * m_skipPixels + rowPitch * (m_height + m_skipRows));
{
Vec4 cScale = m_texFormatInfo.valueMax-m_texFormatInfo.valueMin;
Vec4 cBias = m_texFormatInfo.valueMin;
DE_ASSERT(m_numLevels == 1);
// Fill data with grid.
- data.resize(slicePitch*(m_depth+m_skipImages));
+ data.resize(pixelSize * m_skipPixels + rowPitch * m_skipRows + slicePitch * (m_skipImages + m_depth));
{
Vec4 cScale = m_texFormatInfo.valueMax-m_texFormatInfo.valueMin;
Vec4 cBias = m_texFormatInfo.valueMin;
template <typename Comparer>
static DistributionCompareResult distributionCompare (const std::vector<deUint64>& orderedObservationsA, const std::vector<deUint64>& orderedObservationsB, const Comparer& comparer)
{
- // Mann\96Whitney U test
+ // Mann-Whitney U test
const int n1 = (int)orderedObservationsA.size();
const int n2 = (int)orderedObservationsB.size();
es31fShaderAtomicOpTests.hpp
es31fShaderImageLoadStoreTests.cpp
es31fShaderImageLoadStoreTests.hpp
+ es31fSRGBDecodeTests.cpp
+ es31fSRGBDecodeTests.hpp
es31fSSBOLayoutCase.cpp
es31fSSBOLayoutCase.hpp
es31fSSBOLayoutTests.cpp
es31fNegativePreciseTests.hpp
es31fNegativeAdvancedBlendEquationTests.cpp
es31fNegativeAdvancedBlendEquationTests.hpp
+ es31fNegativeTessellationTests.cpp
+ es31fNegativeTessellationTests.hpp
es31fTextureGatherTests.cpp
es31fTextureGatherTests.hpp
es31fTextureFormatTests.cpp
es31fCopyImageTests.cpp
es31fDrawBuffersIndexedTests.hpp
es31fDrawBuffersIndexedTests.cpp
+ es31fNegativeShaderStorageTests.cpp
+ es31fNegativeShaderStorageTests.hpp
+ es31fNegativeSSBOBlockTests.cpp
+ es31fNegativeSSBOBlockTests.hpp
)
add_library(deqp-gles31-functional STATIC ${DEQP_GLES31_FUNCTIONAL_SRCS})
using namespace glu::TextureTestUtil;
using tcu::Float;
+using tcu::IVec2;
using tcu::IVec3;
+using tcu::IVec4;
using tcu::Sampler;
using tcu::ScopedLogSection;
using tcu::TestLog;
VIEWCLASS_ASTC_12x12_RGBA
};
+enum Verify
+{
+ VERIFY_NONE = 0,
+ VERIFY_COMPARE_REFERENCE
+};
+
const char* viewClassToName (ViewClass viewClass)
{
switch (viewClass)
}
}
+class RandomizedRenderGrid
+{
+public:
+ RandomizedRenderGrid (const IVec2& targetSize, const IVec2& cellSize, int maxCellCount, deUint32 seed);
+ bool nextCell (void);
+ IVec2 getOrigin (void) const;
+
+ const IVec2& getCellSize (void) const { return m_cellSize; };
+ IVec4 getUsedAreaBoundingBox (void) const;
+ int getCellCount (void) const { return m_cellCount; };
+
+private:
+ static IVec2 getRandomOffset (deUint32 seed, IVec2 targetSize, IVec2 cellSize, IVec2 grid, int cellCount);
+
+ const IVec2 m_targetSize;
+ const IVec2 m_cellSize;
+ const IVec2 m_grid;
+ int m_currentCell;
+ const int m_cellCount;
+ const IVec2 m_baseRandomOffset;
+};
+
+RandomizedRenderGrid::RandomizedRenderGrid (const IVec2& targetSize, const IVec2& cellSize, int maxCellCount, deUint32 seed)
+ : m_targetSize (targetSize)
+ , m_cellSize (cellSize)
+ , m_grid (targetSize / cellSize)
+ , m_currentCell (0)
+ // If the grid exactly fits height, take one row for randomization.
+ , m_cellCount (deMin32(maxCellCount, ((targetSize.y() % cellSize.y()) == 0) && m_grid.y() > 1 ? m_grid.x() * (m_grid.y() - 1) : m_grid.x() * m_grid.y()))
+ , m_baseRandomOffset (getRandomOffset(seed, targetSize, cellSize, m_grid, m_cellCount))
+{
+}
+
+IVec2 RandomizedRenderGrid::getRandomOffset (deUint32 seed, IVec2 targetSize, IVec2 cellSize, IVec2 grid, int cellCount)
+{
+ de::Random rng (seed);
+ IVec2 result;
+ IVec2 extraSpace = targetSize - (cellSize * grid);
+
+ // If there'll be unused rows, donate them into extra space.
+ // (Round the required rows to full cell row to find out how many rows are unused, multiply by size)
+ DE_ASSERT(deDivRoundUp32(cellCount, grid.x()) <= grid.y());
+ extraSpace.y() += (grid.y() - deDivRoundUp32(cellCount, grid.x())) * cellSize.y();
+
+ DE_ASSERT(targetSize.x() > cellSize.x() && targetSize.y() > cellSize.y());
+ // If grid fits perfectly just one row of cells, just give up on randomizing.
+ DE_ASSERT(extraSpace.x() > 0 || extraSpace.y() > 0 || grid.y() == 1);
+ DE_ASSERT(extraSpace.x() + grid.x() * cellSize.x() == targetSize.x());
+
+ // \note Putting these as ctor params would make evaluation order undefined, I think <sigh>. Hence,
+ // no direct return.
+ result.x() = rng.getInt(0, extraSpace.x());
+ result.y() = rng.getInt(0, extraSpace.y());
+ return result;
+}
+
+bool RandomizedRenderGrid::nextCell (void)
+{
+ if (m_currentCell >= getCellCount())
+ return false;
+
+ m_currentCell++;
+ return true;
+}
+
+IVec2 RandomizedRenderGrid::getOrigin (void) const
+{
+ const int gridX = (m_currentCell - 1) % m_grid.x();
+ const int gridY = (m_currentCell - 1) / m_grid.x();
+ const IVec2 currentOrigin = (IVec2(gridX, gridY) * m_cellSize) + m_baseRandomOffset;
+
+ DE_ASSERT(currentOrigin.x() >= 0 && (currentOrigin.x() + m_cellSize.x()) <= m_targetSize.x());
+ DE_ASSERT(currentOrigin.y() >= 0 && (currentOrigin.y() + m_cellSize.y()) <= m_targetSize.y());
+
+ return currentOrigin;
+}
+
+IVec4 RandomizedRenderGrid::getUsedAreaBoundingBox (void) const
+{
+ const IVec2 lastCell (de::min(m_currentCell + 1, m_grid.x()), ((m_currentCell + m_grid.x() - 1) / m_grid.x()));
+ const IVec2 size = lastCell * m_cellSize;
+
+ return IVec4(m_baseRandomOffset.x(), m_baseRandomOffset.y(), size.x(), size.y());
+}
+
class ImageInfo
{
public:
}
}
+IVec3 getLevelSize (deUint32 target, const IVec3& baseSize, int level)
+{
+ IVec3 size;
+
+ if (target != GL_TEXTURE_2D_ARRAY)
+ {
+ for (int i = 0; i < 3; i++)
+ size[i] = de::max(baseSize[i] >> level, 1);
+ }
+ else
+ {
+ for (int i = 0; i < 2; i++)
+ size[i] = de::max(baseSize[i] >> level, 1);
+
+ size[2] = baseSize[2];
+ }
+
+ return size;
+}
+
+deUint32 mapFaceNdxToFace (int ndx)
+{
+ const deUint32 cubeFaces[] =
+ {
+ GL_TEXTURE_CUBE_MAP_POSITIVE_X,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
+
+ GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
+
+ GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
+ };
+
+ return de::getSizedArrayElement<6>(cubeFaces, ndx);
+}
+
+// Class for iterating over mip levels and faces/slices/... of a texture.
+class TextureImageIterator
+{
+public:
+ TextureImageIterator (const ImageInfo info, int levelCount);
+ ~TextureImageIterator (void) {}
+
+ // Need to call next image once, newly constructed not readable, except for getSize
+ bool nextImage (void);
+ bool hasNextImage (void) const { return (m_currentLevel < (m_levelCount - 1)) || m_currentImage < (m_levelImageCount - 1); }
+
+ int getMipLevel (void) const { return m_currentLevel; }
+ int getMipLevelCount (void) const { return m_levelCount; }
+ int getCurrentImage (void) const { return m_currentImage;}
+ int getLevelImageCount (void) const { return m_levelImageCount; }
+ IVec2 getSize (void) const { return m_levelSize.toWidth<2>(); } // Assume that image sizes never grow over iteration
+ deUint32 getTarget (void) const { return m_info.getTarget(); }
+
+private:
+ int m_levelImageCount; // Need to be defined in CTOR for the hasNextImage to work!
+ const ImageInfo m_info;
+ int m_currentLevel;
+ IVec3 m_levelSize;
+ int m_currentImage;
+ const int m_levelCount;
+};
+
+TextureImageIterator::TextureImageIterator (const ImageInfo info, int levelCount)
+ : m_levelImageCount (info.getTarget() == GL_TEXTURE_CUBE_MAP ? 6 : getLevelSize(info.getTarget(), info.getSize(), 0).z())
+ , m_info (info)
+ , m_currentLevel (0)
+ , m_levelSize (getLevelSize(info.getTarget(), info.getSize(), 0))
+ , m_currentImage (-1)
+ , m_levelCount (levelCount)
+{
+ DE_ASSERT(m_levelCount <= getLevelCount(info));
+}
+
+bool TextureImageIterator::nextImage (void)
+{
+ if (!hasNextImage())
+ return false;
+
+ m_currentImage++;
+ if (m_currentImage == m_levelImageCount)
+ {
+ m_currentLevel++;
+ m_currentImage = 0;
+
+ m_levelSize = getLevelSize(m_info.getTarget(), m_info.getSize(), m_currentLevel);
+
+ if (getTarget() == GL_TEXTURE_CUBE_MAP)
+ m_levelImageCount = 6;
+ else
+ m_levelImageCount = m_levelSize.z();
+ }
+ DE_ASSERT(m_currentLevel < m_levelCount);
+ DE_ASSERT(m_currentImage < m_levelImageCount);
+ return true;
+}
+
+// Get name
+string getTextureImageName (int textureTarget, int mipLevel, int imageIndex)
+{
+ std::ostringstream result;
+ result << "Level";
+ result << mipLevel;
+ switch (textureTarget)
+ {
+ case GL_TEXTURE_2D: break;
+ case GL_TEXTURE_3D: result << "Slice" << imageIndex; break;
+ case GL_TEXTURE_CUBE_MAP: result << "Face" << imageIndex; break;
+ case GL_TEXTURE_2D_ARRAY: result << "Layer" << imageIndex; break;
+ default:
+ DE_FATAL("Unsupported texture target");
+ break;
+ }
+ return result.str();
+}
+
+// Get description
+string getTextureImageDescription (int textureTarget, int mipLevel, int imageIndex)
+{
+ std::ostringstream result;
+ result << "level ";
+ result << mipLevel;
+
+ switch (textureTarget)
+ {
+ case GL_TEXTURE_2D: break;
+ case GL_TEXTURE_3D: result << " and Slice " << imageIndex; break;
+ case GL_TEXTURE_CUBE_MAP: result << " and Face " << imageIndex; break;
+ case GL_TEXTURE_2D_ARRAY: result << " and Layer " << imageIndex; break;
+ default:
+ DE_FATAL("Unsupported texture target");
+ break;
+ }
+ return result.str();
+}
+
+// Compute texture coordinates
+void computeQuadTexCoords(vector<float>& texCoord, const TextureImageIterator& iteration)
+{
+ const int currentImage = iteration.getCurrentImage();
+ switch (iteration.getTarget())
+ {
+ case GL_TEXTURE_2D:
+ computeQuadTexCoord2D(texCoord, tcu::Vec2(0.0f, 0.0f), tcu::Vec2(1.0f, 1.0f));
+ break;
+
+ case GL_TEXTURE_3D:
+ {
+ const float r = (float(currentImage) + 0.5f) / (float)iteration.getLevelImageCount();
+ computeQuadTexCoord3D(texCoord, tcu::Vec3(0.0f, 0.0f, r), tcu::Vec3(1.0f, 1.0f, r), tcu::IVec3(0, 1, 2));
+ break;
+ }
+
+ case GL_TEXTURE_CUBE_MAP:
+ computeQuadTexCoordCube(texCoord, glu::getCubeFaceFromGL(mapFaceNdxToFace(currentImage)));
+ break;
+
+ case GL_TEXTURE_2D_ARRAY:
+ computeQuadTexCoord2DArray(texCoord, currentImage, tcu::Vec2(0.0f, 0.0f), tcu::Vec2(1.0f, 1.0f));
+ break;
+
+ default:
+ DE_FATAL("Unsupported texture target");
+ }
+}
+
+// Struct for storing each reference image with necessary metadata.
+struct CellContents
+{
+ IVec2 origin;
+ tcu::Surface reference;
+ std::string name;
+ std::string description;
+};
+
// Return format that has more restrictions on texel data.
deUint32 getMoreRestrictiveFormat (deUint32 formatA, deUint32 formatB)
{
return IVec3(1, 1, 1);
}
-IVec3 getLevelSize (deUint32 target, const IVec3& baseSize, int level)
-{
- IVec3 size;
-
- if (target != GL_TEXTURE_2D_ARRAY)
- {
- for (int i = 0; i < 3; i++)
- size[i] = de::max(baseSize[i] >> level, 1);
- }
- else
- {
- for (int i = 0; i < 2; i++)
- size[i] = de::max(baseSize[i] >> level, 1);
-
- size[2] = baseSize[2];
- }
-
- return size;
-}
-
bool isColorRenderable (deUint32 format)
{
switch (format)
return res;
}
-deUint32 mapFaceNdxToFace (int ndx)
-{
- const deUint32 cubeFaces[] =
- {
- GL_TEXTURE_CUBE_MAP_POSITIVE_X,
- GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
-
- GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
- GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
-
- GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
- GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
- };
-
- return de::getSizedArrayElement<6>(cubeFaces, ndx);
-}
-
deUint32 getFormatForInternalFormat (deUint32 format)
{
return glu::getTransferFormat(glu::mapGLInternalFormat(format)).format;
srcImageData, srcImageInfo, srcLevel, srcPos, copySize);
}
-void verifyTexture2DView (tcu::TestContext& testContext,
+template<class TextureView>
+void renderTexture (glu::RenderContext& renderContext,
+ TextureRenderer& renderer,
+ ReferenceParams& renderParams,
+ tcu::ResultCollector& results,
+ de::Random& rng,
+ const TextureView& refTexture,
+ const Verify verify,
+ TextureImageIterator& imageIterator,
+ tcu::TestLog& log)
+{
+ const tcu::RenderTarget& renderTarget = renderContext.getRenderTarget();
+ const tcu::RGBA threshold = renderTarget.getPixelFormat().getColorThreshold() + tcu::RGBA(1,1,1,1);
+ const glw::Functions& gl = renderContext.getFunctions();
+ const IVec2 renderTargetSize = IVec2(renderTarget.getWidth(), renderTarget.getHeight());
+
+ while (imageIterator.hasNextImage())
+ {
+ // \note: Reserve space upfront to avoid assigning tcu::Surface, which incurs buffer mem copy. Using a
+ // conservative estimate for simplicity
+ const int imagesOnLevel = imageIterator.getLevelImageCount();
+ const int imageEstimate = (imageIterator.getMipLevelCount() - imageIterator.getMipLevel()) * imagesOnLevel;
+ RandomizedRenderGrid renderGrid (renderTargetSize, imageIterator.getSize(), imageEstimate, rng.getUint32());
+ vector<CellContents> cellContents (renderGrid.getCellCount());
+ int cellsUsed = 0;
+
+ // \note: Ordering of conditions is significant. If put the other way around, the code would skip one of the
+ // images if the grid runs out of cells before the texture runs out of images. Advancing one grid cell over the
+ // needed number has no negative impact.
+ while (renderGrid.nextCell() && imageIterator.nextImage())
+ {
+ const int level = imageIterator.getMipLevel();
+ const IVec2 levelSize = imageIterator.getSize();
+ const IVec2 origin = renderGrid.getOrigin();
+ vector<float> texCoord;
+
+ DE_ASSERT(imageIterator.getTarget() != GL_TEXTURE_CUBE_MAP || levelSize.x() >= 4 || levelSize.y() >= 4);
+
+ renderParams.baseLevel = level;
+ renderParams.maxLevel = level;
+
+ gl.texParameteri(imageIterator.getTarget(), GL_TEXTURE_BASE_LEVEL, level);
+ gl.texParameteri(imageIterator.getTarget(), GL_TEXTURE_MAX_LEVEL, level);
+
+ computeQuadTexCoords(texCoord, imageIterator);
+
+ // Setup base viewport.
+ gl.viewport(origin.x(), origin.y(), levelSize.x(), levelSize.y());
+
+ // Draw.
+ renderer.renderQuad(0, &texCoord[0], renderParams);
+ GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to render.");
+
+ if (verify == VERIFY_COMPARE_REFERENCE)
+ {
+ const int target = imageIterator.getTarget();
+ const int imageIndex = imageIterator.getCurrentImage();
+
+ cellContents[cellsUsed].origin = origin;
+ cellContents[cellsUsed].name = getTextureImageName(target, level, imageIndex);
+ cellContents[cellsUsed].description = getTextureImageDescription(target, level, imageIndex);
+
+ cellContents[cellsUsed].reference.setSize(levelSize.x(), levelSize.y());
+
+ // Compute reference.
+ sampleTexture(tcu::SurfaceAccess(cellContents[cellsUsed].reference, renderContext.getRenderTarget().getPixelFormat()), refTexture, &texCoord[0], renderParams);
+ cellsUsed++;
+ }
+ }
+
+ if (cellsUsed > 0)
+ {
+ const IVec4 boundingBox = renderGrid.getUsedAreaBoundingBox();
+ tcu::Surface renderedFrame (boundingBox[2], boundingBox[3]);
+
+ glu::readPixels(renderContext, boundingBox.x(), boundingBox.y(), renderedFrame.getAccess());
+ GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to read pixels.");
+
+ for (int idx = 0; idx < cellsUsed; idx++)
+ {
+ const CellContents& cell (cellContents[idx]);
+ const IVec2 cellOrigin = cell.origin - boundingBox.toWidth<2>();
+ const tcu::ConstPixelBufferAccess resultAccess = getSubregion(renderedFrame.getAccess(), cellOrigin.x(), cellOrigin.y(), cell.reference.getWidth(), cell.reference.getHeight());
+
+ if (!intThresholdCompare(log, cell.name.c_str(), cell.description.c_str(), cell.reference.getAccess(), resultAccess, threshold.toIVec().cast<deUint32>(), tcu::COMPARE_LOG_ON_ERROR))
+ results.fail("Image comparison of " + cell.description + " failed.");
+ else
+ log << TestLog::Message << "Image comparison of " << cell.description << " passed." << TestLog::EndMessage;;
+ }
+ }
+ }
+
+ gl.texParameteri(imageIterator.getTarget(), GL_TEXTURE_BASE_LEVEL, 0);
+ gl.texParameteri(imageIterator.getTarget(), GL_TEXTURE_MAX_LEVEL, 1000);
+}
+
+void renderTexture2DView (tcu::TestContext& testContext,
glu::RenderContext& renderContext,
TextureRenderer& renderer,
tcu::ResultCollector& results,
de::Random& rng,
deUint32 name,
const ImageInfo& info,
- const tcu::Texture2DView& refTexture)
+ const tcu::Texture2DView& refTexture,
+ Verify verify)
{
tcu::TestLog& log = testContext.getLog();
const glw::Functions& gl = renderContext.getFunctions();
- const tcu::RGBA threshold = renderContext.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(1,1,1,1);
const tcu::TextureFormat format = refTexture.getLevel(0).getFormat();
const tcu::TextureFormatInfo spec = tcu::getTextureFormatInfo(format);
ReferenceParams renderParams (TEXTURETYPE_2D);
+ TextureImageIterator imageIterator (info, getLevelCount(info));
renderParams.samplerType = getSamplerType(format);
renderParams.sampler = Sampler(Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::NEAREST_MIPMAP_NEAREST, Sampler::NEAREST);
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup texture filtering state.");
- for (int level = 0; level < getLevelCount(info); level++)
- {
- const IVec3 levelSize = getLevelSize(info.getTarget(), info.getSize(), level);
- const RandomViewport viewport (renderContext.getRenderTarget(), levelSize.x(), levelSize.y(), rng.getUint32());
-
- vector<float> texCoord;
- tcu::Surface renderedFrame (viewport.width, viewport.height);
- tcu::Surface referenceFrame (viewport.width, viewport.height);
-
- renderParams.baseLevel = level;
- renderParams.maxLevel = level;
-
- gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, level);
- gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level);
-
- computeQuadTexCoord2D(texCoord, tcu::Vec2(0.0f, 0.0f), tcu::Vec2(1.0f, 1.0f));
-
- // Setup base viewport.
- gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
-
- // Draw.
- renderer.renderQuad(0, &texCoord[0], renderParams);
- glu::readPixels(renderContext, viewport.x, viewport.y, renderedFrame.getAccess());
- GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to render and read pixels.");
-
- // Compute reference.
- sampleTexture(tcu::SurfaceAccess(referenceFrame, renderContext.getRenderTarget().getPixelFormat()), refTexture, &texCoord[0], renderParams);
-
- // Compare and log.
- if (!pixelThresholdCompare(log, ("Level" + de::toString(level)).c_str(), ("Render level " + de::toString(level)).c_str(), referenceFrame, renderedFrame, threshold, tcu::COMPARE_LOG_ON_ERROR))
- results.fail("Image comparison of level " + de::toString(level) + " failed.");
- else
- log << TestLog::Message << "Image comparison of level " << level << " passed." << TestLog::EndMessage;
- }
-
- gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
- gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1000);
+ renderTexture<tcu::Texture2DView>(renderContext, renderer, renderParams, results, rng, refTexture, verify, imageIterator, log);
gl.bindTexture(GL_TEXTURE_2D, 0);
GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to unbind texture.");
}
}
-void verifyTexture2D (tcu::TestContext& testContext,
+void renderTexture2D (tcu::TestContext& testContext,
glu::RenderContext& renderContext,
TextureRenderer& textureRenderer,
tcu::ResultCollector& results,
de::Random& rng,
deUint32 name,
const vector<ArrayBuffer<deUint8> >& data,
- const ImageInfo& info)
+ const ImageInfo& info,
+ Verify verify)
{
if (glu::isCompressedFormat(info.getFormat()))
{
{
const tcu::Texture2DView refTexture((int)levelAccesses.size(), &(levelAccesses[0]));
- verifyTexture2DView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture);
+ renderTexture2DView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture, verify);
}
}
else
const vector<tcu::ConstPixelBufferAccess> levelAccesses = getLevelAccesses(data, info);
const tcu::Texture2DView refTexture ((int)levelAccesses.size(), &(levelAccesses[0]));
- verifyTexture2DView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture);
+ renderTexture2DView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture, verify);
}
}
-void verifyTexture3DView (tcu::TestContext& testContext,
+void renderTexture3DView (tcu::TestContext& testContext,
glu::RenderContext& renderContext,
TextureRenderer& renderer,
tcu::ResultCollector& results,
de::Random& rng,
deUint32 name,
const ImageInfo& info,
- const tcu::Texture3DView& refTexture)
+ const tcu::Texture3DView& refTexture,
+ Verify verify)
{
tcu::TestLog& log = testContext.getLog();
const glw::Functions& gl = renderContext.getFunctions();
- const tcu::RGBA threshold = renderContext.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(1,1,1,1);
const tcu::TextureFormat format = refTexture.getLevel(0).getFormat();
const tcu::TextureFormatInfo spec = tcu::getTextureFormatInfo(format);
ReferenceParams renderParams (TEXTURETYPE_3D);
+ TextureImageIterator imageIterator (info, getLevelCount(info));
renderParams.samplerType = getSamplerType(format);
renderParams.sampler = Sampler(Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::NEAREST_MIPMAP_NEAREST, Sampler::NEAREST);
gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup texture filtering state.");
- for (int level = 0; level < getLevelCount(info); level++)
- {
- const IVec3 levelSize = getLevelSize(info.getTarget(), info.getSize(), level);
-
- renderParams.baseLevel = level;
- renderParams.maxLevel = level;
-
- gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, level);
- gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, level);
-
- for (int slice = 0; slice < levelSize.z(); slice++)
- {
- const RandomViewport viewport (renderContext.getRenderTarget(), levelSize.x(), levelSize.y(), rng.getUint32());
- const float r = (float(slice) + 0.5f) / (float)levelSize.z();
- tcu::Surface renderedFrame (viewport.width, viewport.height);
- tcu::Surface referenceFrame (viewport.width, viewport.height);
- vector<float> texCoord;
-
- computeQuadTexCoord3D(texCoord, tcu::Vec3(0.0f, 0.0f, r), tcu::Vec3(1.0f, 1.0f, r), tcu::IVec3(0, 1, 2));
-
- // Setup base viewport.
- gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
-
- // Draw.
- renderer.renderQuad(0, &texCoord[0], renderParams);
- glu::readPixels(renderContext, viewport.x, viewport.y, renderedFrame.getAccess());
- GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to render and read pixels.");
-
- // Compute reference.
- sampleTexture(tcu::SurfaceAccess(referenceFrame, renderContext.getRenderTarget().getPixelFormat()), refTexture, &texCoord[0], renderParams);
-
- // Compare and log.
- if (!pixelThresholdCompare(log, ("Level" + de::toString(level) + "Slice" + de::toString(slice)).c_str(), ("Render level " + de::toString(level) + ", Slice" + de::toString(slice)).c_str(), referenceFrame, renderedFrame, threshold, tcu::COMPARE_LOG_ON_ERROR))
- results.fail("Image comparison of level " + de::toString(level) + " and slice " + de::toString(slice) + " failed.");
- else
- log << TestLog::Message << "Image comparison of level " << level << " and slice " << slice << " passed." << TestLog::EndMessage;;
- }
- }
-
- gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 0);
- gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 1000);
+ renderTexture<tcu::Texture3DView>(renderContext, renderer, renderParams, results, rng, refTexture, verify, imageIterator, log);
gl.bindTexture(GL_TEXTURE_3D, 0);
GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to unbind texture.");
}
-void verifyTexture3D (tcu::TestContext& testContext,
+void renderTexture3D (tcu::TestContext& testContext,
glu::RenderContext& renderContext,
TextureRenderer& textureRenderer,
tcu::ResultCollector& results,
de::Random& rng,
deUint32 name,
const vector<ArrayBuffer<deUint8> >& data,
- const ImageInfo& info)
+ const ImageInfo& info,
+ Verify verify)
{
if (glu::isCompressedFormat(info.getFormat()))
{
{
const tcu::Texture3DView refTexture((int)levelAccesses.size(), &(levelAccesses[0]));
- verifyTexture3DView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture);
+ renderTexture3DView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture, verify);
}
}
else
const vector<tcu::ConstPixelBufferAccess> levelAccesses = getLevelAccesses(data, info);
const tcu::Texture3DView refTexture ((int)levelAccesses.size(), &(levelAccesses[0]));
- verifyTexture3DView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture);
+ renderTexture3DView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture, verify);
}
}
-void verifyTextureCubemapView (tcu::TestContext& testContext,
+void renderTextureCubemapView (tcu::TestContext& testContext,
glu::RenderContext& renderContext,
TextureRenderer& renderer,
tcu::ResultCollector& results,
de::Random& rng,
deUint32 name,
const ImageInfo& info,
- const tcu::TextureCubeView& refTexture)
+ const tcu::TextureCubeView& refTexture,
+ Verify verify)
{
tcu::TestLog& log = testContext.getLog();
const glw::Functions& gl = renderContext.getFunctions();
- const tcu::RGBA threshold = renderContext.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(1,1,1,1);
const tcu::TextureFormat format = refTexture.getLevelFace(0, tcu::CUBEFACE_POSITIVE_X).getFormat();
const tcu::TextureFormatInfo spec = tcu::getTextureFormatInfo(format);
ReferenceParams renderParams (TEXTURETYPE_CUBE);
+ // \note It seems we can't reliably sample two smallest texture levels with cubemaps
+ TextureImageIterator imageIterator (info, getLevelCount(info) - 2);
renderParams.samplerType = getSamplerType(format);
renderParams.sampler = Sampler(Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::NEAREST_MIPMAP_NEAREST, Sampler::NEAREST);
gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup texture filtering state.");
- for (int level = 0; level < getLevelCount(info); level++)
- {
- const IVec3 levelSize = getLevelSize(info.getTarget(), info.getSize(), level);
-
- // \note It seems we can't reliably sample two smallest texture levels with cubemaps
- if (levelSize.x() < 4 && levelSize.y() < 4)
- continue;
-
- renderParams.baseLevel = level;
- renderParams.maxLevel = level;
-
- gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, level);
- gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, level);
-
- for (int face = 0; face < 6; face++)
- {
- const RandomViewport viewport (renderContext.getRenderTarget(), levelSize.x(), levelSize.y(), rng.getUint32());
- const string cubemapFaceName = glu::getCubeMapFaceStr(mapFaceNdxToFace(face)).toString();
- tcu::Surface renderedFrame (viewport.width, viewport.height);
- tcu::Surface referenceFrame (viewport.width, viewport.height);
- vector<float> texCoord;
-
- computeQuadTexCoordCube(texCoord, glu::getCubeFaceFromGL(mapFaceNdxToFace(face)));
-
- // Setup base viewport.
- gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
-
- // Draw.
- renderer.renderQuad(0, &texCoord[0], renderParams);
- glu::readPixels(renderContext, viewport.x, viewport.y, renderedFrame.getAccess());
- GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to render and read pixels.");
-
- // Compute reference.
- sampleTexture(tcu::SurfaceAccess(referenceFrame, renderContext.getRenderTarget().getPixelFormat()), refTexture, &texCoord[0], renderParams);
-
- // Compare and log.
- if (!pixelThresholdCompare(log, ("Level" + de::toString(level) + "Face" + cubemapFaceName).c_str(), ("Render level " + de::toString(level) + ", Face " + cubemapFaceName).c_str(), referenceFrame, renderedFrame, threshold, tcu::COMPARE_LOG_ON_ERROR))
- results.fail("Image comparison of level " + de::toString(level) + " and face " + cubemapFaceName + " failed.");
- else
- log << TestLog::Message << "Image comparison of level " << level << " and face " << cubemapFaceName << " passed." << TestLog::EndMessage;
- }
- }
-
- gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0);
- gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 1000);
+ renderTexture<tcu::TextureCubeView>(renderContext, renderer, renderParams, results, rng, refTexture, verify, imageIterator, log);
gl.bindTexture(GL_TEXTURE_CUBE_MAP, 0);
GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to unbind texture.");
}
-void verifyTextureCubemap (tcu::TestContext& testContext,
+void renderTextureCubemap (tcu::TestContext& testContext,
glu::RenderContext& renderContext,
TextureRenderer& textureRenderer,
tcu::ResultCollector& results,
de::Random& rng,
deUint32 name,
const vector<ArrayBuffer<deUint8> >& data,
- const ImageInfo& info)
+ const ImageInfo& info,
+ Verify verify)
{
if (glu::isCompressedFormat(info.getFormat()))
{
{
const tcu::TextureCubeView refTexture(getLevelCount(info), levels);
- verifyTextureCubemapView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture);
+ renderTextureCubemapView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture, verify);
}
}
else
{
const tcu::TextureCubeView refTexture(getLevelCount(info), levels);
- verifyTextureCubemapView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture);
+ renderTextureCubemapView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture, verify);
}
}
}
-void verifyTexture2DArrayView (tcu::TestContext& testContext,
+void renderTexture2DArrayView (tcu::TestContext& testContext,
glu::RenderContext& renderContext,
TextureRenderer& renderer,
tcu::ResultCollector& results,
de::Random& rng,
deUint32 name,
const ImageInfo& info,
- const tcu::Texture2DArrayView& refTexture)
+ const tcu::Texture2DArrayView& refTexture,
+ Verify verify)
{
tcu::TestLog& log = testContext.getLog();
const glw::Functions& gl = renderContext.getFunctions();
- const tcu::RGBA threshold = renderContext.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(1,1,1,1);
const tcu::TextureFormat format = refTexture.getLevel(0).getFormat();
const tcu::TextureFormatInfo spec = tcu::getTextureFormatInfo(format);
ReferenceParams renderParams (TEXTURETYPE_2D_ARRAY);
+ TextureImageIterator imageIterator (info, getLevelCount(info));
renderParams.samplerType = getSamplerType(format);
renderParams.sampler = Sampler(Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::NEAREST_MIPMAP_NEAREST, Sampler::NEAREST);
gl.texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup texture filtering state.");
- for (int level = 0; level < getLevelCount(info); level++)
- {
- const IVec3 levelSize = getLevelSize(info.getTarget(), info.getSize(), level);
-
- renderParams.baseLevel = level;
- renderParams.maxLevel = level;
-
- gl.texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, level);
- gl.texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, level);
-
- for (int layer = 0; layer < levelSize.z(); layer++)
- {
- const RandomViewport viewport (renderContext.getRenderTarget(), levelSize.x(), levelSize.y(), rng.getUint32());
- tcu::Surface renderedFrame (viewport.width, viewport.height);
- tcu::Surface referenceFrame (viewport.width, viewport.height);
- vector<float> texCoord;
-
- computeQuadTexCoord2DArray(texCoord, layer, tcu::Vec2(0.0f, 0.0f), tcu::Vec2(1.0f, 1.0f));
-
- // Setup base viewport.
- gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
-
- // Draw.
- renderer.renderQuad(0, &texCoord[0], renderParams);
- glu::readPixels(renderContext, viewport.x, viewport.y, renderedFrame.getAccess());
- GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to render and read pixels.");
-
- // Compute reference.
- sampleTexture(tcu::SurfaceAccess(referenceFrame, renderContext.getRenderTarget().getPixelFormat()), refTexture, &texCoord[0], renderParams);
-
- // Compare and log.
- if (!pixelThresholdCompare(log, ("Level" + de::toString(level) + "Layer" + de::toString(layer)).c_str(), ("Render level " + de::toString(level) + ", Layer" + de::toString(layer)).c_str(), referenceFrame, renderedFrame, threshold, tcu::COMPARE_LOG_ON_ERROR))
- results.fail("Image comparison of level " + de::toString(level) + " and layer " + de::toString(layer) + " failed.");
- else
- log << TestLog::Message << "Image comparison of level " << level << " and layer " << layer << " passed." << TestLog::EndMessage;
- }
- }
-
- gl.texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 0);
- gl.texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 1000);
+ renderTexture<tcu::Texture2DArrayView>(renderContext, renderer, renderParams, results, rng, refTexture, verify, imageIterator, log);
gl.bindTexture(GL_TEXTURE_2D_ARRAY, 0);
GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to unbind texture.");
}
-void verifyTexture2DArray (tcu::TestContext& testContext,
+void renderTexture2DArray (tcu::TestContext& testContext,
glu::RenderContext& renderContext,
TextureRenderer& textureRenderer,
tcu::ResultCollector& results,
de::Random& rng,
deUint32 name,
const vector<ArrayBuffer<deUint8> >& data,
- const ImageInfo& info)
+ const ImageInfo& info,
+ Verify verify)
{
if (glu::isCompressedFormat(info.getFormat()))
{
{
const tcu::Texture2DArrayView refTexture((int)levelAccesses.size(), &(levelAccesses[0]));
- verifyTexture2DArrayView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture);
+ renderTexture2DArrayView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture, verify);
}
}
else
const vector<tcu::ConstPixelBufferAccess> levelAccesses = getLevelAccesses(data, info);
const tcu::Texture2DArrayView refTexture ((int)levelAccesses.size(), &(levelAccesses[0]));
- verifyTexture2DArrayView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture);
+ renderTexture2DArrayView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture, verify);
}
}
}
}
-void verifyRenderbuffer (tcu::TestContext& testContext,
+void renderRenderbuffer (tcu::TestContext& testContext,
glu::RenderContext& renderContext,
tcu::ResultCollector& results,
deUint32 name,
const vector<ArrayBuffer<deUint8> >& data,
- const ImageInfo& info)
+ const ImageInfo& info,
+ Verify verify)
{
const glw::Functions& gl = renderContext.getFunctions();
TestLog& log = testContext.getLog();
gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, name);
GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to bind and attach renderbuffer to framebuffer.");
- glu::readPixels(renderContext, 0, 0, renderbuffer.getAccess());
+ if (verify)
+ glu::readPixels(renderContext, 0, 0, renderbuffer.getAccess());
gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to unbind renderbuffer and framebuffer.");
}
- if (isFloatFormat(info.getFormat()))
+ if (verify == VERIFY_COMPARE_REFERENCE)
{
- const tcu::UVec4 threshold (2, 2, 2, 2);
+ if (isFloatFormat(info.getFormat()))
+ {
+ const tcu::UVec4 threshold (2, 2, 2, 2);
- if (!(tcu::floatUlpThresholdCompare(log, "Image comparison", "Image comparison", refRenderbuffer, renderbuffer.getAccess(), threshold, tcu::COMPARE_LOG_ON_ERROR)))
- results.fail("Image comparison failed.");
- else
- log << TestLog::Message << "Image comarison passed." << TestLog::EndMessage;
- }
- else if (isIntFormat(info.getFormat()) || isUintFormat(info.getFormat()))
- {
- const tcu::UVec4 threshold (1, 1, 1, 1);
+ if (!(tcu::floatUlpThresholdCompare(log, "Image comparison", "Image comparison", refRenderbuffer, renderbuffer.getAccess(), threshold, tcu::COMPARE_LOG_ON_ERROR)))
+ results.fail("Image comparison failed.");
+ else
+ log << TestLog::Message << "Image comarison passed." << TestLog::EndMessage;
+ }
+ else if (isIntFormat(info.getFormat()) || isUintFormat(info.getFormat()))
+ {
+ const tcu::UVec4 threshold (1, 1, 1, 1);
- if (!(tcu::intThresholdCompare(log, "Image comparison", "Image comparison", refRenderbuffer, renderbuffer.getAccess(), threshold, tcu::COMPARE_LOG_ON_ERROR)))
- results.fail("Image comparison failed.");
+ if (!(tcu::intThresholdCompare(log, "Image comparison", "Image comparison", refRenderbuffer, renderbuffer.getAccess(), threshold, tcu::COMPARE_LOG_ON_ERROR)))
+ results.fail("Image comparison failed.");
+ else
+ log << TestLog::Message << "Image comarison passed." << TestLog::EndMessage;
+ }
else
- log << TestLog::Message << "Image comarison passed." << TestLog::EndMessage;
- }
- else
- {
- const Vec4 threshold = calculateThreshold(format, readPixelsFormat);
+ {
+ const Vec4 threshold = calculateThreshold(format, readPixelsFormat);
- if (!(tcu::floatThresholdCompare(log, "Image comparison", "Image comparison", refRenderbuffer, renderbuffer.getAccess(), threshold, tcu::COMPARE_LOG_ON_ERROR)))
- results.fail("Image comparison failed.");
- else
- log << TestLog::Message << "Image comarison passed." << TestLog::EndMessage;
+ if (!(tcu::floatThresholdCompare(log, "Image comparison", "Image comparison", refRenderbuffer, renderbuffer.getAccess(), threshold, tcu::COMPARE_LOG_ON_ERROR)))
+ results.fail("Image comparison failed.");
+ else
+ log << TestLog::Message << "Image comarison passed." << TestLog::EndMessage;
+ }
}
}
-void verify (tcu::TestContext& testContext,
+void render (tcu::TestContext& testContext,
glu::RenderContext& renderContext,
TextureRenderer& textureRenderer,
tcu::ResultCollector& results,
de::Random& rng,
deUint32 name,
const vector<ArrayBuffer<deUint8> >& data,
- const ImageInfo& info)
+ const ImageInfo& info,
+ Verify verify)
{
switch (info.getTarget())
{
case GL_TEXTURE_2D:
- verifyTexture2D(testContext, renderContext, textureRenderer, results, rng, name, data, info);
+ renderTexture2D(testContext, renderContext, textureRenderer, results, rng, name, data, info, verify);
break;
case GL_TEXTURE_3D:
- verifyTexture3D(testContext, renderContext, textureRenderer, results, rng, name, data, info);
+ renderTexture3D(testContext, renderContext, textureRenderer, results, rng, name, data, info, verify);
break;
case GL_TEXTURE_CUBE_MAP:
- verifyTextureCubemap(testContext, renderContext, textureRenderer, results, rng, name, data, info);
+ renderTextureCubemap(testContext, renderContext, textureRenderer, results, rng, name, data, info, verify);
break;
case GL_TEXTURE_2D_ARRAY:
- verifyTexture2DArray(testContext, renderContext, textureRenderer, results, rng, name, data, info);
+ renderTexture2DArray(testContext, renderContext, textureRenderer, results, rng, name, data, info, verify);
break;
case GL_RENDERBUFFER:
- verifyRenderbuffer(testContext, renderContext, results, name, data, info);
+ renderRenderbuffer(testContext, renderContext, results, name, data, info, verify);
break;
default:
TestCase::IterateResult iterate (void);
private:
+
void logTestInfoIter (void);
void createImagesIter (void);
void destroyImagesIter (void);
void verifySourceIter (void);
void verifyDestinationIter (void);
+ void renderSourceIter (void);
+ void renderDestinationIter (void);
void copyImageIter (void);
+ typedef void (CopyImageTest::*IterationFunc)(void);
+
+ struct Iteration
+ {
+ Iteration (int methodCount_, const IterationFunc* methods_)
+ : methodCount (methodCount_)
+ , methods (methods_)
+ {
+ }
+
+ int methodCount;
+ const IterationFunc* methods;
+ };
+
struct State
{
State (int seed,
log << TestLog::Message << "Verifying source image." << TestLog::EndMessage;
- verify(m_testCtx, m_context.getRenderContext(), m_state->textureRenderer, results, rng, *srcImage, srcImageLevels, m_srcImageInfo);
+ render(m_testCtx, m_context.getRenderContext(), m_state->textureRenderer, results, rng, *srcImage, srcImageLevels, m_srcImageInfo, VERIFY_COMPARE_REFERENCE);
}
void CopyImageTest::verifyDestinationIter (void)
log << TestLog::Message << "Verifying destination image." << TestLog::EndMessage;
- verify(m_testCtx, m_context.getRenderContext(), m_state->textureRenderer, results, rng, *dstImage, dstImageLevels, m_dstImageInfo);
+ render(m_testCtx, m_context.getRenderContext(), m_state->textureRenderer, results, rng, *dstImage, dstImageLevels, m_dstImageInfo, VERIFY_COMPARE_REFERENCE);
+}
+
+void CopyImageTest::renderSourceIter (void)
+{
+ TestLog& log = m_testCtx.getLog();
+ const tcu::ScopedLogSection sourceSection (log, "Source image verify.", "Source image verify.");
+
+ de::Random& rng = m_state->rng;
+ tcu::ResultCollector& results = m_state->results;
+ glu::ObjectWrapper& srcImage = *m_state->srcImage;
+ vector<ArrayBuffer<deUint8> >& srcImageLevels = m_state->srcImageLevels;
+
+ log << TestLog::Message << "Verifying source image." << TestLog::EndMessage;
+
+ render(m_testCtx, m_context.getRenderContext(), m_state->textureRenderer, results, rng, *srcImage, srcImageLevels, m_srcImageInfo, VERIFY_NONE);
+}
+
+void CopyImageTest::renderDestinationIter (void)
+{
+ TestLog& log = m_testCtx.getLog();
+ const tcu::ScopedLogSection destinationSection (log, "Destination image verify.", "Destination image verify.");
+
+ de::Random& rng = m_state->rng;
+ tcu::ResultCollector& results = m_state->results;
+ glu::ObjectWrapper& dstImage = *m_state->dstImage;
+ vector<ArrayBuffer<deUint8> >& dstImageLevels = m_state->dstImageLevels;
+
+ log << TestLog::Message << "Verifying destination image." << TestLog::EndMessage;
+
+ render(m_testCtx, m_context.getRenderContext(), m_state->textureRenderer, results, rng, *dstImage, dstImageLevels, m_dstImageInfo, VERIFY_NONE);
}
struct Copy
TestCase::IterateResult CopyImageTest::iterate (void)
{
- void(CopyImageTest::*methods[])(void) =
+ // Note: Returning from iterate() has two side-effects: it touches
+ // watchdog and calls eglSwapBuffers. For the first it's important
+ // to keep work per iteration reasonable to avoid
+ // timeouts. Because of the latter, it's prudent to do more than
+ // trivial amount of work. Otherwise we'll end up waiting for a
+ // new buffer in swap, it seems.
+
+ // The split below tries to combine trivial work with actually
+ // expensive rendering iterations without having too much
+ // rendering in one iteration to avoid timeouts.
+ const IterationFunc iteration1[] =
{
&CopyImageTest::logTestInfoIter,
-
- // Render both images and then copy and verify again.
&CopyImageTest::createImagesIter,
- &CopyImageTest::verifySourceIter,
- &CopyImageTest::verifyDestinationIter,
+ &CopyImageTest::renderSourceIter
+ };
+ const IterationFunc iteration2[] =
+ {
+ &CopyImageTest::renderDestinationIter
+ };
+ const IterationFunc iteration3[] =
+ {
&CopyImageTest::copyImageIter,
- &CopyImageTest::verifySourceIter,
+ &CopyImageTest::verifySourceIter
+ };
+ const IterationFunc iteration4[] =
+ {
&CopyImageTest::verifyDestinationIter,
- &CopyImageTest::destroyImagesIter,
-
- // Create images and immediately copies between thew and verify.
+ &CopyImageTest::destroyImagesIter
+ };
+ const IterationFunc iteration5[] =
+ {
&CopyImageTest::createImagesIter,
&CopyImageTest::copyImageIter,
- &CopyImageTest::verifySourceIter,
+ &CopyImageTest::verifySourceIter
+ };
+ const IterationFunc iteration6[] =
+ {
&CopyImageTest::verifyDestinationIter,
&CopyImageTest::destroyImagesIter
};
+ const Iteration iterations[] =
+ {
+ Iteration(DE_LENGTH_OF_ARRAY(iteration1), iteration1),
+ Iteration(DE_LENGTH_OF_ARRAY(iteration2), iteration2),
+ Iteration(DE_LENGTH_OF_ARRAY(iteration3), iteration3),
+ Iteration(DE_LENGTH_OF_ARRAY(iteration4), iteration4),
+ Iteration(DE_LENGTH_OF_ARRAY(iteration5), iteration5),
+ Iteration(DE_LENGTH_OF_ARRAY(iteration6), iteration6)
+ };
+
+ DE_ASSERT(m_iteration < DE_LENGTH_OF_ARRAY(iterations));
+ for (int method = 0; method < iterations[m_iteration].methodCount; method++)
+ (this->*iterations[m_iteration].methods[method])();
- if (m_iteration < DE_LENGTH_OF_ARRAY(methods))
+ m_iteration++;
+
+ if (m_iteration < DE_LENGTH_OF_ARRAY(iterations))
{
- (this->*methods[m_iteration])();
- m_iteration++;
return CONTINUE;
}
else
const string targetTestName = string(targetToName(srcTarget)) + "_to_" + targetToName(dstTarget);
- const IVec3 targetSize2D (128, 128, 1);
- const IVec3 targetSize3D (128, 128, 16);
-
- const IVec3 srcSize = getTestedSize(srcTarget, srcFormat, (srcIs3D ? targetSize3D : targetSize2D));
- const IVec3 dstSize = getTestedSize(dstTarget, dstFormat, (dstIs3D ? targetSize3D : targetSize2D));
+ // Compressed formats require more space to fit all block size combinations.
+ const bool isCompressedCase = glu::isCompressedFormat(srcFormat) || glu::isCompressedFormat(dstFormat);
+ const IVec3 targetSize = isCompressedCase ? IVec3(128, 128, 16) : IVec3(64, 64, 8);
+ const IVec3 srcSize = getTestedSize(srcTarget, srcFormat, targetSize);
+ const IVec3 dstSize = getTestedSize(dstTarget, dstFormat, targetSize);
group->addChild(new CopyImageTest(root->getContext(),
ImageInfo(srcFormat, srcTarget, srcSize),
#include "es31fNegativeShaderImageLoadStoreTests.hpp"
#include "es31fNegativeShaderFunctionTests.hpp"
#include "es31fNegativeShaderDirectiveTests.hpp"
+#include "es31fNegativeSSBOBlockTests.hpp"
#include "es31fNegativePreciseTests.hpp"
#include "es31fNegativeAdvancedBlendEquationTests.hpp"
+#include "es31fNegativeShaderStorageTests.hpp"
+#include "es31fNegativeTessellationTests.hpp"
#include "deUniquePtr.hpp"
#include "deRandom.hpp"
const vector<FunctionContainer> fragmentFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeFragmentApiTestFunctions());
const vector<FunctionContainer> vaFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeVertexArrayApiTestFunctions());
const vector<FunctionContainer> stateFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeStateApiTestFunctions());
+ const vector<FunctionContainer> tessellationFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeTessellationTestFunctions());
const vector<FunctionContainer> atomicCounterFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeAtomicCounterTestFunctions());
const vector<FunctionContainer> imageLoadFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeShaderImageLoadTestFunctions());
const vector<FunctionContainer> imageStoreFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeShaderImageStoreTestFunctions());
const vector<FunctionContainer> imageAtomicExchangeFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeShaderImageAtomicExchangeTestFunctions());
const vector<FunctionContainer> shaderFunctionFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeShaderFunctionTestFunctions());
const vector<FunctionContainer> shaderDirectiveFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeShaderDirectiveTestFunctions());
+ const vector<FunctionContainer> ssboBlockFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeSSBOBlockTestFunctions());
const vector<FunctionContainer> preciseFuncs = wrapCoreFunctions(NegativeTestShared::getNegativePreciseTestFunctions());
const vector<FunctionContainer> advancedBlendFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeAdvancedBlendEquationTestFunctions());
+ const vector<FunctionContainer> shaderStorageFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeShaderStorageTestFunctions());
const vector<FunctionContainer> externalFuncs = getUserMessageFuncs();
{
host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader_image_exchange", "Negative Shader Image Atomic Exchange API Cases", imageAtomicExchangeFuncs));
host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader_function", "Negative Shader Function Cases", shaderFunctionFuncs));
host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader_directive", "Negative Shader Directive Cases", shaderDirectiveFuncs));
+ host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "ssbo_block", "Negative SSBO Block Cases", ssboBlockFuncs));
host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "precise", "Negative Precise Cases", preciseFuncs));
host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "advanced_blend", "Negative Advanced Blend Equation Cases", advancedBlendFuncs));
+ host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader_storage", "Negative Shader Storage Cases", shaderStorageFuncs));
+ host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "tessellation", "Negative Tessellation Cases", tessellationFuncs));
}
{
host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader_image_exchange", "Negative Shader Image Atomic Exchange API Cases", imageAtomicExchangeFuncs));
host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader_function", "Negative Shader Function Cases", shaderFunctionFuncs));
host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader_directive", "Negative Shader Directive Cases", shaderDirectiveFuncs));
+ host->addChild(createChildCases(CASETYPE_LOG, m_context, "ssbo_block", "Negative SSBO Block Cases", ssboBlockFuncs));
host->addChild(createChildCases(CASETYPE_LOG, m_context, "precise", "Negative Precise Cases", preciseFuncs));
host->addChild(createChildCases(CASETYPE_LOG, m_context, "advanced_blend", "Negative Advanced Blend Equation Cases", advancedBlendFuncs));
+ host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader_storage", "Negative Shader Storage Cases", shaderStorageFuncs));
+ host->addChild(createChildCases(CASETYPE_LOG, m_context, "tessellation", "Negative Tessellation Cases", tessellationFuncs));
}
{
host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader_image_exchange", "Negative Shader Image Atomic Exchange API Cases", imageAtomicExchangeFuncs));
host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader_function", "Negative Shader Function Cases", shaderFunctionFuncs));
host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader_directive", "Negative Shader Directive Cases", shaderDirectiveFuncs));
+ host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "ssbo_block", "Negative SSBO Block Cases", ssboBlockFuncs));
host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "precise", "Negative Precise Cases", preciseFuncs));
host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "advanced_blend", "Negative Advanced Blend Equation Cases", advancedBlendFuncs));
+ host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader_storage", "Negative Shader Storage Cases", shaderStorageFuncs));
+ host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "tessellation", "Negative Tessellation Cases", tessellationFuncs));
}
}
#include "es31fCopyImageTests.hpp"
#include "es31fDrawBuffersIndexedTests.hpp"
#include "es31fDefaultVertexArrayObjectTests.hpp"
+#include "es31fSRGBDecodeTests.hpp"
namespace deqp
{
}
};
+class SRGBTextureDecodeTests : public TestCaseGroup
+{
+public:
+ SRGBTextureDecodeTests (Context& context)
+ : TestCaseGroup (context, "srgb_texture_decode", "GL_EXT_texture_sRGB_decode tests")
+ {
+ }
+
+ void init (void)
+ {
+ addChild(new SRGBDecodeTests (m_context));
+ }
+};
+
FunctionalTests::FunctionalTests (Context& context)
: TestCaseGroup(context, "functional", "Functionality Tests")
{
addChild(createCopyImageTests (m_context));
addChild(createDrawBuffersIndexedTests (m_context));
addChild(new DefaultVertexArrayObjectTests (m_context));
+ addChild(new SRGBTextureDecodeTests (m_context));
}
} // Functional
FOR_EACH_VERIFIER(new MinimumValueCase(m_context, (std::string() + "max_tess_control_uniform_components_" + verifierSuffix).c_str(), "Test MAX_TESS_CONTROL_UNIFORM_COMPONENTS", GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS, 1024, verifier, glu::ApiType::es(3, 2)))
FOR_EACH_VERIFIER(new MinimumValueCase(m_context, (std::string() + "max_tess_control_texture_image_units_" + verifierSuffix).c_str(), "Test MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS", GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS, 16, verifier, glu::ApiType::es(3, 2)))
FOR_EACH_VERIFIER(new MinimumValueCase(m_context, (std::string() + "max_tess_control_output_components_" + verifierSuffix).c_str(), "Test MAX_TESS_CONTROL_OUTPUT_COMPONENTS", GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS, 64, verifier, glu::ApiType::es(3, 2)))
- FOR_EACH_VERIFIER(new MinimumValueCase(m_context, (std::string() + "max_tess_control_total_output_components_" + verifierSuffix).c_str(), "Test MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS", GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS, 4096, verifier, glu::ApiType::es(3, 2)))
+ FOR_EACH_VERIFIER(new MinimumValueCase(m_context, (std::string() + "max_tess_control_total_output_components_" + verifierSuffix).c_str(), "Test MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS", GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS, 2048, verifier, glu::ApiType::es(3, 2)))
FOR_EACH_VERIFIER(new MinimumValueCase(m_context, (std::string() + "max_tess_control_input_components_" + verifierSuffix).c_str(), "Test MAX_TESS_CONTROL_INPUT_COMPONENTS", GL_MAX_TESS_CONTROL_INPUT_COMPONENTS, 64, verifier, glu::ApiType::es(3, 2)))
FOR_EACH_VERIFIER(new MinimumValueCase(m_context, (std::string() + "max_tess_control_uniform_blocks_" + verifierSuffix).c_str(), "Test MAX_TESS_CONTROL_UNIFORM_BLOCKS", GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS, 12, verifier, glu::ApiType::es(3, 2)))
FOR_EACH_VERIFIER(new MinimumValueCase(m_context, (std::string() + "max_tess_control_atomic_counter_buffers_" + verifierSuffix).c_str(), "Test MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS", GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS, 0, verifier, glu::ApiType::es(3, 2)))
#include "gluShaderProgram.hpp"
#include "gluPixelTransfer.hpp"
#include "gluTextureUtil.hpp"
+#include "gluContextInfo.hpp"
#include "glwFunctions.hpp"
#include "glwEnums.hpp"
{
SHADERTYPE_VERTEX = 0,
SHADERTYPE_FRAGMENT,
- SHADERTYPE_BOTH,
+ SHADERTYPE_TESS_CONTROL,
+ SHADERTYPE_TESS_EVALUATION,
+ SHADERTYPE_ALL,
SHADERTYPE_LAST,
};
switch (shaderType)
{
case SHADERTYPE_VERTEX:
- case SHADERTYPE_BOTH:
+ case SHADERTYPE_ALL:
{
std::ostringstream vertexShaderSource;
vertexShaderSource << "#version 310 es\n"
}
case SHADERTYPE_FRAGMENT:
+ case SHADERTYPE_TESS_CONTROL:
+ case SHADERTYPE_TESS_EVALUATION:
return s_simpleVertexShaderSource;
default:
switch (shaderType)
{
case SHADERTYPE_VERTEX:
+ case SHADERTYPE_TESS_CONTROL:
+ case SHADERTYPE_TESS_EVALUATION:
return s_simpleFragmentShaderSource;
case SHADERTYPE_FRAGMENT:
return fragmentShaderSource.str();
}
- case SHADERTYPE_BOTH:
+ case SHADERTYPE_ALL:
{
std::ostringstream fragmentShaderSource;
fragmentShaderSource << "#version 310 es\n"
}
}
+std::string generateTessControlShader (ShaderType shaderType, const std::string& shaderUniformDeclarations, const std::string& shaderBody)
+{
+ static const char* const s_simpleTessContorlShaderSource = "#version 310 es\n"
+ "#extension GL_EXT_tessellation_shader : require\n"
+ "layout (vertices=3) out;\n"
+ "\n"
+ "void main (void)\n"
+ "{\n"
+ " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
+ "}\n";
+
+ switch (shaderType)
+ {
+ case SHADERTYPE_VERTEX:
+ case SHADERTYPE_FRAGMENT:
+ case SHADERTYPE_TESS_EVALUATION:
+ return s_simpleTessContorlShaderSource;
+
+ case SHADERTYPE_TESS_CONTROL:
+ case SHADERTYPE_ALL:
+ {
+ std::ostringstream tessControlShaderSource;
+ tessControlShaderSource << "#version 310 es\n"
+ << "#extension GL_EXT_tessellation_shader : require\n"
+ << "layout (vertices=3) out;\n"
+ << "\n"
+ << "uniform highp int u_arrayNdx;\n\n"
+ << shaderUniformDeclarations << "\n"
+ << "void main (void)\n"
+ << "{\n"
+ << " highp vec4 color;\n\n"
+ << shaderBody << "\n"
+ << " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
+ << "}\n";
+
+ return tessControlShaderSource.str();
+ }
+
+ default:
+ DE_ASSERT(false);
+ return "";
+ }
+}
+
+std::string generateTessEvaluationShader (ShaderType shaderType, const std::string& shaderUniformDeclarations, const std::string& shaderBody)
+{
+ static const char* const s_simpleTessEvaluationShaderSource = "#version 310 es\n"
+ "#extension GL_EXT_tessellation_shader : require\n"
+ "layout (triangles) in;\n"
+ "\n"
+ "void main (void)\n"
+ "{\n"
+ " gl_Position = gl_TessCoord[0] * gl_in[0].gl_Position + gl_TessCoord[1] * gl_in[1].gl_Position + gl_TessCoord[2] * gl_in[2].gl_Position;\n"
+ "}\n";
+
+ switch (shaderType)
+ {
+ case SHADERTYPE_VERTEX:
+ case SHADERTYPE_FRAGMENT:
+ case SHADERTYPE_TESS_CONTROL:
+ return s_simpleTessEvaluationShaderSource;
+
+ case SHADERTYPE_TESS_EVALUATION:
+ case SHADERTYPE_ALL:
+ {
+ std::ostringstream tessEvaluationShaderSource;
+ tessEvaluationShaderSource << "#version 310 es\n"
+ << "#extension GL_EXT_tessellation_shader : require\n"
+ << "layout (triangles) in;\n"
+ << "\n"
+ << "uniform highp int u_arrayNdx;\n\n"
+ << shaderUniformDeclarations << "\n"
+ << "out mediump vec4 v_color;\n"
+ << "void main (void)\n"
+ << "{\n"
+ << " highp vec4 color;\n\n"
+ << shaderBody << "\n"
+ << " v_color = color;\n"
+ << " gl_Position = gl_TessCoord[0] * gl_in[0].gl_Position + gl_TessCoord[1] * gl_in[1].gl_Position + gl_TessCoord[2] * gl_in[2].gl_Position;\n"
+ << "}\n";
+
+ return tessEvaluationShaderSource.str();
+ }
+
+ default:
+ DE_ASSERT(false);
+ return "";
+ }
+}
+
std::string getUniformName (const std::string& name, int declNdx)
{
return name + de::toString(declNdx);
maxUnits = maxFragmentUnits;
break;
- case SHADERTYPE_BOTH:
+ case SHADERTYPE_ALL:
maxUnits = maxCombinedUnits/2;
break;
}
// Check that we have enough uniforms in different shaders to perform the tests
- if ( ((m_shaderType == SHADERTYPE_VERTEX) || (m_shaderType == SHADERTYPE_BOTH)) && (maxVertexUnits < m_numBindings) )
+ if ( ((m_shaderType == SHADERTYPE_VERTEX) || (m_shaderType == SHADERTYPE_ALL)) && (maxVertexUnits < m_numBindings) )
throw tcu::NotSupportedError("Vertex shader: not enough uniforms available for test");
- if ( ((m_shaderType == SHADERTYPE_FRAGMENT) || (m_shaderType == SHADERTYPE_BOTH)) && (maxFragmentUnits < m_numBindings) )
+ if ( ((m_shaderType == SHADERTYPE_FRAGMENT) || (m_shaderType == SHADERTYPE_ALL)) && (maxFragmentUnits < m_numBindings) )
throw tcu::NotSupportedError("Fragment shader: not enough uniforms available for test");
- if ( (m_shaderType == SHADERTYPE_BOTH) && (maxCombinedUnits < m_numBindings*2) )
+ if ( (m_shaderType == SHADERTYPE_ALL) && (maxCombinedUnits < m_numBindings*2) )
throw tcu::NotSupportedError("Not enough uniforms available for test");
// Check that we have enough binding points to perform the tests
glw::GLenum maxBindingPointEnum,
glw::GLenum maxVertexUnitsEnum,
glw::GLenum maxFragmentUnitsEnum,
+ glw::GLenum maxTessCtrlUnitsEnum,
+ glw::GLenum maxTessEvalUnitsEnum,
glw::GLenum maxCombinedUnitsEnum,
const std::string& uniformName);
virtual ~LayoutBindingNegativeCase (void);
const glw::GLenum m_maxBindingPointEnum;
const glw::GLenum m_maxVertexUnitsEnum;
const glw::GLenum m_maxFragmentUnitsEnum;
+ const glw::GLenum m_maxTessCtrlUnitsEnum;
+ const glw::GLenum m_maxTessEvalUnitsEnum;
const glw::GLenum m_maxCombinedUnitsEnum;
const std::string m_uniformName;
glw::GLint m_numBindings;
std::vector<glw::GLint> m_vertexShaderBinding;
std::vector<glw::GLint> m_fragmentShaderBinding;
+ std::vector<glw::GLint> m_tessCtrlShaderBinding;
+ std::vector<glw::GLint> m_tessEvalShaderBinding;
+ bool m_tessSupport;
private:
void initBindingPoints (int minBindingPoint, int numBindingPoints);
ErrorType errorType,
glw::GLenum maxBindingPointEnum,
glw::GLenum maxVertexUnitsEnum,
+ glw::GLenum maxTessCtrlUnitsEnum,
+ glw::GLenum maxTessEvalUnitsEnum,
glw::GLenum maxFragmentUnitsEnum,
glw::GLenum maxCombinedUnitsEnum,
const std::string& uniformName)
, m_maxBindingPointEnum (maxBindingPointEnum)
, m_maxVertexUnitsEnum (maxVertexUnitsEnum)
, m_maxFragmentUnitsEnum (maxFragmentUnitsEnum)
+ , m_maxTessCtrlUnitsEnum (maxTessCtrlUnitsEnum)
+ , m_maxTessEvalUnitsEnum (maxTessEvalUnitsEnum)
, m_maxCombinedUnitsEnum (maxCombinedUnitsEnum)
, m_uniformName (uniformName)
, m_numBindings (0)
+ , m_tessSupport (false)
{
}
glw::GLint maxVertexUnits = 0; // Available uniforms in the vertex shader
glw::GLint maxFragmentUnits = 0; // Available uniforms in the fragment shader
glw::GLint maxCombinedUnits = 0; // Available uniforms in all the shader stages combined
+ glw::GLint maxTessCtrlUnits = 0; // Available uniforms in tessellation control shader
+ glw::GLint maxTessEvalUnits = 0; // Available uniforms in tessellation evaluation shader
glw::GLint maxUnits = 0; // Maximum available uniforms for this test
+ m_tessSupport = m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader")
+ || contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
+
+ if (!m_tessSupport && (m_shaderType == SHADERTYPE_TESS_EVALUATION || m_shaderType == SHADERTYPE_TESS_CONTROL))
+ TCU_THROW(NotSupportedError, "Tesselation shaders not supported");
+
+ int numShaderStages = m_tessSupport ? 4 : 2;
+
gl.getIntegerv(m_maxVertexUnitsEnum, &maxVertexUnits);
gl.getIntegerv(m_maxFragmentUnitsEnum, &maxFragmentUnits);
+
+ if (m_tessSupport)
+ {
+ gl.getIntegerv(m_maxTessCtrlUnitsEnum, &maxTessCtrlUnits);
+ gl.getIntegerv(m_maxTessEvalUnitsEnum, &maxTessEvalUnits);
+ }
+
gl.getIntegerv(m_maxCombinedUnitsEnum, &maxCombinedUnits);
gl.getIntegerv(m_maxBindingPointEnum, &numBindingPoints);
GLU_EXPECT_NO_ERROR(gl.getError(), "Querying available uniform numbers failed");
m_testCtx.getLog() << tcu::TestLog::Message << "Maximum units for uniform type in the vertex shader: " << maxVertexUnits << tcu::TestLog::EndMessage;
m_testCtx.getLog() << tcu::TestLog::Message << "Maximum units for uniform type in the fragment shader: " << maxFragmentUnits << tcu::TestLog::EndMessage;
+
+ if (m_tessSupport)
+ {
+ m_testCtx.getLog() << tcu::TestLog::Message << "Maximum units for uniform type in the tessellation control shader: " << maxTessCtrlUnits << tcu::TestLog::EndMessage;
+ m_testCtx.getLog() << tcu::TestLog::Message << "Maximum units for uniform type in the tessellation evaluation shader: " << maxTessCtrlUnits << tcu::TestLog::EndMessage;
+ }
+
m_testCtx.getLog() << tcu::TestLog::Message << "Maximum combined units for uniform type: " << maxCombinedUnits << tcu::TestLog::EndMessage;
m_testCtx.getLog() << tcu::TestLog::Message << "Maximum binding point for uniform type: " << numBindingPoints-1 << tcu::TestLog::EndMessage;
maxUnits = maxFragmentUnits;
break;
- case SHADERTYPE_BOTH:
- maxUnits = de::min(de::min(maxVertexUnits, maxFragmentUnits), maxCombinedUnits/2);
+ case SHADERTYPE_ALL:
+ maxUnits = de::min(de::min(de::min(maxVertexUnits, maxFragmentUnits), de::min(maxTessCtrlUnits, maxTessEvalUnits)), maxCombinedUnits/numShaderStages);
+ break;
+
+ case SHADERTYPE_TESS_CONTROL:
+ maxUnits = maxTessCtrlUnits;
+ break;
+
+ case SHADERTYPE_TESS_EVALUATION:
+ maxUnits = maxTessEvalUnits;
break;
default:
{
// leave room for contradictory case
if (maxUnits < 3)
- throw tcu::NotSupportedError("Not enough uniforms available for test");
+ TCU_THROW(NotSupportedError, "Not enough uniforms available for test");
m_numBindings = rnd.getInt(2, deMin32(MAX_UNIFORM_ARRAY_SIZE, maxUnits-1));
}
else
{
if (maxUnits < 2)
- throw tcu::NotSupportedError("Not enough uniforms available for test");
+ TCU_THROW(NotSupportedError, "Not enough uniforms available for test");
m_numBindings = rnd.getInt(2, deMin32(MAX_UNIFORM_ARRAY_SIZE, maxUnits));
}
break;
}
// Check that we have enough uniforms in different shaders to perform the tests
- if ( ((m_shaderType == SHADERTYPE_VERTEX) || (m_shaderType == SHADERTYPE_BOTH)) && (maxVertexUnits < m_numBindings) )
- throw tcu::NotSupportedError("Vertex shader: not enough uniforms available for test");
- if ( ((m_shaderType == SHADERTYPE_FRAGMENT) || (m_shaderType == SHADERTYPE_BOTH)) && (maxFragmentUnits < m_numBindings) )
- throw tcu::NotSupportedError("Fragment shader: not enough uniforms available for test");
- if ( (m_shaderType == SHADERTYPE_BOTH) && (maxCombinedUnits < m_numBindings*2) )
- throw tcu::NotSupportedError("Not enough uniforms available for test");
+ if (((m_shaderType == SHADERTYPE_VERTEX) || (m_shaderType == SHADERTYPE_ALL)) && (maxVertexUnits < m_numBindings) )
+ TCU_THROW(NotSupportedError, "Vertex shader: not enough uniforms available for test");
+
+ if (((m_shaderType == SHADERTYPE_FRAGMENT) || (m_shaderType == SHADERTYPE_ALL)) && (maxFragmentUnits < m_numBindings) )
+ TCU_THROW(NotSupportedError, "Fragment shader: not enough uniforms available for test");
+
+ if (m_tessSupport && ((m_shaderType == SHADERTYPE_TESS_CONTROL) || (m_shaderType == SHADERTYPE_ALL)) && (maxTessCtrlUnits < m_numBindings) )
+ TCU_THROW(NotSupportedError, "Tessellation control shader: not enough uniforms available for test");
+
+ if (m_tessSupport && ((m_shaderType == SHADERTYPE_TESS_EVALUATION) || (m_shaderType == SHADERTYPE_ALL)) && (maxTessEvalUnits < m_numBindings) )
+ TCU_THROW(NotSupportedError, "Tessellation evaluation shader: not enough uniforms available for test");
+
+ if ((m_shaderType == SHADERTYPE_ALL) && (maxCombinedUnits < m_numBindings*numShaderStages) )
+ TCU_THROW(NotSupportedError, "Not enough uniforms available for test");
// Check that we have enough binding points to perform the tests
if (numBindingPoints < m_numBindings)
- throw tcu::NotSupportedError("Not enough binding points available for test");
+ TCU_THROW(NotSupportedError, "Not enough binding points available for test");
+
if (m_errorType == ERRORTYPE_CONTRADICTORY && numBindingPoints == m_numBindings)
- throw tcu::NotSupportedError("Not enough binding points available for test");
+ TCU_THROW(NotSupportedError, "Not enough binding points available for test");
// Initialize the binding points i.e. populate the two binding point vectors
initBindingPoints(0, numBindingPoints);
case ERRORTYPE_LESS_THAN_ZERO: // Out of bounds binding points should cause a compile-time error
case ERRORTYPE_OVER_MAX_UNITS:
- if (!(m_program->getShaderInfo(glu::SHADERTYPE_VERTEX)).compileOk || !(m_program->getShaderInfo(glu::SHADERTYPE_FRAGMENT)).compileOk)
- pass = true;
+ if (m_tessSupport)
+ {
+ if (!(m_program->getShaderInfo(glu::SHADERTYPE_VERTEX)).compileOk
+ || !(m_program->getShaderInfo(glu::SHADERTYPE_FRAGMENT).compileOk)
+ || !(m_program->getShaderInfo(glu::SHADERTYPE_TESSELLATION_CONTROL).compileOk)
+ || !(m_program->getShaderInfo(glu::SHADERTYPE_TESSELLATION_EVALUATION)).compileOk)
+ pass = true;
+ }
+ else
+ {
+ if (!(m_program->getShaderInfo(glu::SHADERTYPE_VERTEX)).compileOk
+ || !(m_program->getShaderInfo(glu::SHADERTYPE_FRAGMENT).compileOk))
+ pass = true;
+ }
+
failMessage = "Test failed - expected a compile-time error";
break;
{
m_vertexShaderBinding.push_back(numBindingPoints+1-m_numBindings);
m_fragmentShaderBinding.push_back(numBindingPoints+1-m_numBindings);
+ m_tessCtrlShaderBinding.push_back(numBindingPoints+1-m_numBindings);
+ m_tessEvalShaderBinding.push_back(numBindingPoints+1-m_numBindings);
break;
}
const glw::GLint binding = -rnd.getInt(1, m_numBindings);
m_vertexShaderBinding.push_back(binding);
m_fragmentShaderBinding.push_back(binding);
+ m_tessCtrlShaderBinding.push_back(binding);
+ m_tessEvalShaderBinding.push_back(binding);
break;
}
{
m_vertexShaderBinding.push_back(minBindingPoint);
m_fragmentShaderBinding.push_back((minBindingPoint+1)%numBindingPoints);
- DE_ASSERT(m_vertexShaderBinding.back() != m_fragmentShaderBinding.back());
+ m_tessCtrlShaderBinding.push_back((minBindingPoint+2)%numBindingPoints);
+ m_tessEvalShaderBinding.push_back((minBindingPoint+3)%numBindingPoints);
+
+ DE_ASSERT(m_vertexShaderBinding.back() != m_fragmentShaderBinding.back());
+ DE_ASSERT(m_fragmentShaderBinding.back() != m_tessEvalShaderBinding.back());
+ DE_ASSERT(m_tessEvalShaderBinding.back() != m_tessCtrlShaderBinding.back());
+ DE_ASSERT(m_tessCtrlShaderBinding.back() != m_vertexShaderBinding.back());
+ DE_ASSERT(m_vertexShaderBinding.back() != m_tessEvalShaderBinding.back());
+ DE_ASSERT(m_tessCtrlShaderBinding.back() != m_fragmentShaderBinding.back());
break;
}
{
m_vertexShaderBinding.push_back(m_vertexShaderBinding.front()+ndx);
m_fragmentShaderBinding.push_back(m_fragmentShaderBinding.front()+ndx);
+ m_tessCtrlShaderBinding.push_back(m_tessCtrlShaderBinding.front()+ndx);
+ m_tessEvalShaderBinding.push_back(m_tessCtrlShaderBinding.front()+ndx);
}
}
TestType testType,
ErrorType errorType,
glw::GLenum samplerType)
- : LayoutBindingNegativeCase (context, name, desc, shaderType, testType, errorType, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, GL_MAX_TEXTURE_IMAGE_UNITS, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, "u_sampler")
+ : LayoutBindingNegativeCase (context,
+ name,
+ desc,
+ shaderType,
+ testType,
+ errorType,
+ GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
+ GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS,
+ GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS,
+ GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS,
+ GL_MAX_TEXTURE_IMAGE_UNITS,
+ GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
+ "u_sampler")
, m_samplerType (samplerType)
{
}
{
std::ostringstream vertexUniformDecl;
std::ostringstream fragmentUniformDecl;
+ std::ostringstream tessCtrlUniformDecl;
+ std::ostringstream tessEvalUniformDecl;
std::ostringstream shaderBody;
const std::string texCoordType = glu::getDataTypeName(getSamplerTexCoordType());
<< " " << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) : getUniformName(m_uniformName, declNdx)) << ";\n";
fragmentUniformDecl << "layout(binding = " << m_fragmentShaderBinding[declNdx] << ") uniform highp " << samplerType
<< " " << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) : getUniformName(m_uniformName, declNdx)) << ";\n";
+ tessCtrlUniformDecl << "layout(binding = " << m_tessCtrlShaderBinding[declNdx] << ") uniform highp " << samplerType
+ << " " << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) : getUniformName(m_uniformName, declNdx)) << ";\n";
+ tessEvalUniformDecl << "layout(binding = " << m_tessEvalShaderBinding[declNdx] << ") uniform highp " << samplerType
+ << " " << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) : getUniformName(m_uniformName, declNdx)) << ";\n";
}
// Generate the shader body for the vertex and fragment shaders
<< " color = vec4(0.0, 0.0, 0.0, 1.0);\n"
<< " }\n";
- return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources()
+ glu::ProgramSources sources = glu::ProgramSources()
<< glu::VertexSource(generateVertexShader(m_shaderType, vertexUniformDecl.str(), shaderBody.str()))
- << glu::FragmentSource(generateFragmentShader(m_shaderType, fragmentUniformDecl.str(), shaderBody.str())));
+ << glu::FragmentSource(generateFragmentShader(m_shaderType, fragmentUniformDecl.str(), shaderBody.str()));
+
+ if (m_tessSupport)
+ sources << glu::TessellationControlSource(generateTessControlShader(m_shaderType, tessCtrlUniformDecl.str(), shaderBody.str()))
+ << glu::TessellationEvaluationSource(generateTessEvaluationShader(m_shaderType, tessEvalUniformDecl.str(), shaderBody.str()));
+
+ return new glu::ShaderProgram(m_context.getRenderContext(), sources);
+
}
glu::DataType SamplerBindingNegativeCase::getSamplerTexCoordType(void) const
TestType testType,
ErrorType errorType,
glw::GLenum imageType)
- : LayoutBindingNegativeCase (context, name, desc, shaderType, testType, errorType, GL_MAX_IMAGE_UNITS, GL_MAX_VERTEX_IMAGE_UNIFORMS, GL_MAX_FRAGMENT_IMAGE_UNIFORMS, GL_MAX_COMBINED_IMAGE_UNIFORMS, "u_image")
+ : LayoutBindingNegativeCase (context,
+ name,
+ desc,
+ shaderType,
+ testType,
+ errorType,
+ GL_MAX_IMAGE_UNITS,
+ GL_MAX_VERTEX_IMAGE_UNIFORMS,
+ GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS,
+ GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS,
+ GL_MAX_FRAGMENT_IMAGE_UNIFORMS,
+ GL_MAX_COMBINED_IMAGE_UNIFORMS,
+ "u_image")
, m_imageType (imageType)
{
}
{
std::ostringstream vertexUniformDecl;
std::ostringstream fragmentUniformDecl;
+ std::ostringstream tessCtrlUniformDecl;
+ std::ostringstream tessEvalUniformDecl;
std::ostringstream shaderBody;
const std::string texCoordType = glu::getDataTypeName(getImageTexCoordType());
<< " " << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) : getUniformName(m_uniformName, declNdx)) << ";\n";
fragmentUniformDecl << "layout(rgba8, binding = " << m_fragmentShaderBinding[declNdx] << ") uniform readonly highp " << imageType
<< " " << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) : getUniformName(m_uniformName, declNdx)) << ";\n";
+ tessCtrlUniformDecl << "layout(rgba8, binding = " << m_tessCtrlShaderBinding[declNdx] << ") uniform readonly highp " << imageType
+ << " " << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) : getUniformName(m_uniformName, declNdx)) << ";\n";
+ tessEvalUniformDecl << "layout(rgba8, binding = " << m_tessEvalShaderBinding[declNdx] << ") uniform readonly highp " << imageType
+ << " " << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) : getUniformName(m_uniformName, declNdx)) << ";\n";
}
// Generate the shader body for the vertex and fragment shaders
<< " color = vec4(0.0, 0.0, 0.0, 1.0);\n"
<< " }\n";
- return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources()
- << glu::VertexSource(generateVertexShader(m_shaderType, vertexUniformDecl.str(), shaderBody.str()))
- << glu::FragmentSource(generateFragmentShader(m_shaderType, fragmentUniformDecl.str(), shaderBody.str())));
+ glu::ProgramSources sources = glu::ProgramSources()
+ << glu::VertexSource(generateVertexShader(m_shaderType, vertexUniformDecl.str(), shaderBody.str()))
+ << glu::FragmentSource(generateFragmentShader(m_shaderType, fragmentUniformDecl.str(), shaderBody.str()));
+
+ if (m_tessSupport)
+ sources << glu::TessellationControlSource(generateTessControlShader(m_shaderType, tessCtrlUniformDecl.str(), shaderBody.str()))
+ << glu::TessellationEvaluationSource(generateTessEvaluationShader(m_shaderType, tessEvalUniformDecl.str(), shaderBody.str()));
+
+ return new glu::ShaderProgram(m_context.getRenderContext(), sources);
}
glu::DataType ImageBindingNegativeCase::getImageTexCoordType(void) const
ShaderType shaderType,
TestType testType,
ErrorType errorType)
- : LayoutBindingNegativeCase(context, name, desc, shaderType, testType, errorType, GL_MAX_UNIFORM_BUFFER_BINDINGS, GL_MAX_VERTEX_UNIFORM_BLOCKS, GL_MAX_FRAGMENT_UNIFORM_BLOCKS, GL_MAX_COMBINED_UNIFORM_BLOCKS, "ColorBlock")
+ : LayoutBindingNegativeCase(context,
+ name,
+ desc,
+ shaderType,
+ testType,
+ errorType,
+ GL_MAX_UNIFORM_BUFFER_BINDINGS,
+ GL_MAX_VERTEX_UNIFORM_BLOCKS,
+ GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS,
+ GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS,
+ GL_MAX_FRAGMENT_UNIFORM_BLOCKS,
+ GL_MAX_COMBINED_UNIFORM_BLOCKS,
+ "ColorBlock")
{
}
{
std::ostringstream vertexUniformDecl;
std::ostringstream fragmentUniformDecl;
+ std::ostringstream tessCtrlUniformDecl;
+ std::ostringstream tessEvalUniformDecl;
std::ostringstream shaderBody;
const bool arrayInstance = (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY);
const int numDeclarations = (arrayInstance ? 1 : m_numBindings);
<< " highp vec4 color1;\n"
<< " highp vec4 color2;\n"
<< "} " << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) : getUniformName("colors", declNdx)) << ";\n";
+
+ tessCtrlUniformDecl << "layout(std140, binding = " << m_tessCtrlShaderBinding[declNdx] << ") uniform "
+ << getUniformName(m_uniformName, declNdx) << "\n"
+ << "{\n"
+ << " highp vec4 color1;\n"
+ << " highp vec4 color2;\n"
+ << "} " << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) : getUniformName("colors", declNdx)) << ";\n";
+
+ tessEvalUniformDecl << "layout(std140, binding = " << m_tessCtrlShaderBinding[declNdx] << ") uniform "
+ << getUniformName(m_uniformName, declNdx) << "\n"
+ << "{\n"
+ << " highp vec4 color1;\n"
+ << " highp vec4 color2;\n"
+ << "} " << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) : getUniformName("colors", declNdx)) << ";\n";
}
// Generate the shader body for the vertex and fragment shaders
<< " color = vec4(0.0, 0.0, 0.0, 1.0);\n"
<< " }\n";
- return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources()
- << glu::VertexSource(generateVertexShader(m_shaderType, vertexUniformDecl.str(), shaderBody.str()))
- << glu::FragmentSource(generateFragmentShader(m_shaderType, fragmentUniformDecl.str(), shaderBody.str())));
+ glu::ProgramSources sources = glu::ProgramSources()
+ << glu::VertexSource(generateVertexShader(m_shaderType, vertexUniformDecl.str(), shaderBody.str()))
+ << glu::FragmentSource(generateFragmentShader(m_shaderType, fragmentUniformDecl.str(), shaderBody.str()));
+
+ if (m_tessSupport)
+ sources << glu::TessellationControlSource(generateTessControlShader(m_shaderType, tessCtrlUniformDecl.str(), shaderBody.str()))
+ << glu::TessellationEvaluationSource(generateTessEvaluationShader(m_shaderType, tessEvalUniformDecl.str(), shaderBody.str()));
+
+ return new glu::ShaderProgram(m_context.getRenderContext(), sources);
}
ShaderType shaderType,
TestType testType,
ErrorType errorType)
- : LayoutBindingNegativeCase(context, name, desc, shaderType, testType, errorType, GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, "ColorBuffer")
+ : LayoutBindingNegativeCase(context,
+ name,
+ desc,
+ shaderType,
+ testType,
+ errorType,
+ GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS,
+ GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS,
+ GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS,
+ GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS,
+ GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS,
+ GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS,
+ "ColorBuffer")
{
}
{
std::ostringstream vertexUniformDecl;
std::ostringstream fragmentUniformDecl;
+ std::ostringstream tessCtrlUniformDecl;
+ std::ostringstream tessEvalUniformDecl;
std::ostringstream shaderBody;
const bool arrayInstance = (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY);
const int numDeclarations = (arrayInstance ? 1 : m_numBindings);
<< " highp vec4 color1;\n"
<< " highp vec4 color2;\n"
<< "} " << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) : getUniformName("colors", declNdx)) << ";\n";
+
+ tessCtrlUniformDecl << "layout(std140, binding = " << m_tessCtrlShaderBinding[declNdx] << ") buffer "
+ << getUniformName(m_uniformName, declNdx) << "\n"
+ << "{\n"
+ << " highp vec4 color1;\n"
+ << " highp vec4 color2;\n"
+ << "} " << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) : getUniformName("colors", declNdx)) << ";\n";
+
+ tessEvalUniformDecl << "layout(std140, binding = " << m_tessEvalShaderBinding[declNdx] << ") buffer "
+ << getUniformName(m_uniformName, declNdx) << "\n"
+ << "{\n"
+ << " highp vec4 color1;\n"
+ << " highp vec4 color2;\n"
+ << "} " << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) : getUniformName("colors", declNdx)) << ";\n";
}
// Generate the shader body for the vertex and fragment shaders
<< " color = vec4(0.0, 0.0, 0.0, 1.0);\n"
<< " }\n";
- return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources()
- << glu::VertexSource(generateVertexShader(m_shaderType, vertexUniformDecl.str(), shaderBody.str()))
- << glu::FragmentSource(generateFragmentShader(m_shaderType, fragmentUniformDecl.str(), shaderBody.str())));
+ glu::ProgramSources sources = glu::ProgramSources()
+ << glu::VertexSource(generateVertexShader(m_shaderType, vertexUniformDecl.str(), shaderBody.str()))
+ << glu::FragmentSource(generateFragmentShader(m_shaderType, fragmentUniformDecl.str(), shaderBody.str()));
+
+ if (m_tessSupport)
+ sources << glu::TessellationControlSource(generateTessControlShader(m_shaderType, tessCtrlUniformDecl.str(), shaderBody.str()))
+ << glu::TessellationEvaluationSource(generateTessEvaluationShader(m_shaderType, tessEvalUniformDecl.str(), shaderBody.str()));
+
+ return new glu::ShaderProgram(m_context.getRenderContext(), sources);
}
std::string descPostfix;
} s_negativeTestTypes[] =
{
- { SHADERTYPE_VERTEX, TESTTYPE_BINDING_SINGLE, LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS, "vertex_binding_over_max", "over maximum binding point"},
- { SHADERTYPE_FRAGMENT, TESTTYPE_BINDING_SINGLE, LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS, "fragment_binding_over_max", "over maximum binding point"},
- { SHADERTYPE_VERTEX, TESTTYPE_BINDING_SINGLE, LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO, "vertex_binding_neg", "negative binding point"},
- { SHADERTYPE_FRAGMENT, TESTTYPE_BINDING_SINGLE, LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO, "fragment_binding_neg", "negative binding point"},
-
- { SHADERTYPE_VERTEX, TESTTYPE_BINDING_ARRAY, LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS, "vertex_binding_over_max_array", "over maximum binding point"},
- { SHADERTYPE_FRAGMENT, TESTTYPE_BINDING_ARRAY, LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS, "fragment_binding_over_max_array", "over maximum binding point"},
- { SHADERTYPE_VERTEX, TESTTYPE_BINDING_ARRAY, LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO, "vertex_binding_neg_array", "negative binding point"},
- { SHADERTYPE_FRAGMENT, TESTTYPE_BINDING_ARRAY, LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO, "fragment_binding_neg_array", "negative binding point"},
-
- { SHADERTYPE_BOTH, TESTTYPE_BINDING_SINGLE, LayoutBindingNegativeCase::ERRORTYPE_CONTRADICTORY, "binding_contradictory", "contradictory binding points"},
- { SHADERTYPE_BOTH, TESTTYPE_BINDING_ARRAY, LayoutBindingNegativeCase::ERRORTYPE_CONTRADICTORY, "binding_contradictory_array", "contradictory binding points"},
+ { SHADERTYPE_VERTEX, TESTTYPE_BINDING_SINGLE, LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS, "vertex_binding_over_max", "over maximum binding point" },
+ { SHADERTYPE_FRAGMENT, TESTTYPE_BINDING_SINGLE, LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS, "fragment_binding_over_max", "over maximum binding point" },
+ { SHADERTYPE_TESS_CONTROL, TESTTYPE_BINDING_SINGLE, LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS, "tess_control_binding_over_max", "over maximum binding point" },
+ { SHADERTYPE_TESS_EVALUATION, TESTTYPE_BINDING_SINGLE, LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS, "tess_evaluation_binding_over_max", "over maximum binding point" },
+ { SHADERTYPE_VERTEX, TESTTYPE_BINDING_SINGLE, LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO, "vertex_binding_neg", "negative binding point" },
+ { SHADERTYPE_FRAGMENT, TESTTYPE_BINDING_SINGLE, LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO, "fragment_binding_neg", "negative binding point" },
+ { SHADERTYPE_TESS_CONTROL, TESTTYPE_BINDING_SINGLE, LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO, "tess_control_binding_neg", "negative binding point" },
+ { SHADERTYPE_TESS_EVALUATION, TESTTYPE_BINDING_SINGLE, LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO, "tess_evaluation_binding_neg", "negative binding point" },
+
+ { SHADERTYPE_VERTEX, TESTTYPE_BINDING_ARRAY, LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS, "vertex_binding_over_max_array", "over maximum binding point" },
+ { SHADERTYPE_FRAGMENT, TESTTYPE_BINDING_ARRAY, LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS, "fragment_binding_over_max_array", "over maximum binding point" },
+ { SHADERTYPE_TESS_CONTROL, TESTTYPE_BINDING_ARRAY, LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS, "tess_control_binding_over_max_array", "over maximum binding point" },
+ { SHADERTYPE_TESS_EVALUATION, TESTTYPE_BINDING_ARRAY, LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS, "tess_evaluation_binding_over_max_array", "over maximum binding point" },
+ { SHADERTYPE_VERTEX, TESTTYPE_BINDING_ARRAY, LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO, "vertex_binding_neg_array", "negative binding point" },
+ { SHADERTYPE_FRAGMENT, TESTTYPE_BINDING_ARRAY, LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO, "fragment_binding_neg_array", "negative binding point" },
+ { SHADERTYPE_TESS_CONTROL, TESTTYPE_BINDING_ARRAY, LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO, "tess_control_binding_neg_array", "negative binding point" },
+ { SHADERTYPE_TESS_EVALUATION, TESTTYPE_BINDING_ARRAY, LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO, "tess_evaluation_binding_neg_array", "negative binding point" },
+
+ { SHADERTYPE_ALL, TESTTYPE_BINDING_SINGLE, LayoutBindingNegativeCase::ERRORTYPE_CONTRADICTORY, "binding_contradictory", "contradictory binding points" },
+ { SHADERTYPE_ALL, TESTTYPE_BINDING_ARRAY, LayoutBindingNegativeCase::ERRORTYPE_CONTRADICTORY, "binding_contradictory_array", "contradictory binding points" },
};
// Render tests
void readn_pixels (NegativeTestContext& ctx)
{
+ std::vector<GLfloat> floatData (4);
std::vector<GLubyte> ubyteData (4);
GLuint fbo = 0x1234;
ctx.beginSection("GL_INVALID_OPERATION is generated by ReadnPixels if the buffer size required to store the requested data is larger than bufSize.");
ctx.glReadnPixels(0, 0, 0x1234, 0x1234, GL_RGBA, GL_UNSIGNED_BYTE, (int) ubyteData.size(), &ubyteData[0]);
ctx.expectError(GL_INVALID_OPERATION);
+ ctx.glReadnPixels(0, 0, 1, 1, GL_RGBA, GL_FLOAT, (int) floatData.size(), &floatData[0]);
+ ctx.expectError(GL_INVALID_OPERATION);
ctx.endSection();
ctx.beginSection("GL_INVALID_FRAMEBUFFER_OPERATION is generated if the currently bound framebuffer is not framebuffer complete.");
{
std::vector<GLubyte> ubyteData (4);
std::vector<GLushort> ushortData (4);
- std::vector<GLfloat> floatData (4);
GLint readFormat = 0x1234;
GLint readType = 0x1234;
ctx.expectError(GL_INVALID_OPERATION);
ctx.glReadPixels(0, 0, 1, 1, GL_ALPHA, GL_UNSIGNED_SHORT_5_5_5_1, &ushortData[0]);
ctx.expectError(GL_INVALID_OPERATION);
- ctx.glReadnPixels(0, 0, 1, 1, GL_RGBA, GL_FLOAT, (int) floatData.size(), &floatData[0]);
- ctx.expectError(GL_INVALID_OPERATION);
ctx.endSection();
ctx.beginSection("GL_RGBA/GL_UNSIGNED_BYTE is always accepted and the other acceptable pair can be discovered by querying GL_IMPLEMENTATION_COLOR_READ_FORMAT and GL_IMPLEMENTATION_COLOR_READ_TYPE.");
ctx.endSection();
ctx.beginSection("GL_INVALID_VALUE is generated if target is GL_ATOMIC_COUNTER_BUFFER and offset is not multiples of 4.");
- ctx.glBindBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, bufTF, 5, 0);
+ ctx.glBindBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, bufTF, 5, 4);
ctx.expectError(GL_INVALID_VALUE);
ctx.endSection();
- ctx.beginSection("GL_INVALID_VALUE is generated if target is GL_SHADER_STORAGE_BUFFER and offset is not a multiple of the value of GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT.");
ctx.glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &ssAlignment);
- ctx.glBindBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, bufTF, ssAlignment+1, 0);
- ctx.expectError(GL_INVALID_VALUE);
- ctx.endSection();
+
+ if (ssAlignment != 1)
+ {
+ ctx.beginSection("GL_INVALID_VALUE is generated if target is GL_SHADER_STORAGE_BUFFER and offset is not a multiple of the value of GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT.");
+ ctx.glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, bufTF, ssAlignment+1, 4);
+ ctx.expectError(GL_INVALID_VALUE);
+ ctx.endSection();
+ }
}
ctx.glDeleteBuffers(1, &bufU);
ctx.expectError(GL_INVALID_VALUE);
ctx.endSection();
- if (contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)))
- {
- int maxACize = 0x1234;
- int maxSSize = 0x1234;
-
- ctx.beginSection("GL_INVALID_VALUE is generated if target is GL_ATOMIC_COUNTER_BUFFER and index is greater than or equal to GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS.");
- ctx.glGetIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, &maxACize);
- ctx.glBindBufferRange(GL_ATOMIC_COUNTER_BUFFER, maxACize, bufU, 0, 4);
- ctx.expectError(GL_INVALID_VALUE);
- ctx.endSection();
-
- ctx.beginSection("GL_INVALID_VALUE is generated if target is GL_SHADER_STORAGE_BUFFER and index is greater than or equal to GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS.");
- ctx.glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &maxSSize);
- ctx.glBindBufferRange(GL_SHADER_STORAGE_BUFFER, maxSSize, bufU, 0, 4);
- ctx.expectError(GL_INVALID_VALUE);
- ctx.endSection();
- }
-
ctx.glDeleteBuffers(1, &bufU);
ctx.glDeleteBuffers(1, &bufTF);
}
--- /dev/null
+/*-------------------------------------------------------------------------
+* drawElements Quality Program OpenGL ES 3.1 Module
+* -------------------------------------------------
+*
+* Copyright 2016 The Android Open Source Project
+*
+* 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.
+*
+*//*!
+* \file
+* \brief Negative Shader Storage Buffer Object (SSBO) tests.
+*//*--------------------------------------------------------------------*/
+#include "es31fNegativeSSBOBlockTests.hpp"
+#include "glwDefs.hpp"
+#include "glwEnums.hpp"
+#include "tcuStringTemplate.hpp"
+#include "gluShaderProgram.hpp"
+#include <map>
+
+namespace deqp
+{
+namespace gles31
+{
+namespace Functional
+{
+namespace NegativeTestShared
+{
+namespace
+{
+using tcu::TestLog;
+using glu::CallLogWrapper;
+using namespace glw;
+namespace args
+{
+enum ArgMember
+{
+ ARGMEMBER_FORMAT = 0,
+ ARGMEMBER_BINDING_POINT,
+ ARGMEMBER_MATRIX_ORDER,
+ ARGMEMBER_MEMBER_TYPE,
+ ARGMEMBER_NAME,
+ ARGMEMBER_FIXED_ARRAY,
+ ARGMEMBER_VARIABLE_ARRAY,
+ ARGMEMBER_REORDER
+};
+
+// key pair ssbo arg data
+struct SsboArgData
+{
+ ArgMember member;
+ std::string data;
+
+ SsboArgData(const ArgMember& member_, const std::string& data_)
+ {
+ member = member_;
+ data = data_;
+ }
+};
+
+// class which manages string based argument used to build varying ssbo interface blocks and members
+class SsboArgs
+{
+public:
+ SsboArgs(const std::string version, tcu::TestLog& log);
+
+ void setSingleValue (const SsboArgData argData);
+ bool setAllValues (const std::vector<SsboArgData> argDataList);
+
+ const std::string& getContextVersion (void) const;
+ const std::string& getStdFormat (void) const;
+ const std::string& getBindingPoint (void) const;
+ const std::string& getMatrixOrder (void) const;
+ const std::string& getMemberType (void) const;
+ const std::string& getMemberName (void) const;
+ const std::string& getMemberFixedArrayName (void) const;
+ const std::string& getMemberVariableArray (void) const;
+ bool getMemberReorder (void) const;
+ int getNumberMembers (void) const;
+
+ void resetValues (void);
+
+ std::map<std::string, std::string> populateArgsMap (void) const;
+
+private:
+ std::string m_negativeContextVersion;
+ std::string m_stdFormat;
+ std::string m_bindingPoint;
+ std::string m_matrixOrder;
+ std::string m_memberType;
+ std::string m_memberName;
+ std::string m_memberFixedArrayerName;
+ std::string m_memberVariableArray;
+ bool m_memberReorder;
+ int m_numberMembers;
+ tcu::TestLog& m_testLog;
+
+ void setDefaultValues (void);
+};
+
+//constructor which ensure a proper context is passed into the struct
+SsboArgs::SsboArgs(const std::string version, tcu::TestLog& log)
+ : m_negativeContextVersion (version)
+ , m_numberMembers (8)
+ , m_testLog (log)
+{
+ setDefaultValues();
+}
+
+void SsboArgs::setSingleValue (const SsboArgData argData)
+{
+ std::string message;
+
+ switch (argData.member)
+ {
+ case ARGMEMBER_FORMAT:
+ m_stdFormat = argData.data;
+ return;
+ case ARGMEMBER_BINDING_POINT:
+ m_bindingPoint = argData.data;
+ return;
+ case ARGMEMBER_MATRIX_ORDER:
+ m_matrixOrder = argData.data;
+ return;
+ case ARGMEMBER_MEMBER_TYPE:
+ m_memberType = argData.data;
+ return;
+ case ARGMEMBER_NAME:
+ m_memberName = argData.data;
+ return;
+ case ARGMEMBER_FIXED_ARRAY:
+ m_memberFixedArrayerName = argData.data;
+ return;
+ case ARGMEMBER_VARIABLE_ARRAY:
+ m_memberVariableArray = argData.data;
+ return;
+ case ARGMEMBER_REORDER:
+ if (argData.data == "true")
+ {
+ m_memberReorder = true;
+ }
+ return;
+ default:
+ message = "auto loop argument data member not recognised.";
+ m_testLog << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
+ }
+}
+
+bool SsboArgs::setAllValues (const std::vector<SsboArgData> argDataList)
+{
+ std::string message;
+
+ if ((argDataList.size() == 0) || (argDataList.size() > (size_t)m_numberMembers))
+ {
+ message = "set of args does not match the number of args struct changeable members.";
+ m_testLog << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
+
+ return false;
+ }
+ else
+ {
+ for (unsigned int idx = 0; idx < argDataList.size(); idx++)
+ {
+ setSingleValue(argDataList[idx]);
+ }
+ }
+
+ return true;
+}
+
+const std::string& SsboArgs::getContextVersion (void) const
+{
+ return m_negativeContextVersion;
+}
+
+const std::string& SsboArgs::getStdFormat (void) const
+{
+ return m_stdFormat;
+}
+
+const std::string& SsboArgs::getBindingPoint (void) const
+{
+ return m_bindingPoint;
+}
+
+const std::string& SsboArgs::getMatrixOrder (void) const
+{
+ return m_matrixOrder;
+}
+
+const std::string& SsboArgs::getMemberType (void) const
+{
+ return m_memberType;
+}
+
+const std::string& SsboArgs::getMemberName (void) const
+{
+ return m_memberName;
+}
+
+const std::string& SsboArgs::getMemberFixedArrayName (void) const
+{
+ return m_memberFixedArrayerName;
+}
+
+const std::string& SsboArgs::getMemberVariableArray (void) const
+{
+ return m_memberVariableArray;
+}
+
+bool SsboArgs::getMemberReorder (void) const
+{
+ return m_memberReorder;
+}
+
+int SsboArgs::getNumberMembers (void) const
+{
+ return m_numberMembers;
+}
+
+void SsboArgs::resetValues (void)
+{
+ setDefaultValues();
+}
+
+//converts SsboArgs member variable into a map object to be used by tcu::StringTemplate
+std::map<std::string, std::string> SsboArgs::populateArgsMap (void) const
+{
+ std::map<std::string, std::string> argsMap;
+
+ // key placeholders located at specific points in the ssbo block
+ argsMap["NEGATIVE_CONTEXT_VERSION"] = m_negativeContextVersion;
+ argsMap["STD_FORMAT"] = m_stdFormat;
+ argsMap["BINDING_POINT"] = m_bindingPoint;
+ argsMap["MATRIX_ORDER"] = m_matrixOrder;
+ argsMap["MEMBER_TYPE"] = m_memberType;
+ argsMap["MEMBER_NAME"] = m_memberName;
+ argsMap["MEMBER_FIXED_ARRAY"] = m_memberFixedArrayerName;
+ argsMap["MEMBER_VARIABLE_ARRAY"] = m_memberVariableArray;
+
+ return argsMap;
+}
+
+// default values i.e. same shader template
+void SsboArgs::setDefaultValues (void)
+{
+ m_stdFormat = "std430";
+ m_bindingPoint = "0";
+ m_matrixOrder = "column_major";
+ m_memberType = "int";
+ m_memberName = "matrix";
+ m_memberFixedArrayerName = "10";
+ m_memberVariableArray = "";
+ m_memberReorder = false;
+}
+} // args
+
+std::string generateVaryingSSBOShader(const glw::GLenum shaderType, const args::SsboArgs& args, tcu::TestLog& log)
+{
+ std::map<std::string, std::string> argsMap;
+ std::ostringstream source;
+ std::string sourceString;
+ std::stringstream ssboString;
+ std::string message;
+
+ if (args.getMemberReorder())
+ {
+ ssboString << " mediump vec4 array_1[${MEMBER_FIXED_ARRAY}];\n"
+ << " highp mat4 ${MEMBER_NAME};\n"
+ << " lowp ${MEMBER_TYPE} data;\n"
+ << " mediump float array_2[${MEMBER_VARIABLE_ARRAY}];\n";
+ }
+ else
+ {
+ ssboString << " lowp ${MEMBER_TYPE} data;\n"
+ << " highp mat4 ${MEMBER_NAME};\n"
+ << " mediump vec4 array_1[${MEMBER_FIXED_ARRAY}];\n"
+ << " mediump float array_2[${MEMBER_VARIABLE_ARRAY}];\n";
+ }
+
+ argsMap = args.populateArgsMap();
+
+ switch (shaderType)
+ {
+ case GL_VERTEX_SHADER:
+ {
+ source << "${NEGATIVE_CONTEXT_VERSION}\n"
+ << "layout (location = 0) in highp vec4 position;\n"
+ << "layout (location = 1) in mediump vec4 colour;\n"
+ << "out mediump vec4 vertex_colour;\n"
+ << "layout (${STD_FORMAT}, binding = ${BINDING_POINT}, ${MATRIX_ORDER}) buffer ssbo_block\n"
+ << "{\n";
+
+ source << ssboString.str();
+
+ source << "} ssbo;\n"
+ << "void main()\n"
+ << "{\n"
+ << " mediump vec4 variable;\n"
+ << " gl_Position = ssbo.${MEMBER_NAME} * position;\n"
+ << " for (int idx = 0; idx < ${MEMBER_FIXED_ARRAY}; idx++)\n"
+ << " {\n"
+ << " variable += ssbo.array_1[idx];\n"
+ << " }\n"
+ << " vertex_colour = colour + variable;\n"
+ << "}\n";
+
+ sourceString = source.str();
+ sourceString = tcu::StringTemplate(sourceString).specialize(argsMap);
+
+ return sourceString;
+ }
+
+ case GL_FRAGMENT_SHADER:
+ {
+ source << "${NEGATIVE_CONTEXT_VERSION}\n"
+ << "in mediump vec4 vertex_colour;\n"
+ << "layout (location = 0) out mediump vec4 fragment_colour;\n"
+ << "layout (${STD_FORMAT}, binding = ${BINDING_POINT}, ${MATRIX_ORDER}) buffer ssbo_block\n"
+ << "{\n";
+
+ source << ssboString.str();
+
+ source << "} ssbo;\n"
+ << "void main()\n"
+ << "{\n"
+ << " mediump vec4 variable;\n"
+ << " variable * ssbo.${MEMBER_NAME};\n"
+ << " for (int idx = 0; idx < ${MEMBER_FIXED_ARRAY}; idx++)\n"
+ << " {\n"
+ << " variable += ssbo.array_1[idx];\n"
+ << " }\n"
+ << " fragment_colour = vertex_colour + variable;\n"
+ << "}\n";
+
+ sourceString = source.str();
+ sourceString = tcu::StringTemplate(sourceString).specialize(argsMap);
+
+ return sourceString;
+ }
+
+ case GL_GEOMETRY_SHADER:
+ {
+ // TODO:
+ return sourceString;
+ }
+
+ case GL_TESS_CONTROL_SHADER:
+ {
+ // TODO:
+ return sourceString;
+ }
+
+ case GL_TESS_EVALUATION_SHADER:
+ {
+ // TODO:
+ return sourceString;
+ }
+
+ case GL_COMPUTE_SHADER:
+ {
+ // TODO:
+ return sourceString;
+ }
+
+ default:
+ {
+ message = "shader type not recognised.";
+ log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
+ }
+ }
+
+ return std::string();
+}
+
+void logProgramInfo(NegativeTestContext& ctx, GLint program)
+{
+ GLint maxLength = 0;
+ std::string message;
+ tcu::TestLog& log = ctx.getLog();
+
+ ctx.glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
+
+ message = "Program log:";
+ log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
+
+ if (maxLength == 0)
+ {
+ message = "No available info log.";
+ log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
+ return;
+ }
+
+ std::vector<GLchar> infoLog(maxLength);
+ ctx.glGetProgramInfoLog(program, maxLength, &maxLength, &infoLog[0]);
+
+ std::string programLogMessage(&infoLog[0], maxLength);
+ log << tcu::TestLog::Message << programLogMessage << tcu::TestLog::EndMessage;
+}
+
+void ssbo_block_matching(NegativeTestContext& ctx)
+{
+ const bool isES32 = contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+ const glu::GLSLVersion version = isES32 ? glu::GLSL_VERSION_320_ES : glu::GLSL_VERSION_310_ES;
+ tcu::TestLog& log = ctx.getLog();
+ std::string message;
+ std::string versionString(glu::getGLSLVersionDeclaration(version));
+ args::SsboArgs ssboArgs(versionString, log);
+ GLint shaderVertexGL;
+ std::string shaderVertexString;
+ const char* shaderVertexCharPtr;
+
+ // List of arguments used to create varying ssbo objects in the fragment shader
+ const args::SsboArgData argDataArrayFrag[] = { args::SsboArgData(args::ARGMEMBER_FORMAT, "std140"),
+ args::SsboArgData(args::ARGMEMBER_BINDING_POINT, "10"),
+ args::SsboArgData(args::ARGMEMBER_MATRIX_ORDER, "row_major"),
+ args::SsboArgData(args::ARGMEMBER_MEMBER_TYPE, "vec2"),
+ args::SsboArgData(args::ARGMEMBER_NAME, "name_changed"),
+ args::SsboArgData(args::ARGMEMBER_FIXED_ARRAY, "20"),
+ args::SsboArgData(args::ARGMEMBER_VARIABLE_ARRAY, "5"),
+ args::SsboArgData(args::ARGMEMBER_REORDER, "true") };
+ std::vector<args::SsboArgData> argDataVectorFrag(argDataArrayFrag, argDataArrayFrag + sizeof(argDataArrayFrag) / sizeof(argDataArrayFrag[0]));
+
+ // create default vertex shader
+ shaderVertexString = generateVaryingSSBOShader(GL_VERTEX_SHADER, ssboArgs, log);
+ shaderVertexCharPtr = shaderVertexString.c_str();
+ shaderVertexGL = ctx.glCreateShader(GL_VERTEX_SHADER);
+
+ // log
+ message = shaderVertexString;
+ log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
+
+ // compile
+ ctx.glShaderSource(shaderVertexGL, 1, &shaderVertexCharPtr, DE_NULL);
+ ctx.glCompileShader(shaderVertexGL);
+
+ for (std::size_t idx = 0; idx < argDataVectorFrag.size(); ++idx)
+ {
+ GLint linkStatus = -1;
+ GLint program;
+ GLint shaderFragmentGL;
+ std::string shaderFragmentString;
+ const char* shaderFragmentCharPtr;
+
+ ctx.beginSection("Multiple shaders created using SSBO's sharing the same name but not matching layouts");
+
+ program = ctx.glCreateProgram();
+
+ // reset args to default and make a single change
+ ssboArgs.resetValues();
+ ssboArgs.setSingleValue(argDataVectorFrag[idx]);
+
+ // create fragment shader
+ shaderFragmentString = generateVaryingSSBOShader(GL_FRAGMENT_SHADER, ssboArgs, log);
+ shaderFragmentCharPtr = shaderFragmentString.c_str();
+ shaderFragmentGL = ctx.glCreateShader(GL_FRAGMENT_SHADER);
+
+ // log
+ message = shaderFragmentString;
+ log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
+
+ // compile
+ ctx.glShaderSource(shaderFragmentGL, 1, &shaderFragmentCharPtr, DE_NULL);
+ ctx.glCompileShader(shaderFragmentGL);
+
+ // attach shaders to program and attempt to link
+ ctx.glAttachShader(program, shaderVertexGL);
+ ctx.glAttachShader(program, shaderFragmentGL);
+ ctx.glLinkProgram(program);
+ ctx.glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
+
+ logProgramInfo(ctx, program);
+
+ if (linkStatus == GL_TRUE)
+ {
+ ctx.fail("Program should not have linked");
+ }
+
+ // clean up resources
+ ctx.glDeleteShader(shaderFragmentGL);
+ ctx.glDeleteProgram(program);
+
+ ctx.endSection();
+ }
+
+ // clean up default resources
+ ctx.glDeleteShader(shaderVertexGL);
+}
+
+void ssbo_block_shared_qualifier(NegativeTestContext& ctx)
+{
+ const bool isES32 = contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+ const glu::GLSLVersion version = isES32 ? glu::GLSL_VERSION_320_ES : glu::GLSL_VERSION_310_ES;
+ tcu::TestLog& log = ctx.getLog();
+ std::string message;
+ std::string versionString(glu::getGLSLVersionDeclaration(version));
+ args::SsboArgs ssboArgs(versionString, log);
+ bool result;
+ GLint shaderVertexGL;
+ std::string shaderVertexString;
+ const char* shaderVertexCharPtr;
+
+ // default args used in vertex shader ssbo
+ const args::SsboArgData argDataArrayVert[] = { args::SsboArgData(args::ARGMEMBER_FORMAT, "shared"),
+ args::SsboArgData(args::ARGMEMBER_BINDING_POINT, "0"),
+ args::SsboArgData(args::ARGMEMBER_MATRIX_ORDER, "column_major"),
+ args::SsboArgData(args::ARGMEMBER_FIXED_ARRAY, "10"),
+ args::SsboArgData(args::ARGMEMBER_VARIABLE_ARRAY, "10"),
+ args::SsboArgData(args::ARGMEMBER_REORDER, "false") };
+ std::vector<args::SsboArgData> argDataVectorVert(argDataArrayVert, argDataArrayVert + sizeof(argDataArrayVert) / sizeof(argDataArrayVert[0]));
+
+ // args changed in fragment shader ssbo
+ const args::SsboArgData argDataArrayFrag[] = { args::SsboArgData(args::ARGMEMBER_MATRIX_ORDER, "row_major"),
+ args::SsboArgData(args::ARGMEMBER_VARIABLE_ARRAY, ""),
+ args::SsboArgData(args::ARGMEMBER_FIXED_ARRAY, "20") };
+ std::vector<args::SsboArgData> argDataVectorFrag(argDataArrayFrag, argDataArrayFrag + sizeof(argDataArrayFrag) / sizeof(argDataArrayFrag[0]));
+
+ // set default vertex ssbo args
+ result = ssboArgs.setAllValues(argDataVectorVert);
+
+ if (result == false)
+ {
+ message = "Invalid use of args.setAllValues()";
+ log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
+ return;
+ }
+
+ // create default vertex shader
+ shaderVertexString = generateVaryingSSBOShader(GL_VERTEX_SHADER, ssboArgs, log);
+ shaderVertexCharPtr = shaderVertexString.c_str();
+ shaderVertexGL = ctx.glCreateShader(GL_VERTEX_SHADER);
+
+ // log
+ message = shaderVertexString;
+ log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
+
+ // compile
+ ctx.glShaderSource(shaderVertexGL, 1, &shaderVertexCharPtr, DE_NULL);
+ ctx.glCompileShader(shaderVertexGL);
+
+ for (std::size_t idx = 0; idx < argDataVectorFrag.size(); idx++)
+ {
+ GLint linkStatus = -1;
+ GLint program;
+ GLint shaderFragmentGL;
+ std::string shaderFragmentString;
+ const char* shaderFragmentCharPtr;
+
+ ctx.beginSection("Multiple shaders created using SSBO's sharing the same name but not matching layouts");
+
+ program = ctx.glCreateProgram();
+
+ // reset args to default and make a single change
+ ssboArgs.setAllValues(argDataVectorVert);
+ ssboArgs.setSingleValue(argDataVectorFrag[idx]);
+
+ // create fragment shader
+ shaderFragmentString = generateVaryingSSBOShader(GL_FRAGMENT_SHADER, ssboArgs, log);
+ shaderFragmentCharPtr = shaderFragmentString.c_str();
+ shaderFragmentGL = ctx.glCreateShader(GL_FRAGMENT_SHADER);
+
+ // log
+ message = shaderFragmentString;
+ log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
+
+ // compile
+ ctx.glShaderSource(shaderFragmentGL, 1, &shaderFragmentCharPtr, DE_NULL);
+ ctx.glCompileShader(shaderFragmentGL);
+
+ // attach shaders to the program and attempt to link
+ ctx.glAttachShader(program, shaderVertexGL);
+ ctx.glAttachShader(program, shaderFragmentGL);
+ ctx.glLinkProgram(program);
+ ctx.glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
+
+ logProgramInfo(ctx, program);
+
+ if (linkStatus == GL_TRUE)
+ {
+ ctx.fail("Program should not have linked");
+ }
+
+ // clean up resources
+ ctx.glDeleteShader(shaderFragmentGL);
+ ctx.glDeleteProgram(program);
+
+ ctx.endSection();
+ }
+
+ // clean up default resources
+ ctx.glDeleteShader(shaderVertexGL);
+}
+} // anonymous
+
+std::vector<FunctionContainer> getNegativeSSBOBlockTestFunctions (void)
+{
+ const FunctionContainer funcs[] =
+ {
+ { ssbo_block_matching, "ssbo_block_interface_matching_tests", "Invalid Shader Linkage" },
+ { ssbo_block_shared_qualifier, "ssbo_using_shared_qualifier_tests", "Invalid Shader Linkage" },
+ };
+
+ return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
+}
+} // NegativeTestShared
+} //Functional
+} //gles31
+} //deqp
--- /dev/null
+#ifndef _ES31FNEGATIVESSBOBLOCKTESTS_HPP
+#define _ES31FNEGATIVESSBOBLOCKTESTS_HPP
+/*-------------------------------------------------------------------------
+* drawElements Quality Program OpenGL ES 3.1 Module
+* -------------------------------------------------
+*
+* Copyright 2016 The Android Open Source Project
+*
+* 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.
+*
+*//*!
+* \file
+* \brief Negative Shader Storage Block Object (SSBO) API tests.
+*//*--------------------------------------------------------------------*/
+#include "tcuDefs.hpp"
+#include "es31fNegativeTestShared.hpp"
+
+namespace deqp
+{
+namespace gles31
+{
+namespace Functional
+{
+namespace NegativeTestShared
+{
+
+std::vector<FunctionContainer> getNegativeSSBOBlockTestFunctions (void);
+
+} // NegativeTestShared
+} // Functional
+} // gles31
+} // deqp
+
+#endif // _ES31FNEGATIVESSBOBLOCKTESTS_HPP
\ No newline at end of file
}
}
-void compile_compute_shader_helper (NegativeTestContext& ctx, const char** computeShaderSource, GLint* compileStatus)
+void compile_compute_shader_helper (NegativeTestContext& ctx, const char* const* computeShaderSource, GLint* compileStatus)
{
GLuint shader = ctx.glCreateShader(GL_COMPUTE_SHADER);
ctx.beginSection("Compile Computer Shader");
{
- const char* computeShaderSource = "#version 300 es\n"
- "void main (void)\n"
- "{\n"
- "}\n\0";
+ const char* const computeShaderSource = "#version 300 es\n"
+ "void main (void)\n"
+ "{\n"
+ "}\n";
compile_compute_shader_helper(ctx, &computeShaderSource, &compileStatus);
if (compileStatus != GL_FALSE)
ctx.fail("Compute Shader should not have compiled with #version 300 es.");
}
{
- const char* computeShaderSource = "#version 310 es\n"
- "buffer SSBO { vec4 data }"
- "void main (void)\n"
- "{\n"
- "}\n\0";
+ const char* const computeShaderSource = "#version 310 es\n"
+ "buffer SSBO { vec4 data }"
+ "void main (void)\n"
+ "{\n"
+ "}\n";
compile_compute_shader_helper(ctx, &computeShaderSource, &compileStatus);
if (compileStatus != GL_FALSE)
ctx.fail("Compute Shader should not have compiled: incorrect SSBO syntax.");
}
{
- const char* computeShaderSource = "#version 310 es\n"
- "buffer SSBO { vec4 data;};"
- "uniform mat4 data;"
- "void main (void)\n"
- "{\n"
- "}\n\0";
+ const char* const computeShaderSource = "#version 310 es\n"
+ "buffer SSBO { vec4 data;};"
+ "uniform mat4 data;"
+ "void main (void)\n"
+ "{\n"
+ "}\n";
compile_compute_shader_helper(ctx, &computeShaderSource, &compileStatus);
if (compileStatus != GL_FALSE)
ctx.fail("Compute Shader should not have compiled: buffer variable redefinition.");
}
{
- const char* computeShaderSource = "#version 310 es\n"
- "buffer SSBO { vec4 data[]; vec4 moreData;};"
- "void main (void)\n"
- "{\n"
- "}\n\0";
+ const char* const computeShaderSource = "#version 310 es\n"
+ "buffer SSBO { vec4 data[]; vec4 moreData;};"
+ "void main (void)\n"
+ "{\n"
+ "}\n";
compile_compute_shader_helper(ctx, &computeShaderSource, &compileStatus);
if (compileStatus != GL_FALSE)
ctx.fail("Compute Shader should not have compiled: unspecified length buffer member not at the end.");
}
{
- const char* computeShaderSource = "#version 310 es\n"
- "in vec4 data;"
- "void main (void)\n"
- "{\n"
- "}\n\0";
+ const char* const computeShaderSource = "#version 310 es\n"
+ "in vec4 data;"
+ "void main (void)\n"
+ "{\n"
+ "}\n";
compile_compute_shader_helper(ctx, &computeShaderSource, &compileStatus);
if (compileStatus != GL_FALSE)
ctx.fail("Compute Shader should not have compiled: input qualifier used.");
}
{
- const char* computeShaderSource = "#version 310 es\n"
- "shared uint data = 0;";
+ const char* const computeShaderSource = "#version 310 es\n"
+ "shared uint data = 0;";
compile_compute_shader_helper(ctx, &computeShaderSource, &compileStatus);
if (compileStatus != GL_FALSE)
ctx.fail("Compute Shader should not have compiled: shared-qualified variable initialized.");
}
+ {
+ const char* const computeShaderSource = "#version 310 es\n"
+ "buffer SSBO { vec4 data; vec4 moreData[];} ssbo;"
+ "void test (vec4 data[10]) {}"
+ "void main (void)\n"
+ "{\n"
+ " test(ssbo.moreData);"
+ "}\n";
+
+ compile_compute_shader_helper(ctx, &computeShaderSource, &compileStatus);
+ if (compileStatus != GL_FALSE)
+ ctx.fail("Compute Shader should not have compiled: unspecified length buffer member passed as argument to function.");
+ }
+ {
+ const char* const computeShaderSource = "#version 310 es\n"
+ "buffer SSBO { vec4 data; vec4 moreData[];} ssbo;"
+ "void main (void)\n"
+ "{\n"
+ " vec4 var = ssbo.moreData[-1];"
+ "}\n";
+
+ compile_compute_shader_helper(ctx, &computeShaderSource, &compileStatus);
+ if (compileStatus != GL_FALSE)
+ ctx.fail("Compute Shader should not have compiled: unspecified length buffer member indexed with negative constant expression.");
+ }
+ {
+ const char* const computeShaderSource = "#version 310 es\n"
+ "layout(binding=-1) buffer SSBO { vec4 data;};"
+ "void main (void)\n"
+ "{\n"
+ "}\n";
+
+ compile_compute_shader_helper(ctx, &computeShaderSource, &compileStatus);
+ if (compileStatus != GL_FALSE)
+ ctx.fail("Compute Shader should not have compiled: binding point less than zero.");
+ }
+ {
+ const char* const computeShaderSource = "#version 310 es\n"
+ "layout(binding=1) buffer;"
+ "layout(binding=2) buffer SSBO { vec4 data;};"
+ "void main (void)\n"
+ "{\n"
+ "}\n";
+
+ compile_compute_shader_helper(ctx, &computeShaderSource, &compileStatus);
+ if (compileStatus != GL_FALSE)
+ ctx.fail("Compute Shader should not have compiled: binding point specified for global scope.");
+ }
+ {
+ const char* const computeShaderSource = "#version 310 es\n"
+ "buffer SSBO {"
+ " layout(binding=1) vec4 data;"
+ " layout(binding=2) vec4 moreData[];"
+ "} ssbo;"
+ "void main (void)\n"
+ "{\n"
+ "}\n";
+
+ compile_compute_shader_helper(ctx, &computeShaderSource, &compileStatus);
+ if (compileStatus != GL_FALSE)
+ ctx.fail("Compute Shader should not have compiled: binding point specified for block member declarations.");
+ }
+ {
+ const char* const computeShaderSource = "#version 310 es\n"
+ "readonly buffer SSBO {vec4 data;} ssbo;"
+ "void main (void)\n"
+ "{\n"
+ "ssbo.data = vec4(1, 1, 1, 1);"
+ "}\n";
+
+ compile_compute_shader_helper(ctx, &computeShaderSource, &compileStatus);
+ if (compileStatus != GL_FALSE)
+ ctx.fail("Compute Shader should not have compiled: writing to buffer block qualified with readonly.");
+ }
+ {
+ const char* const computeShaderSource = "#version 310 es\n"
+ "writeonly buffer SSBO {vec4 data;} ssbo;"
+ "void main (void)\n"
+ "{\n"
+ "vec4 var = ssbo.data;"
+ "}\n";
+
+ compile_compute_shader_helper(ctx, &computeShaderSource, &compileStatus);
+ if (compileStatus != GL_FALSE)
+ ctx.fail("Compute Shader should not have compiled: reading from buffer block qualified with writeonly.");
+ }
+
ctx.endSection();
}
if (contextSupports(ctx.getRenderContext().getType() , glu::ApiType::es(3, 2)))
{
ctx.beginSection("gl_BoundingBox does not require the OES/EXT suffix in a 320 es shader.");
- const std::string source = "#version 320 es\n"
- "layout(vertices = 3) out;\n"
- "void main()\n"
- "{\n"
- " gl_BoundingBox[0] = vec4(0.0, 0.0, 0.0, 0.0);\n"
- " gl_BoundingBox[1] = vec4(0.0, 0.0, 0.0, 0.0);\n"
- "}\n";
- verifyShader(ctx, glu::SHADERTYPE_TESSELLATION_CONTROL, source, EXPECT_RESULT_PASS);
+ {
+ const std::string source = "#version 320 es\n"
+ "layout(vertices = 3) out;\n"
+ "void main()\n"
+ "{\n"
+ " gl_BoundingBox[0] = vec4(0.0, 0.0, 0.0, 0.0);\n"
+ " gl_BoundingBox[1] = vec4(0.0, 0.0, 0.0, 0.0);\n"
+ "}\n";
+ verifyShader(ctx, glu::SHADERTYPE_TESSELLATION_CONTROL, source, EXPECT_RESULT_PASS);
+ }
+ ctx.endSection();
+
+ ctx.beginSection("Invalid index used when assigning to gl_BoundingBox in 320 es shader.");
+ {
+ const std::string source = "#version 320 es\n"
+ "layout(vertices = 3) out;\n"
+ "void main()\n"
+ "{\n"
+ " gl_BoundingBox[0] = vec4(0.0, 0.0, 0.0, 0.0);\n"
+ " gl_BoundingBox[2] = vec4(0.0, 0.0, 0.0, 0.0);\n"
+ "}\n";
+ verifyShader(ctx, glu::SHADERTYPE_TESSELLATION_CONTROL, source, EXPECT_RESULT_FAIL);
+ }
+ ctx.endSection();
+
+ ctx.beginSection("Invalid type assignment to per-patch output array in 320 es shader.");
+ {
+ const std::string source = "#version 320 es\n"
+ "layout(vertices = 3) out;\n"
+ "void main()\n"
+ "{\n"
+ " gl_BoundingBox[0] = ivec4(0, 0, 0, 0);\n"
+ " gl_BoundingBox[1] = ivec4(0, 0, 0, 0);\n"
+ "}\n";
+ verifyShader(ctx, glu::SHADERTYPE_TESSELLATION_CONTROL, source, EXPECT_RESULT_FAIL);
+ }
ctx.endSection();
}
}
ctx.endSection();
}
+void executeAccessingBoundingBoxType (NegativeTestContext& ctx, const std::string builtInTypeName, glu::GLSLVersion glslVersion)
+{
+ std::ostringstream sourceStream;
+ std::string version;
+ std::string extensionPrim;
+ std::string extensionTess;
+
+ if (glslVersion == glu::GLSL_VERSION_310_ES)
+ {
+ version = "#version 310 es\n";
+ extensionPrim = "#extension GL_EXT_primitive_bounding_box : require\n";
+ extensionTess = "#extension GL_EXT_tessellation_shader : require\n";
+ }
+ else if (glslVersion >= glu::GLSL_VERSION_320_ES)
+ {
+ version = "#version 320 es\n";
+ extensionPrim = "";
+ extensionTess = "";
+ }
+ else
+ {
+ DE_FATAL("error: context below 3.1 and not supported");
+ }
+
+ ctx.beginSection("cannot access built-in type " + builtInTypeName + "[]" + " in vertex shader");
+ sourceStream << version
+ << extensionPrim
+ << "void main()\n"
+ << "{\n"
+ << " " + builtInTypeName + "[0] = vec4(1.0, 1.0, 1.0, 1.0);\n"
+ << " gl_Position = " + builtInTypeName + "[0];\n"
+ << "}\n";
+ verifyShader(ctx, glu::SHADERTYPE_VERTEX, sourceStream.str(), EXPECT_RESULT_FAIL);
+ ctx.endSection();
+
+ sourceStream.str(std::string());
+
+ if (ctx.isShaderSupported(glu::SHADERTYPE_TESSELLATION_EVALUATION))
+ {
+ ctx.beginSection("cannot access built-in type " + builtInTypeName + "[]" + " in tessellation evaluation shader");
+ sourceStream << version
+ << extensionPrim
+ << extensionTess
+ << "layout (triangles, equal_spacing, ccw) in;\n"
+ << "void main()\n"
+ << "{\n"
+ << " " + builtInTypeName + "[0] = vec4(1.0, 1.0, 1.0, 1.0);\n"
+ << " gl_Position = ( gl_TessCoord.x * " + builtInTypeName + "[0] +\n"
+ << " gl_TessCoord.y * " + builtInTypeName + "[0] +\n"
+ << " gl_TessCoord.z * " + builtInTypeName + "[0]);\n"
+ << "}\n";
+ verifyShader(ctx, glu::SHADERTYPE_TESSELLATION_EVALUATION, sourceStream.str(), EXPECT_RESULT_FAIL);
+ ctx.endSection();
+
+ sourceStream.str(std::string());
+ }
+
+ if (ctx.isShaderSupported(glu::SHADERTYPE_GEOMETRY))
+ {
+ ctx.beginSection("cannot access built-in type " + builtInTypeName + "[]" + " in geometry shader");
+ sourceStream << version
+ << extensionPrim
+ << "layout (triangles) in;\n"
+ << "layout (triangle_strip, max_vertices = 3) out;\n"
+ << "void main()\n"
+ << "{\n"
+ << " " + builtInTypeName + "[0] = vec4(1.0, 1.0, 1.0, 1.0);\n"
+ << " for (int idx = 0; idx < 3; idx++)\n"
+ << " {\n"
+ << " gl_Position = gl_in[idx].gl_Position * " + builtInTypeName + "[0];\n"
+ << " EmitVertex();\n"
+ << " }\n"
+ << " EndPrimitive();\n"
+ << "}\n";
+ verifyShader(ctx, glu::SHADERTYPE_GEOMETRY, sourceStream.str(), EXPECT_RESULT_FAIL);
+ ctx.endSection();
+
+ sourceStream.str(std::string());
+ }
+
+ ctx.beginSection("cannot access built-in type " + builtInTypeName + "[]" + " in fragment shader");
+ sourceStream << version
+ << extensionPrim
+ << "layout (location = 0) out mediump vec4 fs_colour;\n"
+ << "void main()\n"
+ << "{\n"
+ << " " + builtInTypeName + "[0] = vec4(1.0, 1.0, 1.0, 1.0);\n"
+ << " fs_colour = " + builtInTypeName + "[0];\n"
+ << "}\n";
+ verifyShader(ctx, glu::SHADERTYPE_FRAGMENT, sourceStream.str(), EXPECT_RESULT_FAIL);
+ ctx.endSection();
+}
+
+void accessing_bounding_box_type (NegativeTestContext& ctx)
+{
+ // Extension requirements and name differences depending on the context
+ if ((ctx.getRenderContext().getType().getMajorVersion() == 3) && (ctx.getRenderContext().getType().getMinorVersion() == 1))
+ {
+ executeAccessingBoundingBoxType(ctx, "gl_BoundingBoxEXT", glu::GLSL_VERSION_310_ES);
+ }
+ else
+ {
+ executeAccessingBoundingBoxType(ctx, "gl_BoundingBox", glu::GLSL_VERSION_320_ES);
+ }
+
+}
+
} // anonymous
std::vector<FunctionContainer> getNegativeShaderDirectiveTestFunctions (void)
{tessellation_shader, "tessellation_shader", "GL_EXT_tessellation_shader is required in 310 es shaders to use AEP features" },
{texture_buffer, "texture_buffer", "GL_EXT_texture_buffer is required in 310 es shaders to use AEP features" },
{texture_cube_map_array, "texture_cube_map_array", "GL_EXT_texture_cube_map_array is required in 310 es shaders to use AEP features" },
+ {accessing_bounding_box_type, "accessing_bounding_box_type", "Should not be able to access gl_BoundingBoxEXT[] and gl_BoundingBox[] in shaders other than tess control and evaluation" },
};
return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
--- /dev/null
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.1 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2016 The Android Open Source Project
+ *
+ * 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.
+ *
+ *//*!
+ * \file
+ * \brief Negative Shader Storage Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "es31fNegativeShaderStorageTests.hpp"
+
+#include "gluShaderProgram.hpp"
+#include "glwDefs.hpp"
+#include "glwEnums.hpp"
+
+namespace deqp
+{
+namespace gles31
+{
+namespace Functional
+{
+namespace NegativeTestShared
+{
+namespace
+{
+
+void verifyProgram(NegativeTestContext& ctx, glu::ProgramSources sources)
+{
+ tcu::TestLog& log = ctx.getLog();
+ const glu::ShaderProgram program (ctx.getRenderContext(), sources);
+ bool testFailed = false;
+
+ log << program;
+
+ testFailed = program.getProgramInfo().linkOk;
+
+ if (testFailed)
+ {
+ const char* const message("Program was not expected to link.");
+ log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
+ ctx.fail(message);
+ }
+}
+
+const char* getShaderExtensionDeclaration (glw::GLenum glShaderType)
+{
+ switch (glShaderType)
+ {
+ case GL_TESS_CONTROL_SHADER:
+ case GL_TESS_EVALUATION_SHADER: return "#extension GL_EXT_tessellation_shader : require\n";
+ case GL_GEOMETRY_SHADER: return "#extension GL_EXT_geometry_shader : require\n";
+ default:
+ return "";
+ }
+}
+
+glu::ShaderType getGLUShaderType (glw::GLenum glShaderType)
+{
+ switch (glShaderType)
+ {
+ case GL_VERTEX_SHADER: return glu::SHADERTYPE_VERTEX;
+ case GL_FRAGMENT_SHADER: return glu::SHADERTYPE_FRAGMENT;
+ case GL_TESS_CONTROL_SHADER: return glu::SHADERTYPE_TESSELLATION_CONTROL;
+ case GL_TESS_EVALUATION_SHADER: return glu::SHADERTYPE_TESSELLATION_EVALUATION;
+ case GL_GEOMETRY_SHADER: return glu::SHADERTYPE_GEOMETRY;
+ case GL_COMPUTE_SHADER: return glu::SHADERTYPE_COMPUTE;
+ default:
+ DE_FATAL("Unknown shader type");
+ return glu::SHADERTYPE_LAST;
+ }
+}
+
+glw::GLenum getMaxSSBlockSizeEnum (glw::GLenum glShaderType)
+{
+ switch (glShaderType)
+ {
+ case GL_VERTEX_SHADER: return GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS;
+ case GL_FRAGMENT_SHADER: return GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS;
+ case GL_TESS_CONTROL_SHADER: return GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS;
+ case GL_TESS_EVALUATION_SHADER: return GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS;
+ case GL_GEOMETRY_SHADER: return GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS;
+ case GL_COMPUTE_SHADER: return GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS;
+ default:
+ DE_FATAL("Unknown shader type");
+ return -1;
+ }
+}
+
+int getMaxSSBlockSize (NegativeTestContext& ctx, glw::GLenum glShaderType)
+{
+ int maxSSBlocks = 0;
+ ctx.glGetIntegerv(getMaxSSBlockSizeEnum(glShaderType), &maxSSBlocks);
+
+ return maxSSBlocks;
+}
+
+std::string genBlockSource (NegativeTestContext& ctx, deInt64 numSSBlocks, glw::GLenum shaderType)
+{
+ const bool isES32 = contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+ const glu::GLSLVersion version = isES32 ? glu::GLSL_VERSION_320_ES : glu::GLSL_VERSION_310_ES;
+ std::ostringstream source;
+
+ source << glu::getGLSLVersionDeclaration(version) << "\n"
+ << ((isES32) ? "" : getShaderExtensionDeclaration(shaderType));
+
+ switch (shaderType)
+ {
+ case GL_VERTEX_SHADER:
+ case GL_FRAGMENT_SHADER:
+ break;
+
+ case GL_COMPUTE_SHADER:
+ source << "layout (local_size_x = 1) in;\n";
+ break;
+
+ case GL_GEOMETRY_SHADER:
+ source << "layout(points) in;\n"
+ << "layout(line_strip, max_vertices = 3) out;\n";
+ break;
+
+ case GL_TESS_CONTROL_SHADER:
+ source << "layout(vertices = 10) out;\n";
+ break;
+
+ case GL_TESS_EVALUATION_SHADER:
+ source << "layout(triangles) in;\n";
+ break;
+
+ default:
+ DE_FATAL("Unknown shader type");
+ break;
+ }
+
+ source << "\n"
+ << "layout(std430, binding = 0) buffer Block {\n"
+ << " int value;\n"
+ << "} sb_in[" << numSSBlocks << "];\n"
+ << "void main(void) { sb_in[0].value = 1; }\n";
+
+ return source.str();
+}
+
+std::string genCommonSource (NegativeTestContext& ctx, glw::GLenum shaderType)
+{
+ const bool isES32 = contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+ const glu::GLSLVersion version = isES32 ? glu::GLSL_VERSION_320_ES : glu::GLSL_VERSION_310_ES;
+ std::ostringstream source;
+
+ source << glu::getGLSLVersionDeclaration(version) << "\n"
+ << ((isES32) ? "" : getShaderExtensionDeclaration(shaderType));
+
+ switch (shaderType)
+ {
+ case GL_TESS_CONTROL_SHADER:
+ source << "layout(vertices = 3) out;\n"
+ << "void main() {}\n";
+ break;
+
+ case GL_TESS_EVALUATION_SHADER:
+ source << "layout(triangles, equal_spacing, cw) in;\n"
+ << "void main() {}\n";
+ break;
+
+ default:
+ source << "void main() {}\n";
+ break;
+ }
+
+ return source.str();
+}
+
+int genMaxSSBlocksSource (NegativeTestContext& ctx, glw::GLenum glShaderType, glu::ProgramSources& sources)
+{
+ int maxSSBlocks = getMaxSSBlockSize(ctx, glShaderType);
+ const std::string shaderSrc = genBlockSource(ctx, (maxSSBlocks), glShaderType);
+
+ sources.sources[getGLUShaderType(glShaderType)].push_back(shaderSrc);
+
+ return maxSSBlocks;
+}
+
+void block_number_limits (NegativeTestContext& ctx)
+{
+ const glw::GLenum glShaderTypes[] =
+ {
+ GL_VERTEX_SHADER,
+ GL_FRAGMENT_SHADER,
+ GL_TESS_CONTROL_SHADER,
+ GL_TESS_EVALUATION_SHADER,
+ GL_GEOMETRY_SHADER,
+ GL_COMPUTE_SHADER,
+ };
+
+ const std::string vertSource = genCommonSource(ctx, GL_VERTEX_SHADER);
+ const std::string fragSource = genCommonSource(ctx, GL_FRAGMENT_SHADER);
+ const std::string tessControlSource = genCommonSource(ctx, GL_TESS_CONTROL_SHADER);
+ const std::string tessEvalSource = genCommonSource(ctx, GL_TESS_EVALUATION_SHADER);
+
+ for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(glShaderTypes); ndx++)
+ {
+ ctx.beginSection("maxShaderStorageBlocks: Exceed limits");
+
+ if (!ctx.isShaderSupported(static_cast<glu::ShaderType>(getGLUShaderType(glShaderTypes[ndx]))))
+ {
+ ctx.endSection();
+ continue;
+ }
+
+ int maxSSBlocks = getMaxSSBlockSize(ctx, glShaderTypes[ndx]);
+ std::string source = genBlockSource(ctx, maxSSBlocks+1, glShaderTypes[ndx]);
+
+ glu::ProgramSources sources;
+
+ if (maxSSBlocks == 0)
+ {
+ ctx.endSection();
+ continue;
+ }
+
+ switch (glShaderTypes[ndx])
+ {
+ case GL_VERTEX_SHADER:
+ sources << glu::VertexSource(source)
+ << glu::FragmentSource(fragSource);
+ break;
+
+ case GL_FRAGMENT_SHADER:
+ sources << glu::VertexSource(vertSource)
+ << glu::FragmentSource(source);
+ break;
+
+ case GL_TESS_CONTROL_SHADER:
+ sources << glu::VertexSource(vertSource)
+ << glu::FragmentSource(fragSource)
+ << glu::TessellationControlSource(source)
+ << glu::TessellationEvaluationSource(tessEvalSource);
+ break;
+
+ case GL_TESS_EVALUATION_SHADER:
+ sources << glu::VertexSource(vertSource)
+ << glu::FragmentSource(fragSource)
+ << glu::TessellationControlSource(tessControlSource)
+ << glu::TessellationEvaluationSource(source);
+ break;
+
+ case GL_GEOMETRY_SHADER:
+ sources << glu::VertexSource(vertSource)
+ << glu::FragmentSource(fragSource)
+ << glu::GeometrySource(source);
+ break;
+
+ case GL_COMPUTE_SHADER:
+ sources << glu::ComputeSource(source);
+ break;
+
+ default:
+ DE_FATAL("Unknown shader type");
+ break;
+ }
+
+ verifyProgram(ctx, sources);
+ ctx.endSection();
+ }
+}
+
+void max_combined_block_number_limit (NegativeTestContext& ctx)
+{
+ ctx.beginSection("maxCombinedShaderStorageBlocks: Exceed limits");
+
+ glu::ProgramSources sources;
+
+ int combinedSSBlocks = 0;
+ int maxCombinedSSBlocks = 0;
+
+ combinedSSBlocks += genMaxSSBlocksSource(ctx, GL_VERTEX_SHADER, sources);
+ combinedSSBlocks += genMaxSSBlocksSource(ctx, GL_FRAGMENT_SHADER, sources);
+
+ if ((ctx.isShaderSupported(glu::SHADERTYPE_TESSELLATION_CONTROL)) && (ctx.isShaderSupported(glu::SHADERTYPE_TESSELLATION_EVALUATION)))
+ {
+ combinedSSBlocks += genMaxSSBlocksSource(ctx, GL_TESS_CONTROL_SHADER, sources);
+ combinedSSBlocks += genMaxSSBlocksSource(ctx, GL_TESS_EVALUATION_SHADER, sources);
+ }
+
+ if (ctx.isShaderSupported(glu::SHADERTYPE_GEOMETRY))
+ combinedSSBlocks += genMaxSSBlocksSource(ctx, GL_GEOMETRY_SHADER, sources);
+
+ ctx.glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &maxCombinedSSBlocks);
+
+ ctx.getLog() << tcu::TestLog::Message << "GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS: " << maxCombinedSSBlocks << tcu::TestLog::EndMessage;
+ ctx.getLog() << tcu::TestLog::Message << "Combined shader storage blocks: " << combinedSSBlocks << tcu::TestLog::EndMessage;
+
+ if (combinedSSBlocks > maxCombinedSSBlocks)
+ verifyProgram(ctx, sources);
+ else
+ ctx.getLog() << tcu::TestLog::Message << "Test skipped: Combined shader storage blocks < GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS: " << tcu::TestLog::EndMessage;
+
+ ctx.endSection();
+}
+
+} // anonymous
+
+std::vector<FunctionContainer> getNegativeShaderStorageTestFunctions ()
+{
+ const FunctionContainer funcs[] =
+ {
+ { block_number_limits, "block_number_limits", "Invalid shader linkage" },
+ { max_combined_block_number_limit, "max_combined_block_number_limit", "Invalid shader linkage" },
+ };
+
+ return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
+}
+
+} // NegativeTestShared
+} // Functional
+} // gles31
+} // deqp
--- /dev/null
+#ifndef _ES31FNEGATIVESHADERSTORAGETESTS_HPP
+#define _ES31FNEGATIVESHADERSTORAGETESTS_HPP
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.1 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2016 The Android Open Source Project
+ *
+ * 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.
+ *
+ *//*!
+ * \file
+ * \brief Negative Shader Storage Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "es31fNegativeTestShared.hpp"
+
+namespace deqp
+{
+namespace gles31
+{
+namespace Functional
+{
+namespace NegativeTestShared
+{
+
+std::vector<FunctionContainer> getNegativeShaderStorageTestFunctions (void);
+
+} // NegativeTestShared
+} // Functional
+} // gles31
+} // deqp
+
+#endif // _ES31FNEGATIVESHADERSTORAGETESTS_HPP
void get_integeri_v (NegativeTestContext& ctx)
{
- GLint data = -1;
- GLint maxUniformBufferBindings = 0;
+ GLint data = -1;
+ GLint maxUniformBufferBindings = 0;
+ GLint maxShaderStorageBufferBindings = 0;
ctx.beginSection("GL_INVALID_ENUM is generated if name is not an accepted value.");
ctx.glGetIntegeri_v(-1, 0, &data);
ctx.glGetIntegeri_v(GL_UNIFORM_BUFFER_BINDING, maxUniformBufferBindings, &data);
ctx.expectError(GL_INVALID_VALUE);
ctx.endSection();
+
+ ctx.beginSection("GL_INVALID_VALUE is generated if index is outside of the valid range for the indexed state target.");
+ ctx.glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &maxShaderStorageBufferBindings);
+ ctx.expectError(GL_NO_ERROR);
+ ctx.glGetIntegeri_v(GL_SHADER_STORAGE_BUFFER_BINDING, maxShaderStorageBufferBindings, &data);
+ ctx.expectError(GL_INVALID_VALUE);
+ ctx.endSection();
}
void get_integer64i_v (NegativeTestContext& ctx)
{
- GLint64 data = (GLint64)-1;
- GLint maxUniformBufferBindings = 0;
+ GLint64 data = (GLint64)-1;
+ GLint maxUniformBufferBindings = 0;
+ GLint maxShaderStorageBufferBindings = 0;
ctx.beginSection("GL_INVALID_ENUM is generated if name is not an accepted value.");
ctx.glGetInteger64i_v(-1, 0, &data);
ctx.glGetInteger64i_v(GL_UNIFORM_BUFFER_START, maxUniformBufferBindings, &data);
ctx.expectError(GL_INVALID_VALUE);
ctx.endSection();
+
+ ctx.beginSection("GL_INVALID_VALUE is generated if index is outside of the valid range for the indexed state target.");
+ ctx.glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &maxShaderStorageBufferBindings);
+ ctx.expectError(GL_NO_ERROR);
+ ctx.glGetInteger64i_v(GL_SHADER_STORAGE_BUFFER_START, maxShaderStorageBufferBindings, &data);
+ ctx.expectError(GL_INVALID_VALUE);
+ ctx.glGetInteger64i_v(GL_SHADER_STORAGE_BUFFER_SIZE, maxShaderStorageBufferBindings, &data);
+ ctx.expectError(GL_INVALID_VALUE);
+ ctx.endSection();
}
void get_string (NegativeTestContext& ctx)
--- /dev/null
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.1 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2016 The Android Open Source Project
+ *
+ * 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.
+ *
+ *//*!
+ * \file
+ * \brief Negative Tessellation tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "es31fNegativeTessellationTests.hpp"
+#include "gluContextInfo.hpp"
+#include "gluShaderProgram.hpp"
+#include "glwDefs.hpp"
+#include "glwEnums.hpp"
+#include "tcuStringTemplate.hpp"
+
+namespace deqp
+{
+
+using std::string;
+using std::map;
+
+namespace gles31
+{
+namespace Functional
+{
+namespace NegativeTestShared
+{
+
+using tcu::TestLog;
+using namespace glw;
+
+static const char* vertexShaderSource = "${GLSL_VERSION_STRING}\n"
+ "\n"
+ "void main (void)\n"
+ "{\n"
+ " gl_Position = vec4(0.0);\n"
+ "}\n";
+
+static const char* fragmentShaderSource = "${GLSL_VERSION_STRING}\n"
+ "precision mediump float;\n"
+ "layout(location = 0) out mediump vec4 fragColor;\n"
+ "\n"
+ "void main (void)\n"
+ "{\n"
+ " fragColor = vec4(1.0);\n"
+ "}\n";
+
+static const char* tessControlShaderSource = "${GLSL_VERSION_STRING}\n"
+ "${GLSL_TESS_EXTENSION_STRING}\n"
+ "layout (vertices=3) out;\n"
+ "\n"
+ "void main()\n"
+ "{\n"
+ " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
+ "}\n";
+
+static const char* tessEvalShaderSource = "${GLSL_VERSION_STRING}\n"
+ "${GLSL_TESS_EXTENSION_STRING}\n"
+ "layout(triangles) in;\n"
+ "\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = gl_TessCoord[0] * gl_in[0].gl_Position;\n"
+ "}\n";
+
+static void checkExtensionSupport (NegativeTestContext& ctx, const char* extName)
+{
+ if (!ctx.getContextInfo().isExtensionSupported(extName))
+ throw tcu::NotSupportedError(string(extName) + " not supported");
+}
+
+static void checkTessellationSupport (NegativeTestContext& ctx)
+{
+ checkExtensionSupport(ctx, "GL_EXT_tessellation_shader");
+}
+
+// Helper for constructing tessellation pipeline sources.
+static glu::ProgramSources makeTessPipelineSources (const std::string& vertexSrc, const std::string& fragmentSrc, const std::string& tessCtrlSrc, const std::string& tessEvalSrc)
+{
+ glu::ProgramSources sources;
+ sources.sources[glu::SHADERTYPE_VERTEX].push_back(vertexSrc);
+ sources.sources[glu::SHADERTYPE_FRAGMENT].push_back(fragmentSrc);
+
+ if (!tessCtrlSrc.empty())
+ sources.sources[glu::SHADERTYPE_TESSELLATION_CONTROL].push_back(tessCtrlSrc);
+
+ if (!tessEvalSrc.empty())
+ sources.sources[glu::SHADERTYPE_TESSELLATION_EVALUATION].push_back(tessEvalSrc);
+
+ return sources;
+}
+
+// Incomplete active tess shaders
+void single_tessellation_stage (NegativeTestContext& ctx)
+{
+ const bool isES32 = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+ const bool requireTES = !ctx.getContextInfo().isExtensionSupported("GL_NV_gpu_shader5");
+ map<string, string> args;
+ args["GLSL_VERSION_STRING"] = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
+ args["GLSL_TESS_EXTENSION_STRING"] = isES32 ? "" : "#extension GL_EXT_tessellation_shader : require";
+
+ checkTessellationSupport(ctx);
+
+ {
+ glu::ShaderProgram program(ctx.getRenderContext(),
+ makeTessPipelineSources(tcu::StringTemplate(vertexShaderSource).specialize(args),
+ tcu::StringTemplate(fragmentShaderSource).specialize(args),
+ tcu::StringTemplate(tessControlShaderSource).specialize(args),
+ "")); // missing tessEvalShaderSource
+ tcu::TestLog& log = ctx.getLog();
+ log << program;
+
+ ctx.beginSection("A link error is generated if a non-separable program has a tessellation control shader but no tessellation evaluation shader, unless GL_NV_gpu_shader5 is supported.");
+
+ if (requireTES && program.isOk())
+ ctx.fail("Program was not expected to link");
+ else if (!requireTES && !program.isOk())
+ ctx.fail("Program was expected to link");
+
+ ctx.endSection();
+ }
+
+ {
+ glu::ShaderProgram program(ctx.getRenderContext(),
+ makeTessPipelineSources(tcu::StringTemplate(vertexShaderSource).specialize(args),
+ tcu::StringTemplate(fragmentShaderSource).specialize(args),
+ tcu::StringTemplate(tessControlShaderSource).specialize(args),
+ "") // missing tessEvalShaderSource
+ << glu::ProgramSeparable(true));
+ tcu::TestLog& log = ctx.getLog();
+ log << program;
+
+ if (!program.isOk())
+ TCU_THROW(TestError, "failed to build program");
+
+ ctx.glUseProgram(program.getProgram());
+ ctx.expectError(GL_NO_ERROR);
+
+ ctx.beginSection("GL_INVALID_OPERATION is generated if current program state has tessellation control shader but no tessellation evaluation shader, unless GL_NV_gpu_shader5 is supported.");
+ ctx.glDrawArrays(GL_PATCHES, 0, 3);
+ ctx.expectError(requireTES ? GL_INVALID_OPERATION : GL_NO_ERROR);
+ ctx.endSection();
+
+ ctx.glUseProgram(0);
+ }
+
+ {
+ glu::ShaderProgram program(ctx.getRenderContext(),
+ makeTessPipelineSources(tcu::StringTemplate(vertexShaderSource).specialize(args),
+ tcu::StringTemplate(fragmentShaderSource).specialize(args),
+ "", // missing tessControlShaderSource
+ tcu::StringTemplate(tessEvalShaderSource).specialize(args)));
+ tcu::TestLog& log = ctx.getLog();
+ log << program;
+
+ ctx.beginSection("A link error is generated if a non-separable program has a tessellation evaluation shader but no tessellation control shader.");
+
+ if (program.isOk())
+ ctx.fail("Program was not expected to link");
+
+ ctx.endSection();
+ }
+
+ {
+ glu::ShaderProgram program(ctx.getRenderContext(),
+ makeTessPipelineSources(tcu::StringTemplate(vertexShaderSource).specialize(args),
+ tcu::StringTemplate(fragmentShaderSource).specialize(args),
+ "", // missing tessControlShaderSource
+ tcu::StringTemplate(tessEvalShaderSource).specialize(args))
+ << glu::ProgramSeparable(true));
+ tcu::TestLog& log = ctx.getLog();
+ log << program;
+
+ if (!program.isOk())
+ TCU_THROW(TestError, "failed to build program");
+
+ ctx.glUseProgram(program.getProgram());
+ ctx.expectError(GL_NO_ERROR);
+
+ ctx.beginSection("GL_INVALID_OPERATION is generated if current program state has tessellation evaluation shader but no tessellation control shader.");
+ ctx.glDrawArrays(GL_PATCHES, 0, 3);
+ ctx.expectError(GL_INVALID_OPERATION);
+ ctx.endSection();
+
+ ctx.glUseProgram(0);
+ }
+}
+
+// Complete active tess shaders invalid primitive mode
+void invalid_primitive_mode (NegativeTestContext& ctx)
+{
+ checkTessellationSupport(ctx);
+
+ const bool isES32 = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+ map<string, string> args;
+ args["GLSL_VERSION_STRING"] = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
+ args["GLSL_TESS_EXTENSION_STRING"] = isES32 ? "" : "#extension GL_EXT_tessellation_shader : require";
+
+ glu::ShaderProgram program(ctx.getRenderContext(),
+ makeTessPipelineSources(tcu::StringTemplate(vertexShaderSource).specialize(args),
+ tcu::StringTemplate(fragmentShaderSource).specialize(args),
+ tcu::StringTemplate(tessControlShaderSource).specialize(args),
+ tcu::StringTemplate(tessEvalShaderSource).specialize(args)));
+ tcu::TestLog& log = ctx.getLog();
+ log << program;
+
+ ctx.glUseProgram(program.getProgram());
+ ctx.expectError(GL_NO_ERROR);
+
+ ctx.beginSection("GL_INVALID_OPERATION is generated if tessellation is active and primitive mode is not GL_PATCHES.");
+ ctx.glDrawArrays(GL_TRIANGLES, 0, 3);
+ ctx.expectError(GL_INVALID_OPERATION);
+ ctx.endSection();
+
+ ctx.glUseProgram(0);
+}
+
+void tessellation_not_active (NegativeTestContext& ctx)
+{
+ checkTessellationSupport(ctx);
+
+ const bool isES32 = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+ const glw::GLenum tessErr = ctx.getContextInfo().isExtensionSupported("GL_NV_gpu_shader5") ? GL_NO_ERROR : GL_INVALID_OPERATION;
+ map<string, string> args;
+ args["GLSL_VERSION_STRING"] = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
+ args["GLSL_TESS_EXTENSION_STRING"] = isES32 ? "" : "#extension GL_EXT_tessellation_shader : require";
+
+ glu::ShaderProgram program(ctx.getRenderContext(),
+ makeTessPipelineSources(tcu::StringTemplate(vertexShaderSource).specialize(args),
+ tcu::StringTemplate(fragmentShaderSource).specialize(args),
+ "", // missing tessControlShaderSource
+ "")); // missing tessEvalShaderSource
+ tcu::TestLog& log = ctx.getLog();
+ log << program;
+
+ ctx.glUseProgram(program.getProgram());
+ ctx.expectError(GL_NO_ERROR);
+
+ ctx.beginSection("GL_INVALID_OPERATION is generated if tessellation is not active and primitive mode is GL_PATCHES, unless GL_NV_gpu_shader5 is supported.");
+ ctx.glDrawArrays(GL_PATCHES, 0, 3);
+ ctx.expectError(tessErr);
+ ctx.endSection();
+
+ ctx.glUseProgram(0);
+}
+
+void invalid_program_state (NegativeTestContext& ctx)
+{
+ checkTessellationSupport(ctx);
+
+ const bool isES32 = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+ map<string, string> args;
+ args["GLSL_VERSION_STRING"] = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
+ args["GLSL_TESS_EXTENSION_STRING"] = isES32 ? "" : "#extension GL_EXT_tessellation_shader : require";
+
+ glu::FragmentSource frgSource(tcu::StringTemplate(fragmentShaderSource).specialize(args));
+ glu::TessellationControlSource tessCtrlSource(tcu::StringTemplate(tessControlShaderSource).specialize(args));
+ glu::TessellationEvaluationSource tessEvalSource(tcu::StringTemplate(tessEvalShaderSource).specialize(args));
+
+ glu::ProgramPipeline pipeline(ctx.getRenderContext());
+
+ glu::ShaderProgram fragProgram (ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << frgSource);
+ glu::ShaderProgram tessCtrlProgram (ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << tessCtrlSource);
+ glu::ShaderProgram tessEvalProgram (ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << tessEvalSource);
+
+ tcu::TestLog& log = ctx.getLog();
+ log << fragProgram << tessCtrlProgram << tessEvalProgram;
+
+ if (!fragProgram.isOk() || !tessCtrlProgram.isOk() || !tessEvalProgram.isOk())
+ throw tcu::TestError("failed to build program");
+
+ ctx.glBindProgramPipeline(pipeline.getPipeline());
+ ctx.expectError(GL_NO_ERROR);
+
+ ctx.glUseProgramStages(pipeline.getPipeline(), GL_FRAGMENT_SHADER_BIT, fragProgram.getProgram());
+ ctx.glUseProgramStages(pipeline.getPipeline(), GL_TESS_CONTROL_SHADER_BIT, tessCtrlProgram.getProgram());
+ ctx.glUseProgramStages(pipeline.getPipeline(), GL_TESS_EVALUATION_SHADER_BIT, tessEvalProgram.getProgram());
+ ctx.expectError(GL_NO_ERROR);
+
+ ctx.beginSection("GL_INVALID_OPERATION is generated if tessellation is active and vertex shader is missing.");
+ ctx.glDrawArrays(GL_PATCHES, 0, 3);
+ ctx.expectError(GL_INVALID_OPERATION);
+ ctx.endSection();
+
+ ctx.glBindProgramPipeline(0);
+ ctx.expectError(GL_NO_ERROR);
+}
+
+void tessellation_control_invalid_vertex_count (NegativeTestContext& ctx)
+{
+ checkTessellationSupport(ctx);
+
+ const char* const tessControlVertLimitSource = "${GLSL_VERSION_STRING}\n"
+ "${GLSL_TESS_EXTENSION_STRING}\n"
+ "layout (vertices=${GL_MAX_PATCH_LIMIT}) out;\n"
+ "void main()\n"
+ "{\n"
+ " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
+ "}\n";
+
+ const bool isES32 = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+ map<string, string> args;
+ args["GLSL_VERSION_STRING"] = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
+ args["GLSL_TESS_EXTENSION_STRING"] = isES32 ? "" : "#extension GL_EXT_tessellation_shader : require";
+
+ int maxPatchVertices= 0;
+
+ ctx.beginSection("Output vertex count exceeds GL_MAX_PATCH_VERTICES.");
+ ctx.glGetIntegerv(GL_MAX_PATCH_VERTICES, &maxPatchVertices);
+ ctx.expectError(GL_NO_ERROR);
+
+ std::ostringstream oss;
+ oss << (maxPatchVertices + 1);
+ args["GL_MAX_PATCH_LIMIT"] = oss.str();
+
+
+ glu::ShaderProgram program(ctx.getRenderContext(),
+ makeTessPipelineSources(tcu::StringTemplate(vertexShaderSource).specialize(args),
+ tcu::StringTemplate(fragmentShaderSource).specialize(args),
+ tcu::StringTemplate(tessControlVertLimitSource).specialize(args),
+ tcu::StringTemplate(tessEvalShaderSource).specialize(args)));
+ tcu::TestLog& log = ctx.getLog();
+ log << program;
+
+ bool testFailed = program.getProgramInfo().linkOk;
+
+ if (testFailed)
+ ctx.fail("Program was not expected to link");
+
+ ctx.endSection();
+}
+
+void invalid_get_programiv (NegativeTestContext& ctx)
+{
+ checkTessellationSupport(ctx);
+
+ GLuint program = ctx.glCreateProgram();
+ GLint params[1] = { 0 };
+
+ ctx.beginSection("GL_INVALID_OPERATION is generated if GL_TESS_CONTROL_OUTPUT_VERTICES is queried for a program which has not been linked properly.");
+ ctx.glGetProgramiv(program, GL_TESS_CONTROL_OUTPUT_VERTICES, ¶ms[0]);
+ ctx.expectError(GL_INVALID_OPERATION);
+ ctx.endSection();
+
+ ctx.beginSection("GL_INVALID_OPERATION is generated if GL_TESS_GEN_MODE is queried for a program which has not been linked properly.");
+ ctx.glGetProgramiv(program, GL_TESS_GEN_MODE, ¶ms[0]);
+ ctx.expectError(GL_INVALID_OPERATION);
+ ctx.endSection();
+
+ ctx.beginSection("GL_INVALID_OPERATION is generated if GL_TESS_GEN_SPACING is queried for a program which has not been linked properly.");
+ ctx.glGetProgramiv(program, GL_TESS_GEN_SPACING, ¶ms[0]);
+ ctx.expectError(GL_INVALID_OPERATION);
+ ctx.endSection();
+
+ ctx.beginSection("GL_INVALID_OPERATION is generated if GL_TESS_GEN_VERTEX_ORDER is queried for a program which has not been linked properly.");
+ ctx.glGetProgramiv(program, GL_TESS_GEN_VERTEX_ORDER, ¶ms[0]);
+ ctx.expectError(GL_INVALID_OPERATION);
+ ctx.endSection();
+
+ ctx.beginSection("GL_INVALID_OPERATION is generated if GL_TESS_GEN_POINT_MODE is queried for a program which has not been linked properly.");
+ ctx.glGetProgramiv(program, GL_TESS_GEN_POINT_MODE, ¶ms[0]);
+ ctx.expectError(GL_INVALID_OPERATION);
+ ctx.endSection();
+
+ ctx.glDeleteProgram(program);
+}
+
+void invalid_patch_parameteri (NegativeTestContext& ctx)
+{
+ checkTessellationSupport(ctx);
+
+ ctx.beginSection("GL_INVALID_ENUM is generated if pname is not GL_PATCH_VERTICES.");
+ ctx.glPatchParameteri(-1, 1);
+ ctx.expectError(GL_INVALID_ENUM);
+ ctx.endSection();
+
+ ctx.beginSection("GL_INVALID_VALUE is generated if value is less than or equal to zero.");
+ ctx.glPatchParameteri(GL_PATCH_VERTICES, 0);
+ ctx.expectError(GL_INVALID_VALUE);
+ ctx.endSection();
+
+ int maxPatchVertices= 0;
+ ctx.glGetIntegerv(GL_MAX_PATCH_VERTICES, &maxPatchVertices);
+ ctx.expectError(GL_NO_ERROR);
+
+ ctx.beginSection("GL_INVALID_VALUE is generated if value is greater than GL_MAX_PATCH_VERTICES.");
+ ctx.glPatchParameteri(GL_PATCH_VERTICES, maxPatchVertices + 1);
+ ctx.expectError(GL_INVALID_VALUE);
+ ctx.endSection();
+}
+
+std::vector<FunctionContainer> getNegativeTessellationTestFunctions (void)
+{
+ const FunctionContainer funcs[] =
+ {
+ { single_tessellation_stage, "single_tessellation_stage", "Invalid program state with single tessellation stage" },
+ { invalid_primitive_mode, "invalid_primitive_mode", "Invalid primitive mode when tessellation is active" },
+ { tessellation_not_active, "tessellation_not_active", "Use of GL_PATCHES when tessellation is not active" },
+ { invalid_program_state, "invalid_program_state", "Invalid program state when tessellation active but no vertex shader present" },
+ { invalid_get_programiv, "get_programiv", "Invalid glGetProgramiv() usage" },
+ { invalid_patch_parameteri, "invalid_program_queries", "Invalid glPatchParameteri() usage" },
+ { tessellation_control_invalid_vertex_count, "tessellation_control_invalid_vertex_count", "Exceed vertex count limit in tessellation control shader" },
+ };
+
+ return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
+}
+
+} // NegativeTestShared
+} // Functional
+} // gles31
+} // deqp
--- /dev/null
+#ifndef _ES31FNEGATIVETESSELLATIONTESTS_HPP
+#define _ES31FNEGATIVETESSELLATIONTESTS_HPP
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.1 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2016 The Android Open Source Project
+ *
+ * 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.
+ *
+ *//*!
+ * \file
+ * \brief Negative Tessellation tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "es31fNegativeTestShared.hpp"
+
+namespace deqp
+{
+namespace gles31
+{
+namespace Functional
+{
+namespace NegativeTestShared
+{
+
+std::vector<FunctionContainer> getNegativeTessellationTestFunctions (void);
+
+} // NegativeTestShared
+} // Functional
+} // gles3
+} // deqp
+
+#endif // _ES31FNEGATIVETESSELLATIONTESTS_HPP
ctx.glTexImage3D (GL_TEXTURE_3D, 0, GL_RGBA, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
ctx.glBindTexture (GL_TEXTURE_2D_ARRAY, textures[1]);
ctx.glTexImage3D (GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
- ctx.glBindTexture (GL_TEXTURE_CUBE_MAP_ARRAY, textures[2]);
- ctx.glTexImage3D (GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGBA, 4, 4, 6, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
ctx.expectError (GL_NO_ERROR);
ctx.beginSection("GL_INVALID_VALUE is generated if level is less than 0.");
if (contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)) || ctx.getContextInfo().isExtensionSupported("GL_OES_texture_cube_map_array"))
{
+ ctx.glBindTexture (GL_TEXTURE_CUBE_MAP_ARRAY, textures[2]);
+ ctx.glTexImage3D (GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGBA, 4, 4, 6, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+ ctx.expectError (GL_NO_ERROR);
+
ctx.glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, -1, 0, 0, 0, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
ctx.expectError(GL_INVALID_VALUE);
}
ctx.glTexImage3D (GL_TEXTURE_3D, 0, GL_RGBA, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
ctx.glBindTexture (GL_TEXTURE_2D_ARRAY, textures[1]);
ctx.glTexImage3D (GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
- ctx.glBindTexture (GL_TEXTURE_CUBE_MAP_ARRAY, textures[2]);
- ctx.glTexImage3D (GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGBA, 4, 4, 6, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
ctx.expectError (GL_NO_ERROR);
ctx.beginSection("GL_INVALID_VALUE is generated if xoffset, yoffset or zoffset are negative.");
if (contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)) || ctx.getContextInfo().isExtensionSupported("GL_OES_texture_cube_map_array"))
{
+ ctx.glBindTexture (GL_TEXTURE_CUBE_MAP_ARRAY, textures[2]);
+ ctx.glTexImage3D (GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGBA, 4, 4, 6, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+ ctx.expectError (GL_NO_ERROR);
+
ctx.glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, -1, 0, 0, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
ctx.expectError(GL_INVALID_VALUE);
ctx.glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, -1, 0, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
{
SCANRESULT_NUM_LINES_OK_BIT = (1 << 0),
SCANRESULT_LINE_WIDTH_OK_BIT = (1 << 1),
+ SCANRESULT_LINE_WIDTH_WARN_BIT = (1 << 2),
+ SCANRESULT_LINE_WIDTH_ERR_BIT = (1 << 3),
+ SCANRESULT_LINE_CONT_OK_BIT = (1 << 4),
+ SCANRESULT_LINE_CONT_ERR_BIT = (1 << 5),
+ SCANRESULT_LINE_CONT_WARN_BIT = (1 << 6),
};
void init (void);
void verifyRenderResult (const IterationConfig& config);
tcu::IVec2 getNumberOfLinesRange (int queryAreaBegin, int queryAreaEnd, float patternStart, float patternSize, int viewportArea, QueryDirection queryDir) const;
- deUint8 scanRow (const tcu::ConstPixelBufferAccess& access, int row, int rowBegin, int rowEnd, const tcu::IVec2& numLines, int& floodCounter) const;
- deUint8 scanColumn (const tcu::ConstPixelBufferAccess& access, int column, int columnBegin, int columnEnd, const tcu::IVec2& numLines, int& floodCounter) const;
+ deUint8 scanRow (const tcu::ConstPixelBufferAccess& access, int row, int rowBegin, int rowEnd, int rowViewportBegin, int rowViewportEnd, const tcu::IVec2& numLines, int& floodCounter) const;
+ deUint8 scanColumn (const tcu::ConstPixelBufferAccess& access, int column, int columnBegin, int columnEnd, int columnViewportBegin, int columnViewportEnd, const tcu::IVec2& numLines, int& floodCounter) const;
bool checkAreaNumLines (const tcu::ConstPixelBufferAccess& access, const tcu::IVec4& area, int& floodCounter, int componentNdx, const tcu::IVec2& numLines) const;
+ deUint8 checkLineContinuity (const tcu::ConstPixelBufferAccess& access, const tcu::IVec2& begin, const tcu::IVec2& end, int componentNdx, int& messageLimitCounter) const;
tcu::IVec2 getNumMinimaMaxima (const tcu::ConstPixelBufferAccess& access, int componentNdx) const;
- bool checkLineWidths (const tcu::ConstPixelBufferAccess& access, const tcu::IVec2& begin, const tcu::IVec2& end, int componentNdx, int& floodCounter) const;
+ deUint8 checkLineWidths (const tcu::ConstPixelBufferAccess& access, const tcu::IVec2& begin, const tcu::IVec2& end, int componentNdx, int& floodCounter) const;
void printLineWidthError (const tcu::IVec2& pos, int detectedLineWidth, const tcu::IVec2& lineWidthRange, bool isHorizontal, int& floodCounter) const;
const int m_patternSide;
void LineRenderCase::verifyRenderResult (const IterationConfig& config)
{
- const glw::Functions& gl = m_context.getRenderContext().getFunctions();
- const bool isMsaa = m_context.getRenderTarget().getNumSamples() > 1;
- const ProjectedBBox projectedBBox = projectBoundingBox(config.bbox);
- const float lineWidth = (m_isWideLineCase) ? ((float)m_wideLineLineWidth) : (1.0f);
- const tcu::IVec4 viewportBBoxArea = getViewportBoundingBoxArea(projectedBBox, config.viewportSize, lineWidth);
- const tcu::IVec4 viewportPatternArea = getViewportPatternArea(config.patternPos, config.patternSize, config.viewportSize, ROUND_INWARDS);
- const tcu::IVec2 expectedHorizontalLines = getNumberOfLinesRange(viewportBBoxArea.y(), viewportBBoxArea.w(), config.patternPos.y(), config.patternSize.y(), config.viewportSize.y(), DIRECTION_VERTICAL);
- const tcu::IVec2 expectedVerticalLines = getNumberOfLinesRange(viewportBBoxArea.x(), viewportBBoxArea.z(), config.patternPos.x(), config.patternSize.x(), config.viewportSize.x(), DIRECTION_HORIZONTAL);
- const tcu::IVec4 verificationArea = tcu::IVec4(de::max(viewportBBoxArea.x(), 0),
- de::max(viewportBBoxArea.y(), 0),
- de::min(viewportBBoxArea.z(), config.viewportSize.x()),
- de::min(viewportBBoxArea.w(), config.viewportSize.y()));
+ const glw::Functions& gl = m_context.getRenderContext().getFunctions();
+ const bool isMsaa = m_context.getRenderTarget().getNumSamples() > 1;
+ const ProjectedBBox projectedBBox = projectBoundingBox(config.bbox);
+ const float lineWidth = (m_isWideLineCase) ? ((float)m_wideLineLineWidth) : (1.0f);
+ const tcu::IVec4 viewportBBoxArea = getViewportBoundingBoxArea(projectedBBox, config.viewportSize, lineWidth);
+ const tcu::IVec4 viewportPatternArea = getViewportPatternArea(config.patternPos, config.patternSize, config.viewportSize, ROUND_INWARDS);
+ const tcu::IVec2 expectedHorizontalLines = getNumberOfLinesRange(viewportBBoxArea.y(), viewportBBoxArea.w(), config.patternPos.y(), config.patternSize.y(), config.viewportSize.y(), DIRECTION_VERTICAL);
+ const tcu::IVec2 expectedVerticalLines = getNumberOfLinesRange(viewportBBoxArea.x(), viewportBBoxArea.z(), config.patternPos.x(), config.patternSize.x(), config.viewportSize.x(), DIRECTION_HORIZONTAL);
+ const tcu::IVec4 verificationArea = tcu::IVec4(de::max(viewportBBoxArea.x(), 0),
+ de::max(viewportBBoxArea.y(), 0),
+ de::min(viewportBBoxArea.z(), config.viewportSize.x()),
+ de::min(viewportBBoxArea.w(), config.viewportSize.y()));
+
+ tcu::Surface viewportSurface (config.viewportSize.x(), config.viewportSize.y());
+ int messageLimitCounter = 8;
+
+ enum ScanResultCodes
+ {
+ SCANRESULT_NUM_LINES_ERR = 0,
+ SCANRESULT_LINE_WIDTH_MSAA = 1,
+ SCANRESULT_LINE_WIDTH_WARN = 2,
+ SCANRESULT_LINE_WIDTH_ERR = 3,
+ SCANRESULT_LINE_CONT_ERR = 4,
+ SCANRESULT_LINE_CONT_WARN = 5,
+ SCANRESULT_LINE_LAST
+ };
- tcu::Surface viewportSurface (config.viewportSize.x(), config.viewportSize.y());
- bool anyError = false;
- bool msaaRelaxationRequired = false;
- int messageLimitCounter = 8;
+ int rowScanResult[SCANRESULT_LINE_LAST] = {0, 0, 0, 0, 0, 0};
+ int columnScanResult[SCANRESULT_LINE_LAST] = {0, 0, 0, 0, 0, 0};
+ bool anyError = false;
+ bool msaaRelaxationRequired = false;
+ bool hwIssueRelaxationRequired = false;
if (!m_calcPerPrimitiveBBox)
m_testCtx.getLog()
y,
verificationArea.x(),
verificationArea.z(),
+ de::max(verificationArea.x(), viewportPatternArea.x()),
+ de::min(verificationArea.z(), viewportPatternArea.z()),
expectedVerticalLines,
messageLimitCounter);
if ((result & SCANRESULT_NUM_LINES_OK_BIT) == 0)
- anyError = true;
+ rowScanResult[SCANRESULT_NUM_LINES_ERR]++;
+ if ((result & SCANRESULT_LINE_CONT_OK_BIT) == 0)
+ {
+ if ((result & SCANRESULT_LINE_CONT_WARN_BIT) != 0)
+ rowScanResult[SCANRESULT_LINE_CONT_WARN]++;
+ else
+ rowScanResult[SCANRESULT_LINE_CONT_ERR]++;
+ }
else if ((result & SCANRESULT_LINE_WIDTH_OK_BIT) == 0)
{
if (m_isWideLineCase && isMsaa)
{
// multisampled wide lines might not be supported
- msaaRelaxationRequired = true;
+ rowScanResult[SCANRESULT_LINE_WIDTH_MSAA]++;
+ }
+ else if ((result & SCANRESULT_LINE_WIDTH_ERR_BIT) == 0 &&
+ (result & SCANRESULT_LINE_WIDTH_WARN_BIT) != 0)
+ {
+ rowScanResult[SCANRESULT_LINE_WIDTH_WARN]++;
}
else
- anyError = true;
+ rowScanResult[SCANRESULT_LINE_WIDTH_ERR]++;
}
}
x,
verificationArea.y(),
verificationArea.w(),
+ de::min(verificationArea.y(), viewportPatternArea.y()),
+ de::min(verificationArea.w(), viewportPatternArea.w()),
expectedHorizontalLines,
messageLimitCounter);
if ((result & SCANRESULT_NUM_LINES_OK_BIT) == 0)
- anyError = true;
+ columnScanResult[SCANRESULT_NUM_LINES_ERR]++;
+ if ((result & SCANRESULT_LINE_CONT_OK_BIT) == 0)
+ {
+ if ((result & SCANRESULT_LINE_CONT_WARN_BIT) != 0)
+ columnScanResult[SCANRESULT_LINE_CONT_WARN]++;
+ else
+ columnScanResult[SCANRESULT_LINE_CONT_ERR]++;
+ }
else if ((result & SCANRESULT_LINE_WIDTH_OK_BIT) == 0)
{
if (m_isWideLineCase && isMsaa)
{
// multisampled wide lines might not be supported
- msaaRelaxationRequired = true;
+ columnScanResult[SCANRESULT_LINE_WIDTH_MSAA]++;
+ }
+ else if ((result & SCANRESULT_LINE_WIDTH_ERR_BIT) == 0 &&
+ (result & SCANRESULT_LINE_WIDTH_WARN_BIT) != 0)
+ {
+ columnScanResult[SCANRESULT_LINE_WIDTH_WARN]++;
}
else
- anyError = true;
+ columnScanResult[SCANRESULT_LINE_WIDTH_ERR]++;
}
}
- if (anyError || msaaRelaxationRequired)
+ if (columnScanResult[SCANRESULT_LINE_WIDTH_ERR] != 0 || rowScanResult[SCANRESULT_LINE_WIDTH_ERR] != 0)
+ anyError = true;
+ else if(columnScanResult[SCANRESULT_LINE_CONT_ERR] != 0 || rowScanResult[SCANRESULT_LINE_CONT_ERR] != 0)
+ anyError = true;
+ else if (columnScanResult[SCANRESULT_LINE_WIDTH_MSAA] != 0 || rowScanResult[SCANRESULT_LINE_WIDTH_MSAA] != 0)
+ msaaRelaxationRequired = true;
+ else if (columnScanResult[SCANRESULT_LINE_WIDTH_WARN] != 0 || rowScanResult[SCANRESULT_LINE_WIDTH_WARN] != 0)
+ hwIssueRelaxationRequired = true;
+ else if (columnScanResult[SCANRESULT_NUM_LINES_ERR] != 0)
+ {
+ // found missing lines in a columnw and row line continuity check reported a warning (not an error) -> line width precision issue
+ if (rowScanResult[SCANRESULT_LINE_CONT_ERR] == 0 && rowScanResult[SCANRESULT_LINE_CONT_WARN])
+ hwIssueRelaxationRequired = true;
+ else
+ anyError = true;
+ }
+ else if (rowScanResult[SCANRESULT_NUM_LINES_ERR] != 0)
+ {
+ // found missing lines in a row and column line continuity check reported a warning (not an error) -> line width precision issue
+ if (columnScanResult[SCANRESULT_LINE_CONT_ERR] == 0 && columnScanResult[SCANRESULT_LINE_CONT_WARN])
+ hwIssueRelaxationRequired = true;
+ else
+ anyError = true;
+ }
+
+ if (anyError || msaaRelaxationRequired || hwIssueRelaxationRequired)
{
if (messageLimitCounter < 0)
m_testCtx.getLog() << tcu::TestLog::Message << "Omitted " << (-messageLimitCounter) << " row/column error descriptions." << tcu::TestLog::EndMessage;
if (anyError)
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed");
+ else if (hwIssueRelaxationRequired)
+ {
+ // Line width hw issue
+ m_testCtx.setTestResult(QP_TEST_RESULT_QUALITY_WARNING, "Line width verification failed");
+ }
else
{
// MSAA wide lines are optional
return tcu::IVec2(numLinesMin, numLinesMax);
}
-deUint8 LineRenderCase::scanRow (const tcu::ConstPixelBufferAccess& access, int row, int rowBegin, int rowEnd, const tcu::IVec2& numLines, int& messageLimitCounter) const
+deUint8 LineRenderCase::scanRow (const tcu::ConstPixelBufferAccess& access, int row, int rowBegin, int rowEnd, int rowViewportBegin, int rowViewportEnd, const tcu::IVec2& numLines, int& messageLimitCounter) const
{
- const bool numLinesOk = checkAreaNumLines(access, tcu::IVec4(rowBegin, row, rowEnd - rowBegin, 1), messageLimitCounter, SCAN_ROW_COMPONENT_NDX, numLines);
- const bool lineWidthOk = checkLineWidths(access, tcu::IVec2(rowBegin, row), tcu::IVec2(rowEnd, row), SCAN_ROW_COMPONENT_NDX, messageLimitCounter);
+ const bool numLinesOk = checkAreaNumLines(access, tcu::IVec4(rowBegin, row, rowEnd - rowBegin, 1), messageLimitCounter, SCAN_ROW_COMPONENT_NDX, numLines);
+ const deUint8 lineWidthRes = checkLineWidths(access, tcu::IVec2(rowBegin, row), tcu::IVec2(rowEnd, row), SCAN_ROW_COMPONENT_NDX, messageLimitCounter);
+ const deUint8 lineContinuityRes = checkLineContinuity(access, tcu::IVec2(rowViewportBegin, row), tcu::IVec2(rowViewportEnd, row), SCAN_COL_COMPONENT_NDX, messageLimitCounter);
+ deUint8 result = 0;
- return (deUint8)((numLinesOk ? (deUint8)SCANRESULT_NUM_LINES_OK_BIT : 0u) |
- (lineWidthOk ? (deUint8)SCANRESULT_LINE_WIDTH_OK_BIT : 0u));
+ if (numLinesOk)
+ result |= (deUint8)SCANRESULT_NUM_LINES_OK_BIT;
+
+ if (lineContinuityRes == 0)
+ result |= (deUint8)SCANRESULT_LINE_CONT_OK_BIT;
+ else
+ result |= lineContinuityRes;
+
+ if (lineWidthRes == 0)
+ result |= (deUint8)SCANRESULT_LINE_WIDTH_OK_BIT;
+ else
+ result |= lineWidthRes;
+
+ return result;
}
-deUint8 LineRenderCase::scanColumn (const tcu::ConstPixelBufferAccess& access, int column, int columnBegin, int columnEnd, const tcu::IVec2& numLines, int& messageLimitCounter) const
+deUint8 LineRenderCase::scanColumn (const tcu::ConstPixelBufferAccess& access, int column, int columnBegin, int columnEnd, int columnViewportBegin, int columnViewportEnd, const tcu::IVec2& numLines, int& messageLimitCounter) const
{
- const bool numLinesOk = checkAreaNumLines(access, tcu::IVec4(column, columnBegin, 1, columnEnd - columnBegin), messageLimitCounter, SCAN_COL_COMPONENT_NDX, numLines);
- const bool lineWidthOk = checkLineWidths(access, tcu::IVec2(column, columnBegin), tcu::IVec2(column, columnEnd), SCAN_COL_COMPONENT_NDX, messageLimitCounter);
+ const bool numLinesOk = checkAreaNumLines(access, tcu::IVec4(column, columnBegin, 1, columnEnd - columnBegin), messageLimitCounter, SCAN_COL_COMPONENT_NDX, numLines);
+ const deUint8 lineWidthRes = checkLineWidths(access, tcu::IVec2(column, columnBegin), tcu::IVec2(column, columnEnd), SCAN_COL_COMPONENT_NDX, messageLimitCounter);
+ const deUint8 lineContinuityRes = checkLineContinuity(access, tcu::IVec2(column, columnViewportBegin), tcu::IVec2(column, columnViewportEnd), SCAN_ROW_COMPONENT_NDX, messageLimitCounter);
+ deUint8 result = 0;
+
+ if (numLinesOk)
+ result |= (deUint8)SCANRESULT_NUM_LINES_OK_BIT;
+
+ if (lineContinuityRes == 0)
+ result |= (deUint8)SCANRESULT_LINE_CONT_OK_BIT;
+ else
+ result |= lineContinuityRes;
- return (deUint8)((numLinesOk ? (deUint8)SCANRESULT_NUM_LINES_OK_BIT : 0u) |
- (lineWidthOk ? (deUint8)SCANRESULT_LINE_WIDTH_OK_BIT : 0u));
+ if (lineWidthRes == 0)
+ result |= (deUint8)SCANRESULT_LINE_WIDTH_OK_BIT;
+ else
+ result |= lineWidthRes;
+
+ return result;
}
bool LineRenderCase::checkAreaNumLines (const tcu::ConstPixelBufferAccess& access, const tcu::IVec4& area, int& messageLimitCounter, int componentNdx, const tcu::IVec2& numLines) const
return tcu::IVec2(numMinima, numMaxima);
}
-bool LineRenderCase::checkLineWidths (const tcu::ConstPixelBufferAccess& access, const tcu::IVec2& begin, const tcu::IVec2& end, int componentNdx, int& messageLimitCounter) const
+deUint8 LineRenderCase::checkLineContinuity (const tcu::ConstPixelBufferAccess& access, const tcu::IVec2& begin, const tcu::IVec2& end, int componentNdx, int& messageLimitCounter) const
{
- const bool multisample = m_context.getRenderTarget().getNumSamples() > 1;
- const int lineRenderWidth = (m_isWideLineCase) ? (m_wideLineLineWidth) : 1;
- const tcu::IVec2 lineWidthRange = (multisample)
- ? (tcu::IVec2(lineRenderWidth, lineRenderWidth+1)) // multisampled "smooth" lines may spread to neighboring pixel
- : (tcu::IVec2(lineRenderWidth, lineRenderWidth));
+ bool line = false;
+ const tcu::IVec2 advance = (begin.x() == end.x()) ? (tcu::IVec2(0, 1)) : (tcu::IVec2(1, 0));
+ int missedPixels = 0;
+ int totalPixels = 0;
+ deUint8 errorMask = 0;
- int lineWidth = 0;
- bool bboxLimitedLine = false;
- bool anyError = false;
+ for (tcu::IVec2 cursor = begin; cursor != end; cursor += advance)
+ {
+ const bool hit = (access.getPixelInt(cursor.x(), cursor.y())[componentNdx] != 0);
+
+ if (hit)
+ line = true;
+ else if (line && !hit)
+ {
+ // non-continuous line detected
+ const tcu::IVec2 advanceNeighbor = tcu::IVec2(1, 1) - advance;
+ const tcu::IVec2 cursorNeighborPos = cursor + advanceNeighbor;
+ const tcu::IVec2 cursorNeighborNeg = cursor - advanceNeighbor;
+ // hw precision issues may lead to a line being non-straight -> check neighboring pixels
+ if ((access.getPixelInt(cursorNeighborPos.x(), cursorNeighborPos.y())[componentNdx] == 0) && (access.getPixelInt(cursorNeighborNeg.x(), cursorNeighborNeg.y())[componentNdx] == 0))
+ ++missedPixels;
+ }
+ ++totalPixels;
+ }
+
+ if (missedPixels > 0 && --messageLimitCounter >= 0)
+ {
+ m_testCtx.getLog()
+ << tcu::TestLog::Message
+ << "Found non-continuous " << ((advance.x() == 1) ? ("horizontal") : ("vertical")) << " line near " << begin << ". "
+ << "Missed pixels: " << missedPixels
+ << tcu::TestLog::EndMessage;
+ // allow 10% missing pixels for warning
+ if (missedPixels <= deRoundFloatToInt32((float)totalPixels * 0.1f))
+ errorMask = SCANRESULT_LINE_CONT_WARN_BIT;
+ else
+ errorMask = SCANRESULT_LINE_CONT_ERR_BIT;
+ }
+
+ return errorMask;
+}
+
+deUint8 LineRenderCase::checkLineWidths (const tcu::ConstPixelBufferAccess& access, const tcu::IVec2& begin, const tcu::IVec2& end, int componentNdx, int& messageLimitCounter) const
+{
+ const bool multisample = m_context.getRenderTarget().getNumSamples() > 1;
+ const int lineRenderWidth = (m_isWideLineCase) ? (m_wideLineLineWidth) : 1;
+ const tcu::IVec2 lineWidthRange = (multisample)
+ ? (tcu::IVec2(lineRenderWidth, lineRenderWidth+1)) // multisampled "smooth" lines may spread to neighboring pixel
+ : (tcu::IVec2(lineRenderWidth, lineRenderWidth));
+ const tcu::IVec2 relaxedLineWidthRange = (tcu::IVec2(lineRenderWidth-1, lineRenderWidth+1));
- const tcu::IVec2 advance = (begin.x() == end.x()) ? (tcu::IVec2(0, 1)) : (tcu::IVec2(1, 0));
+ int lineWidth = 0;
+ bool bboxLimitedLine = false;
+ deUint8 errorMask = 0;
+
+ const tcu::IVec2 advance = (begin.x() == end.x()) ? (tcu::IVec2(0, 1)) : (tcu::IVec2(1, 0));
// fragments before begin?
if (access.getPixelInt(begin.x(), begin.y())[componentNdx] != 0)
if (incorrectLineWidth)
{
- anyError = true;
+ const bool incorrectRelaxedLineWidth = (lineWidth < relaxedLineWidthRange.x() && !bboxLimitedLine) || (lineWidth > relaxedLineWidthRange.y());
+
+ if (incorrectRelaxedLineWidth)
+ errorMask |= SCANRESULT_LINE_WIDTH_ERR_BIT;
+ else
+ errorMask |= SCANRESULT_LINE_WIDTH_WARN_BIT;
+
printLineWidthError(cursor, lineWidth, lineWidthRange, advance.x() == 0, messageLimitCounter);
}
{
if (lineWidth > lineWidthRange.y())
{
- anyError = true;
+ if (lineWidth > relaxedLineWidthRange.y())
+ errorMask |= SCANRESULT_LINE_WIDTH_ERR_BIT;
+ else
+ errorMask |= SCANRESULT_LINE_WIDTH_WARN_BIT;
+
printLineWidthError(cursor, lineWidth, lineWidthRange, advance.x() == 0, messageLimitCounter);
}
if (incorrectLineWidth)
{
- anyError = true;
+ const bool incorrectRelaxedLineWidth = (lineWidth > relaxedLineWidthRange.y());
+
+ if (incorrectRelaxedLineWidth)
+ errorMask |= SCANRESULT_LINE_WIDTH_ERR_BIT;
+ else
+ errorMask |= SCANRESULT_LINE_WIDTH_WARN_BIT;
+
printLineWidthError(cursor, lineWidth, lineWidthRange, advance.x() == 0, messageLimitCounter);
}
}
}
- return !anyError;
+ return errorMask;
}
void LineRenderCase::printLineWidthError (const tcu::IVec2& pos, int detectedLineWidth, const tcu::IVec2& lineWidthRange, bool isHorizontal, int& messageLimitCounter) const
--- /dev/null
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.1 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2017 The Android Open Source Project
+ *
+ * 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.
+ *
+ *//*!
+ * \file
+ * \brief Texture format tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "es31fSRGBDecodeTests.hpp"
+#include "gluContextInfo.hpp"
+#include "gluCallLogWrapper.hpp"
+#include "gluRenderContext.hpp"
+#include "gluTexture.hpp"
+#include "glsTextureTestUtil.hpp"
+#include "tcuPixelFormat.hpp"
+#include "tcuTestContext.hpp"
+#include "tcuRenderTarget.hpp"
+#include "gluTextureUtil.hpp"
+#include "tcuTextureUtil.hpp"
+#include "glwFunctions.hpp"
+#include "gluDefs.hpp"
+#include "glwEnums.hpp"
+#include "deUniquePtr.hpp"
+#include "gluPixelTransfer.hpp"
+#include "tcuDefs.hpp"
+#include "tcuVectorUtil.hpp"
+#include "gluObjectWrapper.hpp"
+#include "gluStrUtil.hpp"
+#include "tcuTestLog.hpp"
+
+namespace deqp
+{
+namespace gles31
+{
+namespace Functional
+{
+namespace
+{
+
+using glu::TextureTestUtil::TEXTURETYPE_2D;
+
+enum SRGBDecode
+{
+ SRGBDECODE_SKIP_DECODE = 0,
+ SRGBDECODE_DECODE,
+ SRGBDECODE_DECODE_DEFAULT
+};
+
+enum ShaderOutputs
+{
+ SHADEROUTPUTS_ONE = 1,
+ SHADEROUTPUTS_TWO,
+};
+
+enum ShaderUniforms
+{
+ SHADERUNIFORMS_ONE = 1,
+ SHADERUNIFORMS_TWO,
+};
+
+enum ShaderSamplingGroup
+{
+ SHADERSAMPLINGGROUP_TEXTURE = 0,
+ SHADERSAMPLINGGROUP_TEXEL_FETCH
+};
+
+enum ShaderSamplingType
+{
+ TEXTURESAMPLING_TEXTURE = 0,
+ TEXTURESAMPLING_TEXTURE_LOD,
+ TEXTURESAMPLING_TEXTURE_GRAD,
+ TEXTURESAMPLING_TEXTURE_OFFSET,
+ TEXTURESAMPLING_TEXTURE_PROJ,
+ TEXTURESAMPLING_TEXELFETCH,
+ TEXTURESAMPLING_TEXELFETCH_OFFSET,
+
+ // ranges required for looping mechanism in a case nodes iteration function
+ TEXTURESAMPLING_TEXTURE_START = TEXTURESAMPLING_TEXTURE,
+ TEXTURESAMPLING_TEXTURE_END = TEXTURESAMPLING_TEXTURE_PROJ + 1,
+ TEXTURESAMPLING_TEXELFETCH_START = TEXTURESAMPLING_TEXELFETCH,
+ TEXTURESAMPLING_TEXELFETCH_END = TEXTURESAMPLING_TEXELFETCH_OFFSET + 1
+};
+
+enum FunctionParameters
+{
+ FUNCTIONPARAMETERS_ONE = 1,
+ FUNCTIONPARAMETERS_TWO
+};
+
+enum Blending
+{
+ BLENDING_REQUIRED = 0,
+ BLENDING_NOT_REQUIRED
+};
+
+enum Toggling
+{
+ TOGGLING_REQUIRED = 0,
+ TOGGLING_NOT_REQUIRED
+};
+
+tcu::Vec4 getColorReferenceLinear (void)
+{
+ return tcu::Vec4(0.2f, 0.3f, 0.4f, 1.0f);
+}
+
+tcu::Vec4 getColorReferenceSRGB (void)
+{
+ return tcu::linearToSRGB(tcu::Vec4(0.2f, 0.3f, 0.4f, 1.0f));
+}
+
+tcu::Vec4 getColorGreenPass (void)
+{
+ return tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
+}
+
+namespace TestDimensions
+{
+ const int WIDTH = 128;
+ const int HEIGHT = 128;
+} // global test texture dimensions
+
+namespace TestSamplingPositions
+{
+ const int X_POS = 0;
+ const int Y_POS = 0;
+} // global test sampling positions
+
+const char* getFunctionDefinitionSRGBToLinearCheck (void)
+{
+ static const char* functionDefinition =
+ "mediump vec4 srgbToLinearCheck(in mediump vec4 texelSRGBA, in mediump vec4 texelLinear) \n"
+ "{ \n"
+ " const int NUM_CHANNELS = 4;"
+ " mediump vec4 texelSRGBAConverted; \n"
+ " mediump vec4 epsilonErr = vec4(0.005); \n"
+ " mediump vec4 testResult; \n"
+ " for (int idx = 0; idx < NUM_CHANNELS; idx++) \n"
+ " { \n"
+ " texelSRGBAConverted[idx] = pow( (texelSRGBA[idx] + 0.055) / 1.055, 1.0 / 0.4116); \n"
+ " } \n"
+ " if ( all(lessThan(abs(texelSRGBAConverted - texelLinear), epsilonErr)) || all(equal(texelSRGBAConverted, texelLinear)) ) \n"
+ " { \n"
+ " return testResult = vec4(0.0, 1.0, 0.0, 1.0); \n"
+ " } \n"
+ " else \n"
+ " { \n"
+ " return testResult = vec4(1.0, 0.0, 0.0, 1.0); \n"
+ " } \n"
+ "} \n";
+
+ return functionDefinition;
+}
+
+const char* getFunctionDefinitionEqualCheck (void)
+{
+ static const char* functionDefinition =
+ "mediump vec4 colorsEqualCheck(in mediump vec4 colorA, in mediump vec4 colorB) \n"
+ "{ \n"
+ " mediump vec4 epsilonErr = vec4(0.005); \n"
+ " mediump vec4 testResult; \n"
+ " if ( all(lessThan(abs(colorA - colorB), epsilonErr)) || all(equal(colorA, colorB)) ) \n"
+ " { \n"
+ " return testResult = vec4(0.0, 1.0, 0.0, 1.0); \n"
+ " } \n"
+ " else \n"
+ " { \n"
+ " return testResult = vec4(1.0, 0.0, 0.0, 1.0); \n"
+ " } \n"
+ "} \n";
+
+ return functionDefinition;
+}
+
+namespace EpsilonError
+{
+ const float CPU = 0.005f;
+}
+
+struct TestGroupConfig
+{
+ TestGroupConfig (const char* groupName, const char* groupDescription, const tcu::TextureFormat groupInternalFormat)
+ : name (groupName)
+ , description (groupDescription)
+ , internalFormat (groupInternalFormat) {}
+
+ ~TestGroupConfig (void) {};
+
+ const char* name;
+ const char* description;
+ const tcu::TextureFormat internalFormat;
+};
+
+struct UniformData
+{
+ UniformData (glw::GLuint uniformLocation, const std::string& uniformName)
+ : location (uniformLocation)
+ , name (uniformName)
+ , toggleDecode (false) {}
+
+ ~UniformData (void) {}
+
+ glw::GLuint location;
+ std::string name;
+ bool toggleDecode;
+};
+
+struct UniformToToggle
+{
+ UniformToToggle (const int uniformProgramIdx, const std::string& uniformName)
+ : programIdx (uniformProgramIdx)
+ , name (uniformName) {}
+
+ ~UniformToToggle (void) {}
+
+ int programIdx;
+ std::string name;
+};
+
+struct ComparisonFunction
+{
+ ComparisonFunction (const std::string& funcName, const FunctionParameters funcParameters, const std::string& funcImplementation)
+ : name (funcName)
+ , parameters (funcParameters)
+ , implementation (funcImplementation) {}
+
+ ~ComparisonFunction (void) {}
+
+ std::string name;
+ FunctionParameters parameters;
+ std::string implementation;
+};
+
+struct FragmentShaderParameters
+{
+ FragmentShaderParameters (const ShaderOutputs outputTotal,
+ const ShaderUniforms uniformTotal,
+ ComparisonFunction* comparisonFunction,
+ Blending blendRequired,
+ Toggling toggleRequired);
+
+ ~FragmentShaderParameters (void);
+
+ ShaderOutputs outputTotal;
+ ShaderUniforms uniformTotal;
+ ShaderSamplingType samplingType;
+ std::string functionName;
+ FunctionParameters functionParameters;
+ std::string functionImplementation;
+ bool hasFunction;
+ Blending blendRequired;
+ Toggling toggleRequired;
+ std::vector<std::string> uniformsToToggle;
+};
+
+FragmentShaderParameters::FragmentShaderParameters (const ShaderOutputs paramsOutputTotal,
+ const ShaderUniforms paramsUniformTotal,
+ ComparisonFunction* paramsComparisonFunction,
+ Blending paramsBlendRequired,
+ Toggling paramsToggleRequired)
+ : outputTotal (paramsOutputTotal)
+ , uniformTotal (paramsUniformTotal)
+ , blendRequired (paramsBlendRequired)
+ , toggleRequired (paramsToggleRequired)
+{
+ if (paramsComparisonFunction != DE_NULL)
+ {
+ functionName = paramsComparisonFunction->name;
+ functionParameters = paramsComparisonFunction->parameters;
+ functionImplementation = paramsComparisonFunction->implementation;
+
+ hasFunction = true;
+ }
+ else
+ {
+ hasFunction = false;
+ }
+}
+
+FragmentShaderParameters::~FragmentShaderParameters (void)
+{
+}
+
+class SRGBTestSampler
+{
+public:
+ SRGBTestSampler (Context& context,
+ const tcu::Sampler::WrapMode wrapS,
+ const tcu::Sampler::WrapMode wrapT,
+ const tcu::Sampler::FilterMode minFilter,
+ const tcu::Sampler::FilterMode magFilter,
+ const SRGBDecode decoding);
+ ~SRGBTestSampler (void);
+
+ void setDecode (const SRGBDecode decoding);
+ void setTextureUnit (const deUint32 textureUnit);
+ void setIsActive (const bool isActive);
+
+ deUint32 getHandle (void) const;
+ bool getIsActive (void) const;
+
+ void bindToTexture (void);
+ void unbindFromTexture (void);
+
+private:
+ const glw::Functions* m_gl;
+ deUint32 m_samplerHandle;
+ tcu::Sampler::WrapMode m_wrapS;
+ tcu::Sampler::WrapMode m_wrapT;
+ tcu::Sampler::FilterMode m_minFilter;
+ tcu::Sampler::FilterMode m_magFilter;
+ SRGBDecode m_decoding;
+ deUint32 m_textureUnit;
+ bool m_isActive;
+};
+
+SRGBTestSampler::SRGBTestSampler (Context& context,
+ const tcu::Sampler::WrapMode wrapS,
+ const tcu::Sampler::WrapMode wrapT,
+ const tcu::Sampler::FilterMode minFilter,
+ const tcu::Sampler::FilterMode magFilter,
+ const SRGBDecode decoding)
+ : m_gl (&context.getRenderContext().getFunctions())
+ , m_wrapS (wrapS)
+ , m_wrapT (wrapT)
+ , m_minFilter (minFilter)
+ , m_magFilter (magFilter)
+ , m_isActive (false)
+{
+ m_gl->genSamplers(1, &m_samplerHandle);
+
+ m_gl->samplerParameteri(m_samplerHandle, GL_TEXTURE_WRAP_S, glu::getGLWrapMode(m_wrapS));
+ m_gl->samplerParameteri(m_samplerHandle, GL_TEXTURE_WRAP_T, glu::getGLWrapMode(m_wrapT));
+ m_gl->samplerParameteri(m_samplerHandle, GL_TEXTURE_MIN_FILTER, glu::getGLFilterMode(m_minFilter));
+ m_gl->samplerParameteri(m_samplerHandle, GL_TEXTURE_MAG_FILTER, glu::getGLFilterMode(m_magFilter));
+
+ this->setDecode(decoding);
+}
+
+SRGBTestSampler::~SRGBTestSampler (void)
+{
+ m_gl->deleteSamplers(1, &m_samplerHandle);
+}
+
+void SRGBTestSampler::setDecode (const SRGBDecode decoding)
+{
+ if (decoding == SRGBDECODE_SKIP_DECODE)
+ {
+ m_gl->samplerParameteri(m_samplerHandle, GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
+ GLU_EXPECT_NO_ERROR(m_gl->getError(), "samplerParameteri(m_samplerID, GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT)");
+ }
+ else if (decoding == SRGBDECODE_DECODE)
+ {
+ m_gl->samplerParameteri(m_samplerHandle, GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT);
+ GLU_EXPECT_NO_ERROR(m_gl->getError(), "samplerParameteri(m_samplerID, GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT)");
+ }
+ else
+ {
+ DE_FATAL("sRGB texture sampler must have either GL_SKIP_DECODE_EXT or GL_DECODE_EXT settings");
+ }
+
+ m_decoding = decoding;
+}
+
+void SRGBTestSampler::setTextureUnit (const deUint32 textureUnit)
+{
+ m_textureUnit = textureUnit;
+}
+
+void SRGBTestSampler::setIsActive (const bool isActive)
+{
+ m_isActive = isActive;
+}
+
+deUint32 SRGBTestSampler::getHandle (void) const
+{
+ return m_samplerHandle;
+}
+
+bool SRGBTestSampler::getIsActive (void) const
+{
+ return m_isActive;
+}
+
+void SRGBTestSampler::bindToTexture (void)
+{
+ m_gl->bindSampler(m_textureUnit, m_samplerHandle);
+}
+
+void SRGBTestSampler::unbindFromTexture (void)
+{
+ m_gl->bindSampler(m_textureUnit, 0);
+}
+
+class SRGBTestTexture
+{
+public:
+ SRGBTestTexture (Context& context,
+ const glu::TextureTestUtil::TextureType targetType,
+ const tcu::TextureFormat internalFormat,
+ const int width,
+ const int height,
+ const tcu::Vec4 color,
+ const tcu::Sampler::WrapMode wrapS,
+ const tcu::Sampler::WrapMode wrapT,
+ const tcu::Sampler::FilterMode minFilter,
+ const tcu::Sampler::FilterMode magFilter,
+ const SRGBDecode decoding);
+ ~SRGBTestTexture (void);
+
+ void setParameters (void);
+ void setDecode (const SRGBDecode decoding);
+ void setHasSampler (const bool hasSampler);
+
+ deUint32 getHandle (void) const;
+ deUint32 getGLTargetType (void) const;
+ SRGBDecode getDecode (void) const;
+ bool getHasSampler (void) const;
+
+ void upload (void);
+
+private:
+ void setColor (void);
+
+ Context& m_context;
+ glu::Texture2D m_source;
+ glu::TextureTestUtil::TextureType m_targetType;
+ const tcu::TextureFormat m_internalFormat;
+ const int m_width;
+ const int m_height;
+ tcu::Vec4 m_color;
+ tcu::Sampler::WrapMode m_wrapS;
+ tcu::Sampler::WrapMode m_wrapT;
+ tcu::Sampler::FilterMode m_minFilter;
+ tcu::Sampler::FilterMode m_magFilter;
+ SRGBDecode m_decoding;
+ bool m_hasSampler;
+};
+
+SRGBTestTexture::SRGBTestTexture (Context& context,
+ const glu::TextureTestUtil::TextureType targetType,
+ const tcu::TextureFormat internalFormat,
+ const int width,
+ const int height,
+ const tcu::Vec4 color,
+ const tcu::Sampler::WrapMode wrapS,
+ const tcu::Sampler::WrapMode wrapT,
+ const tcu::Sampler::FilterMode minFilter,
+ const tcu::Sampler::FilterMode magFilter,
+ SRGBDecode decoding)
+ : m_context (context)
+ , m_source (context.getRenderContext(), glu::getInternalFormat(internalFormat), width, height)
+ , m_targetType (targetType)
+ , m_internalFormat (internalFormat)
+ , m_width (width)
+ , m_height (height)
+ , m_color (color)
+ , m_wrapS (wrapS)
+ , m_wrapT (wrapT)
+ , m_minFilter (minFilter)
+ , m_magFilter (magFilter)
+ , m_decoding (decoding)
+ , m_hasSampler (false)
+{
+ this->setColor();
+}
+
+SRGBTestTexture::~SRGBTestTexture (void)
+{
+}
+
+void SRGBTestTexture::setParameters (void)
+{
+ const glw::Functions& gl = m_context.getRenderContext().getFunctions();
+
+ gl.bindTexture(this->getGLTargetType(), this->getHandle());
+
+ gl.texParameteri(this->getGLTargetType(), GL_TEXTURE_WRAP_S, glu::getGLWrapMode(m_wrapS));
+ gl.texParameteri(this->getGLTargetType(), GL_TEXTURE_WRAP_T, glu::getGLWrapMode(m_wrapT));
+ gl.texParameteri(this->getGLTargetType(), GL_TEXTURE_MIN_FILTER, glu::getGLFilterMode(m_minFilter));
+ gl.texParameteri(this->getGLTargetType(), GL_TEXTURE_MAG_FILTER, glu::getGLFilterMode(m_magFilter));
+
+ gl.bindTexture(this->getGLTargetType(), 0);
+
+ setDecode(m_decoding);
+}
+
+void SRGBTestTexture::setDecode (const SRGBDecode decoding)
+{
+ const glw::Functions& gl = m_context.getRenderContext().getFunctions();
+
+ gl.bindTexture(this->getGLTargetType(), this->getHandle());
+
+ switch (decoding)
+ {
+ case SRGBDECODE_SKIP_DECODE:
+ {
+ gl.texParameteri(this->getGLTargetType(), GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
+ GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri(this->getGLTargetType(), GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT)");
+ break;
+ }
+ case SRGBDECODE_DECODE:
+ {
+ gl.texParameteri(this->getGLTargetType(), GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT);
+ GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri(this->getGLTargetType(), GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT)");
+ break;
+ }
+ case SRGBDECODE_DECODE_DEFAULT:
+ {
+ // do not use srgb decode options. Set to default
+ break;
+ }
+ default:
+ DE_FATAL("Error: Decoding option not recognised");
+ }
+
+ gl.bindTexture(this->getGLTargetType(), 0);
+
+ m_decoding = decoding;
+}
+
+void SRGBTestTexture::setHasSampler (const bool hasSampler)
+{
+ m_hasSampler = hasSampler;
+}
+
+deUint32 SRGBTestTexture::getHandle (void) const
+{
+ return m_source.getGLTexture();
+}
+
+deUint32 SRGBTestTexture::getGLTargetType (void) const
+{
+ switch (m_targetType)
+ {
+ case TEXTURETYPE_2D:
+ {
+ return GL_TEXTURE_2D;
+ }
+ default:
+ {
+ DE_FATAL("Error: Target type not recognised");
+ return -1;
+ }
+ }
+}
+
+SRGBDecode SRGBTestTexture::getDecode (void) const
+{
+ return m_decoding;
+}
+
+bool SRGBTestTexture::getHasSampler (void) const
+{
+ return m_hasSampler;
+}
+
+void SRGBTestTexture::upload (void)
+{
+ m_source.upload();
+}
+
+void SRGBTestTexture::setColor (void)
+{
+ const glw::Functions& gl = m_context.getRenderContext().getFunctions();
+
+ gl.bindTexture(this->getGLTargetType(), this->getHandle());
+
+ m_source.getRefTexture().allocLevel(0);
+
+ for (int py = 0; py < m_height; py++)
+ {
+ for (int px = 0; px < m_width; px++)
+ {
+ m_source.getRefTexture().getLevel(0).setPixel(m_color, px, py);
+ }
+ }
+
+ gl.bindTexture(this->getGLTargetType(), 0);
+}
+
+class SRGBTestProgram
+{
+public:
+ SRGBTestProgram (Context& context, const FragmentShaderParameters& shaderParameters);
+ ~SRGBTestProgram (void);
+
+ void setBlendRequired (bool blendRequired);
+ void setToggleRequired (bool toggleRequired);
+ void setUniformToggle (int location, bool toggleDecodeValue);
+
+ int getUniformTotal (void) const;
+ const std::vector<UniformData>& getUniformDataList (void) const;
+ const UniformData& getUniformAtLocation (int location) const;
+ int getUniformLocation (const std::string& name);
+ deUint32 getHandle (void) const;
+ bool getBlendRequired (void) const;
+ bool getToggleRequired (void) const;
+ const std::string& getFragmentShader (void) const;
+
+private:
+ std::string genFunctionCall (ShaderSamplingType samplingType, const int uniformIdx);
+ void genFragmentShader (void);
+
+ Context& m_context;
+ de::MovePtr<glu::ShaderProgram> m_program;
+ FragmentShaderParameters m_shaderFragmentParameters;
+ std::string m_shaderVertex;
+ std::string m_shaderFragment;
+ std::vector<UniformData> m_uniformDataList;
+ bool m_blendRequired;
+ bool m_toggleRequired;
+};
+
+SRGBTestProgram::SRGBTestProgram (Context& context, const FragmentShaderParameters& shaderParameters)
+ : m_context (context)
+ , m_shaderFragmentParameters (shaderParameters)
+ , m_blendRequired (false)
+ , m_toggleRequired (false)
+{
+ const glw::Functions& gl = m_context.getRenderContext().getFunctions();
+ tcu::TestLog& log = m_context.getTestContext().getLog();
+ glu::ShaderProgramInfo buildInfo;
+ const int totalShaderStages = 2;
+
+ // default vertex shader used in all tests
+ m_shaderVertex = "#version 310 es \n"
+ "layout (location = 0) in mediump vec3 aPosition; \n"
+ "layout (location = 1) in mediump vec2 aTexCoord; \n"
+ "out mediump vec2 vs_aTexCoord; \n"
+ "void main () \n"
+ "{ \n"
+ " gl_Position = vec4(aPosition, 1.0); \n"
+ " vs_aTexCoord = aTexCoord; \n"
+ "} \n";
+
+ this->genFragmentShader();
+
+ m_program = de::MovePtr<glu::ShaderProgram>(new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(m_shaderVertex, m_shaderFragment)));
+
+ if (!m_program->isOk())
+ {
+ TCU_FAIL("Failed to compile shaders and link program");
+ }
+
+ glw::GLint activeUniforms, maxLen;
+ glw::GLint size, location;
+ glw::GLenum type;
+
+ gl.getProgramiv(this->getHandle(), GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLen);
+ gl.getProgramiv(this->getHandle(), GL_ACTIVE_UNIFORMS, &activeUniforms);
+
+ std::vector<glw::GLchar> uniformName(static_cast<int>(maxLen));
+ for (int idx = 0; idx < activeUniforms; idx++)
+ {
+ gl.getActiveUniform(this->getHandle(), idx, maxLen, NULL, &size, &type, &uniformName[0]);
+ location = gl.getUniformLocation(this->getHandle(), &uniformName[0]);
+
+ UniformData uniformData(location, std::string(&uniformName[0], strlen(&uniformName[0])));
+ m_uniformDataList.push_back(uniformData);
+ }
+
+ // log shader program info. Only vertex and fragment shaders included
+ buildInfo.program = m_program->getProgramInfo();
+ for (int shaderIdx = 0; shaderIdx < totalShaderStages; shaderIdx++)
+ {
+ glu::ShaderInfo shaderInfo = m_program->getShaderInfo(static_cast<glu::ShaderType>(static_cast<int>(glu::SHADERTYPE_VERTEX) + static_cast<int>(shaderIdx)), 0);
+ buildInfo.shaders.push_back(shaderInfo);
+ }
+
+ log << buildInfo;
+}
+
+SRGBTestProgram::~SRGBTestProgram (void)
+{
+ m_program = de::MovePtr<glu::ShaderProgram>(DE_NULL);
+}
+
+void SRGBTestProgram::setBlendRequired (bool blendRequired)
+{
+ m_blendRequired = blendRequired;
+}
+
+void SRGBTestProgram::setToggleRequired (bool toggleRequired)
+{
+ m_toggleRequired = toggleRequired;
+}
+
+void SRGBTestProgram::setUniformToggle (int location, bool toggleDecodeValue)
+{
+ if ( (m_uniformDataList.empty() == false) && (location >= 0) && (location <= (int)m_uniformDataList.size()) )
+ {
+ m_uniformDataList[location].toggleDecode = toggleDecodeValue;
+ }
+ else
+ {
+ TCU_THROW(TestError, "Error: Uniform location not found. glGetActiveUniforms returned uniforms incorrectly ");
+ }
+}
+
+int SRGBTestProgram::getUniformTotal (void) const
+{
+ return (int)m_uniformDataList.size();
+}
+
+const std::vector<UniformData>& SRGBTestProgram::getUniformDataList (void) const
+{
+ return m_uniformDataList;
+}
+
+const UniformData& SRGBTestProgram::getUniformAtLocation (int location) const
+{
+ return m_uniformDataList[location];
+}
+
+int SRGBTestProgram::getUniformLocation (const std::string& name)
+{
+ for (std::size_t idx = 0; idx < m_uniformDataList.size(); idx++)
+ {
+ if (m_uniformDataList[idx].name == name)
+ {
+ return m_uniformDataList[idx].location;
+ }
+ }
+
+ TCU_THROW(TestError, "Error: If name correctly requested then glGetActiveUniforms() returned active uniform data incorrectly");
+ return -1;
+}
+
+glw::GLuint SRGBTestProgram::getHandle (void) const
+{
+ return m_program->getProgram();
+}
+
+bool SRGBTestProgram::getBlendRequired (void) const
+{
+ return m_blendRequired;
+}
+
+bool SRGBTestProgram::getToggleRequired (void) const
+{
+ return m_toggleRequired;
+}
+
+const std::string& SRGBTestProgram::getFragmentShader (void) const
+{
+ return m_shaderFragment;
+}
+
+std::string SRGBTestProgram::genFunctionCall (ShaderSamplingType samplingType, const int uniformIdx)
+{
+ std::ostringstream functionCall;
+
+ functionCall << " mediump vec4 texelColor" << uniformIdx << " = ";
+
+ switch (samplingType)
+ {
+ case TEXTURESAMPLING_TEXTURE:
+ {
+ functionCall << "texture(uTexture" << uniformIdx << ", vs_aTexCoord); \n";
+ break;
+ }
+ case TEXTURESAMPLING_TEXTURE_LOD:
+ {
+ functionCall << "textureLod(uTexture" << uniformIdx << ", vs_aTexCoord, 0.0); \n";
+ break;
+ }
+ case TEXTURESAMPLING_TEXTURE_GRAD:
+ {
+ functionCall << "textureGrad(uTexture" << uniformIdx << ", vs_aTexCoord, vec2(0.0, 0.0), vec2(0.0, 0.0)); \n";
+ break;
+ }
+ case TEXTURESAMPLING_TEXTURE_OFFSET:
+ {
+ functionCall << "textureOffset(uTexture" << uniformIdx << ", vs_aTexCoord, ivec2(0.0, 0.0)); \n";
+ break;
+ }
+ case TEXTURESAMPLING_TEXTURE_PROJ:
+ {
+ functionCall << "textureProj(uTexture" << uniformIdx << ", vec3(vs_aTexCoord, 1.0)); \n";
+ break;
+ }
+ case TEXTURESAMPLING_TEXELFETCH:
+ {
+ functionCall << "texelFetch(uTexture" << uniformIdx << ", ivec2(vs_aTexCoord), 0); \n";
+ break;
+ }
+ case TEXTURESAMPLING_TEXELFETCH_OFFSET:
+ {
+ functionCall << "texelFetchOffset(uTexture" << uniformIdx << ", ivec2(vs_aTexCoord), 0, ivec2(0.0, 0.0)); \n";
+ break;
+ }
+ default:
+ {
+ DE_FATAL("Error: Sampling type not recognised");
+ }
+ }
+
+ return functionCall.str();
+}
+
+void SRGBTestProgram::genFragmentShader (void)
+{
+ std::ostringstream source;
+ std::ostringstream sampleTexture;
+ std::ostringstream functionParameters;
+ std::ostringstream shaderOutputs;
+
+ // if comparison function is present resulting shader requires precisely one output
+ DE_ASSERT( !(m_shaderFragmentParameters.hasFunction && (static_cast<int>(m_shaderFragmentParameters.outputTotal) != static_cast<int>(SHADEROUTPUTS_ONE))) );
+
+ // function parameters must equal the number of uniforms i.e. textures passed into the function
+ DE_ASSERT( !(m_shaderFragmentParameters.hasFunction && (static_cast<int>(m_shaderFragmentParameters.uniformTotal) != static_cast<int>(m_shaderFragmentParameters.functionParameters))) );
+
+ // fragment shader cannot contain more outputs than the number of texture uniforms
+ DE_ASSERT( !(static_cast<int>(m_shaderFragmentParameters.outputTotal) > static_cast<int>(m_shaderFragmentParameters.uniformTotal)) ) ;
+
+ source << "#version 310 es \n"
+ << "in mediump vec2 vs_aTexCoord; \n";
+
+ for (int output = 0; output < m_shaderFragmentParameters.outputTotal; output++)
+ {
+ source << "layout (location = " << output << ") out mediump vec4 fs_aColor" << output << "; \n";
+ }
+
+ for (int uniform = 0; uniform < m_shaderFragmentParameters.uniformTotal; uniform++)
+ {
+ source << "uniform sampler2D uTexture" << uniform << "; \n";
+ }
+
+ if (m_shaderFragmentParameters.hasFunction == true)
+ {
+ source << m_shaderFragmentParameters.functionImplementation;
+ }
+
+ source << "void main () \n"
+ << "{ \n";
+
+ for (int uniformIdx = 0; uniformIdx < m_shaderFragmentParameters.uniformTotal; uniformIdx++)
+ {
+ source << this->genFunctionCall(m_shaderFragmentParameters.samplingType, uniformIdx);
+ }
+
+ if (m_shaderFragmentParameters.hasFunction == true)
+ {
+ switch ( static_cast<FunctionParameters>(m_shaderFragmentParameters.functionParameters) )
+ {
+ case FUNCTIONPARAMETERS_ONE:
+ {
+ functionParameters << "(texelColor0)";
+ break;
+ }
+ case FUNCTIONPARAMETERS_TWO:
+ {
+ functionParameters << "(texelColor0, texelColor1)";
+ break;
+ }
+ default:
+ {
+ DE_FATAL("Error: Number of comparison function parameters invalid");
+ }
+ }
+
+ shaderOutputs << " fs_aColor0 = " << m_shaderFragmentParameters.functionName << functionParameters.str() << "; \n";
+ }
+ else
+ {
+ for (int output = 0; output < m_shaderFragmentParameters.outputTotal; output++)
+ {
+ shaderOutputs << " fs_aColor" << output << " = texelColor" << output << "; \n";
+ }
+ }
+
+ source << shaderOutputs.str();
+ source << "} \n";
+
+ m_shaderFragment = source.str();
+}
+
+class SRGBTestCase : public TestCase
+{
+public:
+ SRGBTestCase (Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat);
+ ~SRGBTestCase (void);
+
+ void init (void);
+ void deinit (void);
+ virtual IterateResult iterate (void);
+
+ void setSamplingGroup (const ShaderSamplingGroup samplingGroup);
+ void setSamplingLocations (const int px, const int py);
+ void setShaderProgramBlendRequired (const int programIdx, const bool blend);
+ void setShaderProgramToggleRequired (const int programIdx, const bool toggle);
+ void setUniformToggle (const int programIdx, const std::string& uniformName, bool toggleDecode);
+
+ deUint32 getShaderProgramHandle (const int programIdx) const;
+ deUint32 getTextureHandle (const int textureIdx) const;
+
+ void addTexture (const glu::TextureTestUtil::TextureType targetType,
+ const int width,
+ const int height,
+ const tcu::Vec4 color,
+ const tcu::Sampler::WrapMode wrapS,
+ const tcu::Sampler::WrapMode wrapT,
+ const tcu::Sampler::FilterMode minFilter,
+ const tcu::Sampler::FilterMode magFilter,
+ const SRGBDecode decoding);
+ void addSampler (const tcu::Sampler::WrapMode wrapS,
+ const tcu::Sampler::WrapMode wrapT,
+ const tcu::Sampler::FilterMode minFilter,
+ const tcu::Sampler::FilterMode magFilter,
+ const SRGBDecode decoding);
+ void addShaderProgram (const FragmentShaderParameters& shaderParameters);
+
+ void genShaderPrograms (ShaderSamplingType samplingType);
+ void deleteShaderPrograms (void);
+
+ void readResultTextures (void);
+ void storeResultPixels (std::vector<tcu::Vec4>& resultPixelData);
+
+ void toggleDecode (const std::vector<UniformData>& uniformDataList);
+ void bindSamplerToTexture (const int samplerIdx, const int textureIdx, const deUint32 textureUnit);
+ void activateSampler (const int samplerIdx, const bool active);
+ void logColor (const std::string& colorLogMessage, int colorIdx, tcu::Vec4 color) const;
+ tcu::Vec4 formatReferenceColor (tcu::Vec4 referenceColor);
+
+ // render function has a default implentation. Can be overriden for special cases
+ virtual void render (void);
+
+ // following functions must be overidden to perform individual test cases
+ virtual void setupTest (void) = 0;
+ virtual bool verifyResult (void) = 0;
+
+protected:
+ de::MovePtr<glu::Framebuffer> m_framebuffer;
+ std::vector<SRGBTestTexture*> m_textureSourceList;
+ std::vector<SRGBTestSampler*> m_samplerList;
+ std::vector<glw::GLuint> m_renderBufferList;
+ const tcu::Vec4 m_epsilonError;
+ std::vector<tcu::TextureLevel> m_textureResultList;
+ int m_resultOutputTotal;
+ tcu::TextureFormat m_resultTextureFormat;
+ glw::GLuint m_vaoID;
+ glw::GLuint m_vertexDataID;
+ std::vector<FragmentShaderParameters> m_shaderParametersList;
+ std::vector<SRGBTestProgram*> m_shaderProgramList;
+ ShaderSamplingGroup m_samplingGroup;
+ int m_px;
+ int m_py;
+ const tcu::TextureFormat m_internalFormat;
+
+private:
+ void uploadTextures (void);
+ void initFrameBuffer (void);
+ void initVertexData (void);
+
+ SRGBTestCase (const SRGBTestCase&);
+ SRGBTestCase& operator= (const SRGBTestCase&);
+};
+
+SRGBTestCase::SRGBTestCase (Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
+ : TestCase (context, name, description)
+ , m_epsilonError (EpsilonError::CPU)
+ , m_resultTextureFormat (tcu::TextureFormat(tcu::TextureFormat::sRGBA, tcu::TextureFormat::UNORM_INT8))
+ , m_vaoID (0)
+ , m_vertexDataID (0)
+ , m_samplingGroup (SHADERSAMPLINGGROUP_TEXTURE)
+ , m_internalFormat (internalFormat)
+{
+}
+
+SRGBTestCase::~SRGBTestCase (void)
+{
+ deinit();
+}
+
+void SRGBTestCase::init (void)
+{
+ // extension requirements for test
+ if ( (glu::getInternalFormat(m_internalFormat) == GL_SRGB8_ALPHA8) && !m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_sRGB_decode") )
+ {
+ throw tcu::NotSupportedError("Test requires GL_EXT_texture_sRGB_decode extension");
+ }
+
+ if ( (glu::getInternalFormat(m_internalFormat) == GL_SR8_EXT) && !(m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_sRGB_R8")) )
+ {
+ throw tcu::NotSupportedError("Test requires GL_EXT_texture_sRGB_R8 extension");
+ }
+
+ m_framebuffer = de::MovePtr<glu::Framebuffer>(new glu::Framebuffer(m_context.getRenderContext()));
+}
+
+void SRGBTestCase::deinit (void)
+{
+ const glw::Functions& gl = m_context.getRenderContext().getFunctions();
+
+ m_framebuffer = de::MovePtr<glu::Framebuffer>(DE_NULL);
+
+ for (std::size_t renderBufferIdx = 0; renderBufferIdx < m_renderBufferList.size(); renderBufferIdx++)
+ {
+ gl.deleteRenderbuffers(1, &m_renderBufferList[renderBufferIdx]);
+ }
+ m_renderBufferList.clear();
+
+ for (std::size_t textureSourceIdx = 0; textureSourceIdx < m_textureSourceList.size(); textureSourceIdx++)
+ {
+ delete m_textureSourceList[textureSourceIdx];
+ }
+ m_textureSourceList.clear();
+
+ for (std::size_t samplerIdx = 0; samplerIdx < m_samplerList.size(); samplerIdx++)
+ {
+ delete m_samplerList[samplerIdx];
+ }
+ m_samplerList.clear();
+
+ if (m_vaoID != 0)
+ {
+ gl.deleteVertexArrays(1, &m_vaoID);
+ m_vaoID = 0;
+ }
+
+ if (m_vertexDataID != 0)
+ {
+ gl.deleteBuffers(1, &m_vertexDataID);
+ m_vertexDataID = 0;
+ }
+}
+
+SRGBTestCase::IterateResult SRGBTestCase::iterate (void)
+{
+ bool result;
+ int startIdx = -1;
+ int endIdx = -1;
+
+ this->setupTest();
+
+ if (m_samplingGroup == SHADERSAMPLINGGROUP_TEXTURE)
+ {
+ startIdx = static_cast<int>(TEXTURESAMPLING_TEXTURE_START);
+ endIdx = static_cast<int>(TEXTURESAMPLING_TEXTURE_END);
+ }
+ else if (m_samplingGroup == SHADERSAMPLINGGROUP_TEXEL_FETCH)
+ {
+ startIdx = static_cast<int>(TEXTURESAMPLING_TEXELFETCH_START);
+ endIdx = static_cast<int>(TEXTURESAMPLING_TEXELFETCH_END);
+ }
+ else
+ {
+ DE_FATAL("Error: Sampling group not defined");
+ }
+
+ this->initVertexData();
+ this->initFrameBuffer();
+
+ // loop through all sampling types in the required sampling group, performing individual tests for each
+ for (int samplingTypeIdx = startIdx; samplingTypeIdx < endIdx; samplingTypeIdx++)
+ {
+ this->genShaderPrograms(static_cast<ShaderSamplingType>(samplingTypeIdx));
+ this->uploadTextures();
+ this->render();
+
+ result = this->verifyResult();
+
+ this->deleteShaderPrograms();
+
+ if (result == true)
+ {
+ m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+ }
+ else
+ {
+ m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result verification failed");
+ return STOP;
+ }
+ }
+
+ return STOP;
+}
+
+void SRGBTestCase::setSamplingGroup (const ShaderSamplingGroup samplingGroup)
+{
+ m_samplingGroup = samplingGroup;
+}
+
+void SRGBTestCase::setSamplingLocations (const int px, const int py)
+{
+ m_px = px;
+ m_py = py;
+}
+
+void SRGBTestCase::setShaderProgramBlendRequired (const int programIdx, const bool blend)
+{
+ m_shaderProgramList[programIdx]->setBlendRequired(blend);
+}
+
+void SRGBTestCase::setShaderProgramToggleRequired (const int programIdx, const bool toggle)
+{
+ m_shaderProgramList[programIdx]->setToggleRequired(toggle);
+}
+
+void SRGBTestCase::setUniformToggle (const int programIdx, const std::string& uniformName, bool toggleDecodeValue)
+{
+ int uniformLocation = m_shaderProgramList[programIdx]->getUniformLocation(uniformName);
+ m_shaderProgramList[programIdx]->setUniformToggle(uniformLocation, toggleDecodeValue);
+}
+
+deUint32 SRGBTestCase::getShaderProgramHandle (const int programIdx) const
+{
+ return m_shaderProgramList[programIdx]->getHandle();
+}
+
+deUint32 SRGBTestCase::getTextureHandle (const int textureIdx) const
+{
+ return m_textureSourceList[textureIdx]->getHandle();
+}
+
+void SRGBTestCase::addTexture ( const glu::TextureTestUtil::TextureType targetType,
+ const int width,
+ const int height,
+ const tcu::Vec4 color,
+ const tcu::Sampler::WrapMode wrapS,
+ const tcu::Sampler::WrapMode wrapT,
+ const tcu::Sampler::FilterMode minFilter,
+ const tcu::Sampler::FilterMode magFilter,
+ const SRGBDecode decoding)
+{
+ SRGBTestTexture* texture = new SRGBTestTexture(m_context, targetType, m_internalFormat, width, height, color, wrapS, wrapT, minFilter, magFilter, decoding);
+ m_textureSourceList.push_back(texture);
+}
+
+void SRGBTestCase::addSampler ( const tcu::Sampler::WrapMode wrapS,
+ const tcu::Sampler::WrapMode wrapT,
+ const tcu::Sampler::FilterMode minFilter,
+ const tcu::Sampler::FilterMode magFilter,
+ const SRGBDecode decoding)
+{
+ SRGBTestSampler *sampler = new SRGBTestSampler(m_context, wrapS, wrapT, minFilter, magFilter, decoding);
+ m_samplerList.push_back(sampler);
+}
+
+void SRGBTestCase::addShaderProgram (const FragmentShaderParameters& shaderParameters)
+{
+ m_shaderParametersList.push_back(shaderParameters);
+ m_resultOutputTotal = shaderParameters.outputTotal;
+}
+
+void SRGBTestCase::genShaderPrograms (ShaderSamplingType samplingType)
+{
+ for (int shaderParamsIdx = 0; shaderParamsIdx < (int)m_shaderParametersList.size(); shaderParamsIdx++)
+ {
+ m_shaderParametersList[shaderParamsIdx].samplingType = samplingType;
+ SRGBTestProgram* shaderProgram = new SRGBTestProgram(m_context, m_shaderParametersList[shaderParamsIdx]);
+
+ if (m_shaderParametersList[shaderParamsIdx].blendRequired == BLENDING_REQUIRED)
+ {
+ shaderProgram->setBlendRequired(true);
+ }
+
+ if (m_shaderParametersList[shaderParamsIdx].toggleRequired == TOGGLING_REQUIRED)
+ {
+ shaderProgram->setToggleRequired(true);
+ std::vector<std::string> uniformsToToggle = m_shaderParametersList[shaderParamsIdx].uniformsToToggle;
+
+ for (int uniformNameIdx = 0; uniformNameIdx < (int)uniformsToToggle.size(); uniformNameIdx++)
+ {
+ shaderProgram->setUniformToggle(shaderProgram->getUniformLocation(uniformsToToggle[uniformNameIdx]), true);
+ }
+ }
+
+ m_shaderProgramList.push_back(shaderProgram);
+ }
+}
+
+void SRGBTestCase::deleteShaderPrograms (void)
+{
+ for (std::size_t idx = 0; idx < m_shaderProgramList.size(); idx++)
+ {
+ delete m_shaderProgramList[idx];
+ }
+ m_shaderProgramList.clear();
+}
+
+void SRGBTestCase::readResultTextures (void)
+{
+ const glw::Functions& gl = m_context.getRenderContext().getFunctions();
+ int width = m_context.getRenderContext().getRenderTarget().getWidth();
+ int height = m_context.getRenderContext().getRenderTarget().getHeight();
+
+ gl.bindFramebuffer(GL_FRAMEBUFFER, **m_framebuffer);
+
+ m_textureResultList.resize(m_renderBufferList.size());
+
+ for (std::size_t renderBufferIdx = 0; renderBufferIdx < m_renderBufferList.size(); renderBufferIdx++)
+ {
+ gl.readBuffer(GL_COLOR_ATTACHMENT0 + (glw::GLenum)renderBufferIdx);
+ m_textureResultList[renderBufferIdx].setStorage(m_resultTextureFormat, width, height);
+ glu::readPixels(m_context.getRenderContext(), 0, 0, m_textureResultList[renderBufferIdx].getAccess());
+ GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels()");
+ }
+
+ gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
+}
+
+void SRGBTestCase::storeResultPixels (std::vector<tcu::Vec4>& resultPixelData)
+{
+ tcu::TestLog& log = m_context.getTestContext().getLog();
+ std::ostringstream message;
+ int width = m_context.getRenderContext().getRenderTarget().getWidth();
+ int height = m_context.getRenderContext().getRenderTarget().getHeight();
+
+ // ensure result sampling coordinates are within range of the result color attachment
+ DE_ASSERT((m_px >= 0) && (m_px < width));
+ DE_ASSERT((m_py >= 0) && (m_py < height));
+ DE_UNREF(width && height);
+
+ for (int idx = 0; idx < (int)m_textureResultList.size(); idx++)
+ {
+ resultPixelData.push_back(m_textureResultList[idx].getAccess().getPixel(m_px, m_py));
+ this->logColor(std::string("Result color: "), idx, resultPixelData[idx]);
+ }
+
+ // log error rate (threshold)
+ message << m_epsilonError;
+ log << tcu::TestLog::Message << std::string("Epsilon error: ") << message.str() << tcu::TestLog::EndMessage;
+}
+
+void SRGBTestCase::toggleDecode (const std::vector<UniformData>& uniformDataList)
+{
+ DE_ASSERT( uniformDataList.size() <= m_textureSourceList.size() );
+
+ for (int uniformIdx = 0; uniformIdx < (int)uniformDataList.size(); uniformIdx++)
+ {
+ if (uniformDataList[uniformIdx].toggleDecode == true)
+ {
+ if (m_textureSourceList[uniformIdx]->getDecode() == SRGBDECODE_DECODE_DEFAULT)
+ {
+ // cannot toggle default
+ continue;
+ }
+
+ // toggle sRGB decode values (ignoring value if set to default)
+ m_textureSourceList[uniformIdx]->setDecode((SRGBDecode)((m_textureSourceList[uniformIdx]->getDecode() + 1) % SRGBDECODE_DECODE_DEFAULT));
+ }
+ }
+}
+
+void SRGBTestCase::bindSamplerToTexture (const int samplerIdx, const int textureIdx, const deUint32 textureUnit)
+{
+ deUint32 enumConversion = textureUnit - GL_TEXTURE0;
+ m_textureSourceList[textureIdx]->setHasSampler(true);
+ m_samplerList[samplerIdx]->setTextureUnit(enumConversion);
+}
+
+void SRGBTestCase::activateSampler (const int samplerIdx, const bool active)
+{
+ m_samplerList[samplerIdx]->setIsActive(active);
+}
+
+void SRGBTestCase::logColor (const std::string& colorLogMessage, int colorIdx, tcu::Vec4 color) const
+{
+ tcu::TestLog& log = m_context.getTestContext().getLog();
+ std::ostringstream message;
+
+ message << colorLogMessage << colorIdx << " = (" << color.x() << ", " << color.y() << ", " << color.z() << ", " << color.w() << ")";
+ log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
+}
+
+tcu::Vec4 SRGBTestCase::formatReferenceColor (tcu::Vec4 referenceColor)
+{
+ switch (glu::getInternalFormat(m_internalFormat))
+ {
+ case GL_SRGB8_ALPHA8:
+ {
+ return referenceColor;
+ }
+ case GL_SR8_EXT:
+ {
+ // zero unwanted color channels
+ referenceColor.y() = 0;
+ referenceColor.z() = 0;
+ return referenceColor;
+ }
+ default:
+ {
+ DE_FATAL("Error: Internal format not recognised");
+ return referenceColor;
+ }
+ }
+}
+
+void SRGBTestCase::render (void)
+{
+ const glw::Functions& gl = m_context.getRenderContext().getFunctions();
+
+ // default rendering only uses one program
+ gl.bindFramebuffer(GL_FRAMEBUFFER, **m_framebuffer);
+ gl.bindVertexArray(m_vaoID);
+
+ gl.useProgram(m_shaderProgramList[0]->getHandle());
+
+ for (int textureSourceIdx = 0; textureSourceIdx < (int)m_textureSourceList.size(); textureSourceIdx++)
+ {
+ gl.activeTexture(GL_TEXTURE0 + (glw::GLenum)textureSourceIdx);
+ gl.bindTexture(m_textureSourceList[textureSourceIdx]->getGLTargetType(), m_textureSourceList[textureSourceIdx]->getHandle());
+ glw::GLuint samplerUniformLocationID = gl.getUniformLocation(m_shaderProgramList[0]->getHandle(), m_shaderProgramList[0]->getUniformAtLocation(textureSourceIdx).name.c_str());
+ TCU_CHECK(samplerUniformLocationID != (glw::GLuint)-1);
+ gl.uniform1i(samplerUniformLocationID, (glw::GLenum)textureSourceIdx);
+ }
+
+ for (int samplerIdx = 0; samplerIdx < (int)m_samplerList.size(); samplerIdx++)
+ {
+ if (m_samplerList[samplerIdx]->getIsActive() == true)
+ {
+ m_samplerList[samplerIdx]->bindToTexture();
+ }
+ }
+
+ gl.drawArrays(GL_TRIANGLES, 0, 6);
+
+ for (std::size_t textureSourceIdx = 0; textureSourceIdx < m_textureSourceList.size(); textureSourceIdx++)
+ {
+ gl.bindTexture(m_textureSourceList[textureSourceIdx]->getGLTargetType(), 0);
+ }
+ gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
+ gl.bindVertexArray(0);
+ gl.bindBuffer(GL_ARRAY_BUFFER, 0);
+}
+
+void SRGBTestCase::uploadTextures (void)
+{
+ for (std::size_t idx = 0; idx < m_textureSourceList.size(); idx++)
+ {
+ m_textureSourceList[idx]->upload();
+ m_textureSourceList[idx]->setParameters();
+ }
+}
+
+void SRGBTestCase::initFrameBuffer (void)
+{
+ const glw::Functions& gl = m_context.getRenderContext().getFunctions();
+ int width = m_context.getRenderContext().getRenderTarget().getWidth();
+ int height = m_context.getRenderContext().getRenderTarget().getHeight();
+
+ if (m_resultOutputTotal == 0)
+ {
+ throw std::invalid_argument("SRGBTestExecutor must have at least 1 rendered result");
+ }
+
+ gl.bindFramebuffer(GL_FRAMEBUFFER, **m_framebuffer);
+
+ DE_ASSERT(m_renderBufferList.empty());
+ for (int outputIdx = 0; outputIdx < m_resultOutputTotal; outputIdx++)
+ {
+ glw::GLuint renderBuffer = -1;
+ m_renderBufferList.push_back(renderBuffer);
+ }
+
+ for (std::size_t renderBufferIdx = 0; renderBufferIdx < m_renderBufferList.size(); renderBufferIdx++)
+ {
+ gl.genRenderbuffers(1, &m_renderBufferList[renderBufferIdx]);
+ gl.bindRenderbuffer(GL_RENDERBUFFER, m_renderBufferList[renderBufferIdx]);
+ gl.renderbufferStorage(GL_RENDERBUFFER, glu::getInternalFormat(m_resultTextureFormat), width, height);
+ gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + (glw::GLenum)renderBufferIdx, GL_RENDERBUFFER, m_renderBufferList[renderBufferIdx]);
+ GLU_EXPECT_NO_ERROR(gl.getError(), "Create and setup renderbuffer object");
+ }
+ TCU_CHECK(gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
+
+ std::vector<glw::GLenum> renderBufferTargets(m_renderBufferList.size());
+ for (std::size_t renderBufferIdx = 0; renderBufferIdx < m_renderBufferList.size(); renderBufferIdx++)
+ {
+ renderBufferTargets[renderBufferIdx] = GL_COLOR_ATTACHMENT0 + (glw::GLenum)renderBufferIdx;
+ }
+ gl.drawBuffers((glw::GLsizei)renderBufferTargets.size(), &renderBufferTargets[0]);
+ GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawBuffer()");
+
+ gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
+}
+
+void SRGBTestCase::initVertexData (void)
+{
+ const glw::Functions& gl = m_context.getRenderContext().getFunctions();
+
+ static const glw::GLfloat squareVertexData[] =
+ {
+ // position // texcoord
+ -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, // bottom left corner
+ 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom right corner
+ 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // Top right corner
+
+ -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // top left corner
+ 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // Top right corner
+ -1.0f, -1.0f, 0.0f, 0.0f, 0.0f // bottom left corner
+ };
+
+ DE_ASSERT(m_vaoID == 0);
+ gl.genVertexArrays(1, &m_vaoID);
+ gl.bindVertexArray(m_vaoID);
+
+ gl.genBuffers(1, &m_vertexDataID);
+ gl.bindBuffer(GL_ARRAY_BUFFER, m_vertexDataID);
+ gl.bufferData(GL_ARRAY_BUFFER, (glw::GLsizei)sizeof(squareVertexData), squareVertexData, GL_STATIC_DRAW);
+
+ gl.vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * (glw::GLsizei)sizeof(GL_FLOAT), (glw::GLvoid *)0);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * (glw::GLsizei)sizeof(GL_FLOAT), (glw::GLvoid *)(3 * sizeof(GL_FLOAT)));
+ gl.enableVertexAttribArray(1);
+
+ gl.bindVertexArray(0);
+ gl.bindBuffer(GL_ARRAY_BUFFER, 0);
+}
+
+class TextureDecodeSkippedCase : public SRGBTestCase
+{
+public:
+ TextureDecodeSkippedCase (Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
+ : SRGBTestCase (context, name, description, internalFormat) {}
+
+ ~TextureDecodeSkippedCase (void) {}
+
+ void setupTest (void);
+ bool verifyResult (void);
+};
+
+void TextureDecodeSkippedCase::setupTest (void)
+{
+ // TEST STEPS:
+ // - create and set texture to DECODE_SKIP_EXT
+ // - store texture on GPU
+ // - in fragment shader, sample the texture using texture*() and render texel values to a color attachment in the FBO
+ // - on the host, read back the pixel values into a tcu::TextureLevel
+ // - analyse the texel values, expecting them in sRGB format i.e. linear space decoding was skipped
+
+ FragmentShaderParameters shaderParameters(SHADEROUTPUTS_ONE, SHADERUNIFORMS_ONE, NULL, BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);
+
+ this->addTexture( TEXTURETYPE_2D,
+ TestDimensions::WIDTH,
+ TestDimensions::HEIGHT,
+ getColorReferenceLinear(),
+ tcu::Sampler::MIRRORED_REPEAT_GL,
+ tcu::Sampler::MIRRORED_REPEAT_GL,
+ tcu::Sampler::LINEAR,
+ tcu::Sampler::LINEAR,
+ SRGBDECODE_SKIP_DECODE);
+
+ this->addShaderProgram(shaderParameters);
+ this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);
+
+ this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXTURE);
+}
+
+bool TextureDecodeSkippedCase::verifyResult (void)
+{
+ tcu::TestLog& log = m_context.getTestContext().getLog();
+ const int resultColorIdx = 0;
+ std::vector<tcu::Vec4> pixelResultList;
+ tcu::Vec4 pixelConverted;
+ tcu::Vec4 pixelReference;
+ tcu::Vec4 pixelExpected;
+
+ this->readResultTextures();
+ this->storeResultPixels(pixelResultList);
+
+ pixelConverted = tcu::sRGBToLinear(pixelResultList[resultColorIdx]);
+ pixelReference = this->formatReferenceColor(getColorReferenceLinear());
+ pixelExpected = this->formatReferenceColor(getColorReferenceSRGB());
+
+ this->formatReferenceColor(pixelReference);
+ this->logColor(std::string("Expected color: "), resultColorIdx, pixelExpected);
+
+ // result color 0 should be sRGB. Compare with linear reference color
+ if ( (tcu::boolAll(tcu::lessThan(tcu::abs(pixelConverted - pixelReference), m_epsilonError))) || (tcu::boolAll(tcu::equal(pixelConverted, pixelReference))) )
+ {
+ log << tcu::TestLog::Message << std::string("sRGB as expected") << tcu::TestLog::EndMessage;
+ return true;
+ }
+ else
+ {
+ log << tcu::TestLog::Message << std::string("not sRGB as expected") << tcu::TestLog::EndMessage;
+ return false;
+ }
+}
+
+class TextureDecodeEnabledCase : public SRGBTestCase
+{
+public:
+ TextureDecodeEnabledCase (Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
+ : SRGBTestCase (context, name, description, internalFormat) {}
+
+ ~TextureDecodeEnabledCase (void) {}
+
+ void setupTest (void);
+ bool verifyResult (void);
+};
+
+void TextureDecodeEnabledCase::setupTest (void)
+{
+ // TEST STEPS:
+ // - create and set texture to DECODE_EXT
+ // - store texture on GPU
+ // - in fragment shader, sample the texture using texture*() and render texel values to a color attachment in the FBO
+ // - on the host, read back the pixel values into a tcu::TextureLevel
+ // - analyse the texel values, expecting them in lRGB format i.e. linear space decoding was enabled
+
+ FragmentShaderParameters shaderParameters(SHADEROUTPUTS_ONE, SHADERUNIFORMS_ONE, NULL, BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);
+
+ this->addTexture( TEXTURETYPE_2D,
+ TestDimensions::WIDTH,
+ TestDimensions::HEIGHT,
+ getColorReferenceLinear(),
+ tcu::Sampler::MIRRORED_REPEAT_GL,
+ tcu::Sampler::MIRRORED_REPEAT_GL,
+ tcu::Sampler::LINEAR,
+ tcu::Sampler::LINEAR,
+ SRGBDECODE_DECODE);
+
+ this->addShaderProgram(shaderParameters);
+
+ this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);
+
+ this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXTURE);
+}
+
+bool TextureDecodeEnabledCase::verifyResult (void)
+{
+ tcu::TestLog& log = m_context.getTestContext().getLog();
+ const int resultColorIdx = 0;
+ std::vector<tcu::Vec4> pixelResultList;
+ tcu::Vec4 pixelConverted;
+ tcu::Vec4 pixelReference;
+ tcu::Vec4 pixelExpected;
+
+ this->readResultTextures();
+ this->storeResultPixels(pixelResultList);
+
+ pixelConverted = tcu::linearToSRGB(pixelResultList[resultColorIdx]);
+ pixelReference = this->formatReferenceColor(getColorReferenceSRGB());
+ pixelExpected = this->formatReferenceColor(getColorReferenceLinear());
+
+ this->logColor(std::string("Expected color: "), resultColorIdx, pixelExpected);
+
+ // result color 0 should be SRGB. Compare with sRGB reference color
+ if ( (tcu::boolAll(tcu::lessThan(tcu::abs(pixelConverted - pixelReference), m_epsilonError))) || (tcu::boolAll(tcu::equal(pixelConverted, pixelReference))) )
+ {
+ log << tcu::TestLog::Message << std::string("linear as expected") << tcu::TestLog::EndMessage;
+ return true;
+ }
+ else
+ {
+ log << tcu::TestLog::Message << std::string("not linear as expected") << tcu::TestLog::EndMessage;
+ return false;
+ }
+}
+
+class TexelFetchDecodeSkippedcase : public SRGBTestCase
+{
+public:
+ TexelFetchDecodeSkippedcase (Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
+ : SRGBTestCase (context, name, description, internalFormat) {}
+
+ ~TexelFetchDecodeSkippedcase (void) {}
+
+ void setupTest (void);
+ bool verifyResult (void);
+};
+
+void TexelFetchDecodeSkippedcase::setupTest (void)
+{
+ // TEST STEPS:
+ // - create and set texture to DECODE_SKIP_EXT
+ // - store texture on GPU
+ // - in fragment shader, sample the texture using texelFetch*() and render texel values to a color attachment in the FBO
+ // - on the host, read back the pixel values into a tcu::TextureLevel
+ // - analyse the texel values, expecting them in lRGB format i.e. linear space decoding is always enabled with texelFetch*()
+
+ FragmentShaderParameters shaderParameters(SHADEROUTPUTS_ONE, SHADERUNIFORMS_ONE, NULL, BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);
+
+ this->addTexture( TEXTURETYPE_2D,
+ TestDimensions::WIDTH,
+ TestDimensions::HEIGHT,
+ getColorReferenceLinear(),
+ tcu::Sampler::MIRRORED_REPEAT_GL,
+ tcu::Sampler::MIRRORED_REPEAT_GL,
+ tcu::Sampler::LINEAR,
+ tcu::Sampler::LINEAR,
+ SRGBDECODE_SKIP_DECODE);
+
+ this->addShaderProgram(shaderParameters);
+
+ this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);
+
+ this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXEL_FETCH);
+}
+
+bool TexelFetchDecodeSkippedcase::verifyResult (void)
+{
+ tcu::TestLog& log = m_context.getTestContext().getLog();
+ const int resultColorIdx = 0;
+ std::vector<tcu::Vec4> pixelResultList;
+ tcu::Vec4 pixelReference;
+ tcu::Vec4 pixelExpected;
+
+ this->readResultTextures();
+ this->storeResultPixels(pixelResultList);
+
+ pixelReference = pixelExpected = this->formatReferenceColor(getColorReferenceLinear());
+
+ this->logColor(std::string("Expected color: "), resultColorIdx, pixelExpected);
+
+ // result color 0 should be linear due to automatic conversion via texelFetch*(). Compare with linear reference color
+ if ( (tcu::boolAll(tcu::lessThan(tcu::abs(pixelResultList[0] - pixelReference), m_epsilonError))) || (tcu::boolAll(tcu::equal(pixelResultList[0], pixelReference))) )
+ {
+ log << tcu::TestLog::Message << std::string("linear as expected") << tcu::TestLog::EndMessage;
+ return true;
+ }
+ else
+ {
+ log << tcu::TestLog::Message << std::string("not linear as expected") << tcu::TestLog::EndMessage;
+ return false;
+ }
+}
+
+class GPUConversionDecodeEnabledCase : public SRGBTestCase
+{
+public:
+ GPUConversionDecodeEnabledCase (Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
+ : SRGBTestCase (context, name, description, internalFormat) {}
+
+ ~GPUConversionDecodeEnabledCase (void) {}
+
+ void setupTest (void);
+ bool verifyResult (void);
+};
+
+void GPUConversionDecodeEnabledCase::setupTest (void)
+{
+ // TEST STEPS:
+ // - create and set texture_a to DECODE_SKIP_EXT and texture_b to default
+ // - store textures on GPU
+ // - in fragment shader, sample both textures using texture*() and manually perform sRGB to lRGB conversion on texture_b
+ // - in fragment shader, compare converted texture_b with texture_a
+ // - render green image for pass or red for fail
+
+ ComparisonFunction comparisonFunction("srgbToLinearCheck", FUNCTIONPARAMETERS_TWO, getFunctionDefinitionSRGBToLinearCheck());
+
+ FragmentShaderParameters shaderParameters(SHADEROUTPUTS_ONE, SHADERUNIFORMS_TWO, &comparisonFunction, BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);
+
+ this->addTexture( TEXTURETYPE_2D,
+ TestDimensions::WIDTH,
+ TestDimensions::HEIGHT,
+ getColorReferenceLinear(),
+ tcu::Sampler::MIRRORED_REPEAT_GL,
+ tcu::Sampler::MIRRORED_REPEAT_GL,
+ tcu::Sampler::LINEAR,
+ tcu::Sampler::LINEAR,
+ SRGBDECODE_SKIP_DECODE);
+
+ this->addTexture( TEXTURETYPE_2D,
+ TestDimensions::WIDTH,
+ TestDimensions::HEIGHT,
+ getColorReferenceLinear(),
+ tcu::Sampler::MIRRORED_REPEAT_GL,
+ tcu::Sampler::MIRRORED_REPEAT_GL,
+ tcu::Sampler::LINEAR,
+ tcu::Sampler::LINEAR,
+ SRGBDECODE_DECODE_DEFAULT);
+
+ this->addShaderProgram(shaderParameters);
+
+ this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);
+
+ this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXTURE);
+}
+
+bool GPUConversionDecodeEnabledCase::verifyResult (void)
+{
+ tcu::TestLog& log = m_context.getTestContext().getLog();
+ const int resultColorIdx = 0;
+ std::vector<tcu::Vec4> pixelResultList;
+
+ this->readResultTextures();
+ this->storeResultPixels(pixelResultList);
+ this->logColor(std::string("Expected color: "), resultColorIdx, getColorGreenPass());
+
+ // result color returned from GPU is either green (pass) or fail (red)
+ if ( tcu::boolAll(tcu::equal(pixelResultList[resultColorIdx], getColorGreenPass())) )
+ {
+ log << tcu::TestLog::Message << std::string("returned pass color from GPU") << tcu::TestLog::EndMessage;
+ return true;
+ }
+ else
+ {
+ log << tcu::TestLog::Message << std::string("returned fail color from GPU") << tcu::TestLog::EndMessage;
+ return false;
+ }
+}
+
+class DecodeToggledCase : public SRGBTestCase
+{
+public:
+ DecodeToggledCase (Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
+ : SRGBTestCase (context, name, description, internalFormat) {}
+
+ ~DecodeToggledCase (void) {}
+
+ void render (void);
+ void setupTest (void);
+ bool verifyResult (void);
+};
+
+void DecodeToggledCase::render (void)
+{
+ // override the base SRGBTestCase render function with the purpose of switching between shader programs,
+ // toggling texture sRGB decode state between draw calls
+ const glw::Functions& gl = m_context.getRenderContext().getFunctions();
+
+ gl.bindFramebuffer(GL_FRAMEBUFFER, **m_framebuffer);
+ gl.bindVertexArray(m_vaoID);
+
+ for (std::size_t programIdx = 0; programIdx < m_shaderProgramList.size(); programIdx++)
+ {
+ gl.useProgram(m_shaderProgramList[programIdx]->getHandle());
+
+ this->toggleDecode(m_shaderProgramList[programIdx]->getUniformDataList());
+
+ for (int textureSourceIdx = 0; textureSourceIdx < (int)m_textureSourceList.size(); textureSourceIdx++)
+ {
+ gl.activeTexture(GL_TEXTURE0 + (glw::GLenum)textureSourceIdx);
+ gl.bindTexture(m_textureSourceList[textureSourceIdx]->getGLTargetType(), m_textureSourceList[textureSourceIdx]->getHandle());
+ glw::GLuint samplerUniformLocationID = gl.getUniformLocation(m_shaderProgramList[programIdx]->getHandle(), m_shaderProgramList[programIdx]->getUniformAtLocation(textureSourceIdx).name.c_str());
+ TCU_CHECK(samplerUniformLocationID != (glw::GLuint) - 1);
+ gl.uniform1i(samplerUniformLocationID, (glw::GLenum)textureSourceIdx);
+ }
+
+ for (int samplerIdx = 0; samplerIdx < (int)m_samplerList.size(); samplerIdx++)
+ {
+ if (m_samplerList[samplerIdx]->getIsActive() == true)
+ {
+ m_samplerList[samplerIdx]->bindToTexture();
+ }
+ }
+
+ if (m_shaderProgramList[programIdx]->getBlendRequired() == true)
+ {
+ gl.enable(GL_BLEND);
+ gl.blendEquation(GL_MAX);
+ gl.blendFunc(GL_ONE, GL_ONE);
+ }
+ else
+ {
+ gl.disable(GL_BLEND);
+ }
+
+ gl.drawArrays(GL_TRIANGLES, 0, 6);
+
+ // reset sRGB decode state on textures
+ this->toggleDecode(m_shaderProgramList[programIdx]->getUniformDataList());
+ }
+
+ for (std::size_t textureSourceIdx = 0; textureSourceIdx < m_textureSourceList.size(); textureSourceIdx++)
+ {
+ gl.bindTexture(m_textureSourceList[textureSourceIdx]->getGLTargetType(), 0);
+ }
+ gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
+ gl.bindVertexArray(0);
+ gl.bindBuffer(GL_ARRAY_BUFFER, 0);
+}
+
+void DecodeToggledCase::setupTest (void)
+{
+ // TEST STEPS:
+ // - create and set texture_a to DECODE_SKIP_EXT and texture_b to DECODE_EXT
+ // - create and use two seperate shader programs, program_a and program_b, each using different fragment shaders
+ // - store texture_a and texture_b on GPU
+ // FIRST PASS:
+ // - use program_a
+ // - in fragment shader, sample both textures using texture*() and manually perform sRGB to lRGB conversion on texture_a
+ // - in fragment shader, test converted texture_a value with texture_b
+ // - render green image for pass or red for fail
+ // - store result in a color attachement 0
+ // TOGGLE STAGE
+ // - during rendering, toggle texture_a from DECODE_SKIP_EXT to DECODE_EXT
+ // SECOND PASS:
+ // - use program_b
+ // - in fragment shader, sample both textures using texture*() and manually perform equality check. Both should be linear
+ // - blend first pass result with second pass. Anything but a green result equals fail
+
+ ComparisonFunction srgbToLinearFunction("srgbToLinearCheck", FUNCTIONPARAMETERS_TWO, getFunctionDefinitionSRGBToLinearCheck());
+ ComparisonFunction colorsEqualFunction("colorsEqualCheck", FUNCTIONPARAMETERS_TWO, getFunctionDefinitionEqualCheck());
+
+ FragmentShaderParameters shaderParametersA(SHADEROUTPUTS_ONE, SHADERUNIFORMS_TWO, &srgbToLinearFunction, BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);
+ FragmentShaderParameters shaderParametersB(SHADEROUTPUTS_ONE, SHADERUNIFORMS_TWO, &colorsEqualFunction, BLENDING_REQUIRED, TOGGLING_REQUIRED);
+
+ // need to specify which texture uniform to toggle DECODE_EXT/SKIP_DECODE_EXT
+ shaderParametersB.uniformsToToggle.push_back("uTexture0");
+
+ this->addTexture( TEXTURETYPE_2D,
+ TestDimensions::WIDTH,
+ TestDimensions::HEIGHT,
+ getColorReferenceLinear(),
+ tcu::Sampler::MIRRORED_REPEAT_GL,
+ tcu::Sampler::MIRRORED_REPEAT_GL,
+ tcu::Sampler::LINEAR,
+ tcu::Sampler::LINEAR,
+ SRGBDECODE_SKIP_DECODE);
+
+ this->addTexture( TEXTURETYPE_2D,
+ TestDimensions::WIDTH,
+ TestDimensions::HEIGHT,
+ getColorReferenceLinear(),
+ tcu::Sampler::MIRRORED_REPEAT_GL,
+ tcu::Sampler::MIRRORED_REPEAT_GL,
+ tcu::Sampler::LINEAR,
+ tcu::Sampler::LINEAR,
+ SRGBDECODE_DECODE);
+
+ this->addShaderProgram(shaderParametersA);
+ this->addShaderProgram(shaderParametersB);
+
+ this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);
+ this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXTURE);
+}
+
+bool DecodeToggledCase::verifyResult (void)
+{
+ tcu::TestLog& log = m_context.getTestContext().getLog();
+ const int resultColorIdx = 0;
+ std::vector<tcu::Vec4> pixelResultList;
+
+ this->readResultTextures();
+ this->storeResultPixels(pixelResultList);
+ this->logColor(std::string("Expected color: "), resultColorIdx, getColorGreenPass());
+
+ // result color is either green (pass) or fail (red)
+ if ( tcu::boolAll(tcu::equal(pixelResultList[resultColorIdx], getColorGreenPass())) )
+ {
+ log << tcu::TestLog::Message << std::string("returned pass color from GPU") << tcu::TestLog::EndMessage;
+ return true;
+ }
+ else
+ {
+ log << tcu::TestLog::Message << std::string("returned fail color from GPU") << tcu::TestLog::EndMessage;
+ return false;
+ }
+}
+
+class DecodeMultipleTexturesCase : public SRGBTestCase
+{
+public:
+ DecodeMultipleTexturesCase (Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
+ : SRGBTestCase (context, name, description, internalFormat) {}
+
+ ~DecodeMultipleTexturesCase (void) {}
+
+ void setupTest (void);
+ bool verifyResult (void);
+};
+
+void DecodeMultipleTexturesCase::setupTest (void)
+{
+ // TEST STEPS:
+ // - create and set texture_a to DECODE_SKIP_EXT and texture_b to DECODE_EXT
+ // - upload textures to the GPU and bind to seperate uniform variables
+ // - sample both textures using texture*()
+ // - read texel values back to the CPU
+ // - compare the texel values, both should be different from each other
+
+ FragmentShaderParameters shaderParameters(SHADEROUTPUTS_TWO, SHADERUNIFORMS_TWO, NULL, BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);
+
+ this->addTexture( TEXTURETYPE_2D,
+ TestDimensions::WIDTH,
+ TestDimensions::HEIGHT,
+ getColorReferenceLinear(),
+ tcu::Sampler::MIRRORED_REPEAT_GL,
+ tcu::Sampler::MIRRORED_REPEAT_GL,
+ tcu::Sampler::LINEAR,
+ tcu::Sampler::LINEAR,
+ SRGBDECODE_SKIP_DECODE);
+
+ this->addTexture( TEXTURETYPE_2D,
+ TestDimensions::WIDTH,
+ TestDimensions::HEIGHT,
+ getColorReferenceLinear(),
+ tcu::Sampler::MIRRORED_REPEAT_GL,
+ tcu::Sampler::MIRRORED_REPEAT_GL,
+ tcu::Sampler::LINEAR,
+ tcu::Sampler::LINEAR,
+ SRGBDECODE_DECODE);
+
+ this->addShaderProgram(shaderParameters);
+
+ this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);
+ this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXTURE);
+}
+
+bool DecodeMultipleTexturesCase::verifyResult (void)
+{
+ tcu::TestLog& log = m_context.getTestContext().getLog();
+ const int resultColorIdx = 0;
+ std::vector<tcu::Vec4> pixelResultList;
+ tcu::Vec4 pixelExpected0;
+ tcu::Vec4 pixelExpected1;
+
+ this->readResultTextures();
+ this->storeResultPixels(pixelResultList);
+
+ pixelExpected0 = this->formatReferenceColor(getColorReferenceSRGB());
+ pixelExpected1 = this->formatReferenceColor(getColorReferenceLinear());
+
+ this->logColor(std::string("Expected color: "), resultColorIdx, pixelExpected0);
+ this->logColor(std::string("Expected color: "), resultColorIdx +1, pixelExpected1);
+
+ // check if the two textures have different values i.e. uTexture0 = sRGB and uTexture1 = linear
+ if ( !(tcu::boolAll(tcu::equal(pixelResultList[resultColorIdx], pixelResultList[resultColorIdx +1]))) )
+ {
+ log << tcu::TestLog::Message << std::string("texel values are different") << tcu::TestLog::EndMessage;
+ return true;
+ }
+ else
+ {
+ log << tcu::TestLog::Message << std::string("texel values are equal") << tcu::TestLog::EndMessage;
+ return false;
+ }
+}
+
+class DecodeSamplerCase : public SRGBTestCase
+{
+public:
+ DecodeSamplerCase (Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
+ : SRGBTestCase (context, name, description, internalFormat) {}
+
+ ~DecodeSamplerCase (void) {}
+
+ void setupTest (void);
+ bool verifyResult (void);
+};
+
+void DecodeSamplerCase::setupTest (void)
+{
+ // TEST STEPS:
+ // - create and set texture_a to DECODE_SKIP_EXT
+ // - upload texture to the GPU and bind to sampler
+ // - sample texture using texture*()
+ // - read texel values back to the CPU
+ // - compare the texel values, should be in sampler format (linear)
+
+ FragmentShaderParameters shaderParameters(SHADEROUTPUTS_ONE, SHADERUNIFORMS_ONE, NULL, BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);
+
+ this->addTexture( TEXTURETYPE_2D,
+ TestDimensions::WIDTH,
+ TestDimensions::HEIGHT,
+ getColorReferenceLinear(),
+ tcu::Sampler::MIRRORED_REPEAT_GL,
+ tcu::Sampler::MIRRORED_REPEAT_GL,
+ tcu::Sampler::LINEAR,
+ tcu::Sampler::LINEAR,
+ SRGBDECODE_SKIP_DECODE);
+
+ this->addSampler( tcu::Sampler::MIRRORED_REPEAT_GL,
+ tcu::Sampler::MIRRORED_REPEAT_GL,
+ tcu::Sampler::LINEAR,
+ tcu::Sampler::LINEAR,
+ SRGBDECODE_DECODE);
+
+ this->addShaderProgram(shaderParameters);
+
+ this->bindSamplerToTexture(0, 0, GL_TEXTURE0);
+ this->activateSampler(0, true);
+
+ this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);
+ this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXTURE);
+}
+
+bool DecodeSamplerCase::verifyResult (void)
+{
+ tcu::TestLog& log = m_context.getTestContext().getLog();
+ const int resultColorIdx = 0;
+ std::vector<tcu::Vec4> pixelResultList;
+ tcu::Vec4 pixelConverted;
+ tcu::Vec4 pixelReference;
+ tcu::Vec4 pixelExpected;
+
+ this->readResultTextures();
+ this->storeResultPixels(pixelResultList);
+
+ pixelConverted = tcu::linearToSRGB(pixelResultList[resultColorIdx]);
+ pixelReference = this->formatReferenceColor(getColorReferenceSRGB());
+ pixelExpected = this->formatReferenceColor(getColorReferenceLinear());
+
+ this->logColor(std::string("Expected color: "), resultColorIdx, pixelExpected);
+
+ // texture was rendered using a sampler object with setting DECODE_EXT, therefore, results should be linear
+ if ( (tcu::boolAll(tcu::lessThan(tcu::abs(pixelConverted - pixelReference), m_epsilonError))) || (tcu::boolAll(tcu::equal(pixelConverted, pixelReference))) )
+ {
+ log << tcu::TestLog::Message << std::string("linear as expected") << tcu::TestLog::EndMessage;
+ return true;
+ }
+ else
+ {
+ log << tcu::TestLog::Message << std::string("not linear as expected") << tcu::TestLog::EndMessage;
+ return false;
+ }
+}
+
+} // anonymous
+
+SRGBDecodeTests::SRGBDecodeTests (Context& context)
+ : TestCaseGroup (context, "skip_decode", "sRGB skip decode tests")
+{
+}
+
+SRGBDecodeTests::~SRGBDecodeTests (void)
+{
+}
+
+void SRGBDecodeTests::init (void)
+{
+ const TestGroupConfig testGroupConfigList[] =
+ {
+ TestGroupConfig("srgba8", "srgb decode tests using srgba internal format", tcu::TextureFormat(tcu::TextureFormat::sRGBA, tcu::TextureFormat::UNORM_INT8)),
+ TestGroupConfig("sr8", "srgb decode tests using sr8 internal format", tcu::TextureFormat(tcu::TextureFormat::sR, tcu::TextureFormat::UNORM_INT8))
+ };
+
+ // create groups for all desired internal formats, adding test cases to each
+ for (std::size_t idx = 0; idx < DE_LENGTH_OF_ARRAY(testGroupConfigList); idx++)
+ {
+ tcu::TestCaseGroup* const testGroup = new tcu::TestCaseGroup(m_testCtx, testGroupConfigList[idx].name, testGroupConfigList[idx].description);
+ tcu::TestNode::addChild(testGroup);
+
+ testGroup->addChild(new TextureDecodeSkippedCase (m_context, "skipped", "testing for sRGB color values with sRGB texture decoding skipped", testGroupConfigList[idx].internalFormat));
+ testGroup->addChild(new TextureDecodeEnabledCase (m_context, "enabled", "testing for linear color values with sRGB texture decoding enabled", testGroupConfigList[idx].internalFormat));
+ testGroup->addChild(new TexelFetchDecodeSkippedcase (m_context, "texel_fetch", "testing for linear color values with sRGB texture decoding skipped", testGroupConfigList[idx].internalFormat));
+ testGroup->addChild(new GPUConversionDecodeEnabledCase (m_context, "conversion_gpu", "sampling linear values and performing conversion on the gpu", testGroupConfigList[idx].internalFormat));
+ testGroup->addChild(new DecodeToggledCase (m_context, "toggled", "toggle the sRGB decoding between draw calls", testGroupConfigList[idx].internalFormat));
+ testGroup->addChild(new DecodeMultipleTexturesCase (m_context, "multiple_textures","upload multiple textures with different sRGB decode values and sample",testGroupConfigList[idx].internalFormat));
+ testGroup->addChild(new DecodeSamplerCase (m_context, "using_sampler", "testing that sampler object takes priority over texture state", testGroupConfigList[idx].internalFormat));
+ }
+}
+
+} // Functional
+} // gles31
+} // deqp
--- /dev/null
+#ifndef _ES31FSRGBDECODETESTS_HPP
+#define _ES31FSRGBDECODETESTS_HPP
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.1 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2017 The Android Open Source Project
+ *
+ * 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.
+ *
+ *//*!
+ * \file
+ * \brief sRGB decode tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tes31TestCase.hpp"
+
+namespace deqp
+{
+namespace gles31
+{
+namespace Functional
+{
+
+class SRGBDecodeTests : public TestCaseGroup
+{
+public:
+ SRGBDecodeTests (Context& context);
+ ~SRGBDecodeTests (void);
+
+private:
+ void init (void);
+
+ SRGBDecodeTests (const SRGBDecodeTests& other);
+ SRGBDecodeTests& operator= (const SRGBDecodeTests& other);
+};
+
+} // Functional
+} // gles31
+} // deqp
+
+
+#endif // _ES31FSRGBDECODETESTS_HPP
\ No newline at end of file
<< "void main ()\n"
<< "{\n"
<< " // flip high bits\n"
- << " highp uint mask = uint(1) << (16u + (gl_GlobalInvocationID.x % 16u));\n"
+ << " highp uint mask = uint(1) << (24u + (gl_GlobalInvocationID.x % 8u));\n"
<< " sb_work.dummy = atomicXor(sb_work.targetValue, mask);\n"
<< "}";
queryGroup->addChild(new LimitQueryCase(m_context, "max_tess_evaluation_texture_image_units", "Test MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS", GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS, 16));
queryGroup->addChild(new LimitQueryCase(m_context, "max_tess_control_output_components", "Test MAX_TESS_CONTROL_OUTPUT_COMPONENTS", GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS, 64));
queryGroup->addChild(new LimitQueryCase(m_context, "max_tess_patch_components", "Test MAX_TESS_PATCH_COMPONENTS", GL_MAX_TESS_PATCH_COMPONENTS, 120));
- queryGroup->addChild(new LimitQueryCase(m_context, "max_tess_control_total_output_components", "Test MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS", GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS, 4096));
+ queryGroup->addChild(new LimitQueryCase(m_context, "max_tess_control_total_output_components", "Test MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS", GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS, 2048));
queryGroup->addChild(new LimitQueryCase(m_context, "max_tess_evaluation_output_components", "Test MAX_TESS_EVALUATION_OUTPUT_COMPONENTS", GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS, 64));
queryGroup->addChild(new LimitQueryCase(m_context, "max_tess_control_uniform_blocks", "Test MAX_TESS_CONTROL_UNIFORM_BLOCKS", GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS, 12));
queryGroup->addChild(new LimitQueryCase(m_context, "max_tess_evaluation_uniform_blocks", "Test MAX_TESS_EVALUATION_UNIFORM_BLOCKS", GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS, 12));
(deUint32)(DEPTH_RENDERABLE | STENCIL_RENDERABLE | TEXTURE_VALID),
GLS_ARRAY_RANGE(s_oesPackedDepthStencilTexFormats)
},
+ // The ANGLE extension incorporates GL_OES_depth_texture/GL_OES_packed_depth_stencil.
+ {
+ "GL_ANGLE_depth_texture",
+ (deUint32)(REQUIRED_RENDERABLE | DEPTH_RENDERABLE | TEXTURE_VALID),
+ GLS_ARRAY_RANGE(s_oesDepthTextureFormats),
+ },
// \todo [2013-12-10 lauri] Find out if OES_texture_half_float is really a
// requirement on ES3 also. Or is color_buffer_half_float applicatble at
// all on ES3, since there's also EXT_color_buffer_float?
rotation = "unspecified",
surfacetype = "window",
filters = NYC_EGL_COMMON_FILTERS,
- runtime = "24m"),
+ runtime = "11m"),
])
NYC_GLES2_COMMON_FILTERS = [
rotation = "unspecified",
surfacetype = "window",
filters = NYC_GLES2_COMMON_FILTERS,
- runtime = "40m"),
+ runtime = "30m"),
])
NYC_GLES3_COMMON_FILTERS = [
rotation = "unspecified",
surfacetype = "window",
filters = NYC_GLES3_COMMON_FILTERS,
- runtime = "1h15m"),
+ runtime = "1h50min"),
# Rotations
Configuration(name = "rotate-portrait",
glconfig = "rgba8888d24s8ms0",
rotation = "0",
surfacetype = "window",
filters = NYC_GLES3_COMMON_FILTERS + [include("gles3-rotation.txt")],
- runtime = "7m"),
+ runtime = "5m"),
Configuration(name = "rotate-landscape",
glconfig = "rgba8888d24s8ms0",
rotation = "90",
surfacetype = "window",
filters = NYC_GLES3_COMMON_FILTERS + [include("gles3-rotation.txt")],
- runtime = "7m"),
+ runtime = "5m"),
Configuration(name = "rotate-reverse-portrait",
glconfig = "rgba8888d24s8ms0",
rotation = "180",
surfacetype = "window",
filters = NYC_GLES3_COMMON_FILTERS + [include("gles3-rotation.txt")],
- runtime = "7m"),
+ runtime = "5m"),
Configuration(name = "rotate-reverse-landscape",
glconfig = "rgba8888d24s8ms0",
rotation = "270",
surfacetype = "window",
filters = NYC_GLES3_COMMON_FILTERS + [include("gles3-rotation.txt")],
- runtime = "7m"),
+ runtime = "5m"),
# MSAA
Configuration(name = "multisample",
rotation = "unspecified",
surfacetype = "window",
filters = NYC_GLES31_COMMON_FILTERS,
- runtime = "7h30m"),
+ runtime = "4h40m"),
# Rotations
Configuration(name = "rotate-portrait",
NYC_VULKAN_PKG = Package(module = VULKAN_MODULE, configurations = [
Configuration(name = "master",
filters = NYC_VULKAN_FILTERS,
- runtime = "3h45m"),
+ runtime = "1h11m"),
])
# Master
MASTER_EGL_COMMON_FILTERS = [include("egl-master.txt"),
exclude("egl-test-issues.txt"),
- exclude("egl-internal-api-tests.txt")]
+ exclude("egl-internal-api-tests.txt"),
+ exclude("egl-manual-robustness.txt")]
MASTER_EGL_PKG = Package(module = EGL_MODULE, configurations = [
# Master
Configuration(name = "master",
surfacetype = "window",
required = True,
filters = MASTER_EGL_COMMON_FILTERS,
- runtime = "24m"),
+ runtime = "23m"),
])
MASTER_GLES2_COMMON_FILTERS = [
surfacetype = "window",
required = True,
filters = MASTER_GLES2_COMMON_FILTERS,
- runtime = "40m"),
+ runtime = "46m"),
])
MASTER_GLES3_COMMON_FILTERS = [
surfacetype = "window",
required = True,
filters = MASTER_GLES3_COMMON_FILTERS,
- runtime = "1h15m"),
+ runtime = "1h50m"),
# Rotations
Configuration(name = "rotate-portrait",
glconfig = "rgba8888d24s8ms0",
rotation = "0",
surfacetype = "window",
filters = MASTER_GLES3_COMMON_FILTERS + [include("gles3-rotation.txt")],
- runtime = "7m"),
+ runtime = "1m"),
Configuration(name = "rotate-landscape",
glconfig = "rgba8888d24s8ms0",
rotation = "90",
surfacetype = "window",
filters = MASTER_GLES3_COMMON_FILTERS + [include("gles3-rotation.txt")],
- runtime = "7m"),
+ runtime = "1m"),
Configuration(name = "rotate-reverse-portrait",
glconfig = "rgba8888d24s8ms0",
rotation = "180",
surfacetype = "window",
filters = MASTER_GLES3_COMMON_FILTERS + [include("gles3-rotation.txt")],
- runtime = "7m"),
+ runtime = "1m"),
Configuration(name = "rotate-reverse-landscape",
glconfig = "rgba8888d24s8ms0",
rotation = "270",
surfacetype = "window",
filters = MASTER_GLES3_COMMON_FILTERS + [include("gles3-rotation.txt")],
- runtime = "7m"),
+ runtime = "1m"),
# MSAA
Configuration(name = "multisample",
surfacetype = "window",
filters = MASTER_GLES3_COMMON_FILTERS + [include("gles3-multisample.txt"),
exclude("gles3-multisample-issues.txt")],
- runtime = "10m"),
+ runtime = "1m"),
# Pixel format
Configuration(name = "565-no-depth-no-stencil",
surfacetype = "window",
filters = MASTER_GLES3_COMMON_FILTERS + [include("gles3-pixelformat.txt"),
exclude("gles3-pixelformat-issues.txt")],
- runtime = "10m"),
+ runtime = "1m"),
])
MASTER_GLES31_COMMON_FILTERS = [
surfacetype = "window",
required = True,
filters = MASTER_GLES31_COMMON_FILTERS,
- runtime = "7h30m"),
+ runtime = "1h40m"),
# Rotations
Configuration(name = "rotate-portrait",
MASTER_VULKAN_PKG = Package(module = VULKAN_MODULE, configurations = [
Configuration(name = "master",
filters = MASTER_VULKAN_FILTERS,
- runtime = "3h45m"),
+ runtime = "2h29m"),
])
MUSTPASS_LISTS = [
EGL_SOURCE = khr_util.registry_cache.RegistrySource(
"egl.xml",
- 32725,
- "3464385212ae9b816d121c77bc4191ed3dfb32ce7bfca1a02b42fcefa3ec2354")
+ 33315,
+ "19f3b517f0dede56a6a94b820d08149ef5e1726f58202f47d69fa27f6f483bd2")
VERSION = '1.5'
"EGL_EXT_buffer_age",
"EGL_KHR_partial_update",
"EGL_KHR_swap_buffers_with_damage",
- "EGL_KHR_mutable_render_buffer"
+ "EGL_KHR_mutable_render_buffer",
+ "EGL_EXT_pixel_format_float"
]
PROTECTS = [
"KHRONOS_SUPPORT_INT64"
"TRANSPARENT_TYPE",
"TRANSPARENT_RED_VALUE",
"TRANSPARENT_GREEN_VALUE",
- "TRANSPARENT_BLUE_VALUE"
+ "TRANSPARENT_BLUE_VALUE",
+ "COLOR_COMPONENT_TYPE_EXT"
]),
("SurfaceAttrib", [
"CONFIG_ID",
"YUV_PLANE_BPP_8_EXT",
"YUV_PLANE_BPP_10_EXT",
]),
+ ("ColorComponentType", ["COLOR_COMPONENT_TYPE_FIXED_EXT", "COLOR_COMPONENT_TYPE_FLOAT_EXT"]),
("SurfaceTarget", ["READ", "DRAW"]),
# ConfigAttrib values
# ErrorCode
("Error", ["NO_ERROR", "INVALID_ENUM", "INVALID_VALUE", "INVALID_OPERATION", "OUT_OF_MEMORY",
- "INVALID_FRAMEBUFFER_OPERATION"]),
+ "INVALID_FRAMEBUFFER_OPERATION", "CONTEXT_LOST"]),
# PixelType, partially
("Type", [
# GLES2 types
("TextureFormat", [
# generated: UncompressedTextureFormat + CompressedTextureFormat
]),
+
+ # GraphicsResetStatus
+ ("GraphicsResetStatus", [
+ "NO_ERROR",
+ "GUILTY_CONTEXT_RESET",
+ "INNOCENT_CONTEXT_RESET",
+ "UNKNOWN_CONTEXT_RESET",
+ ]),
]
def getEnumGroupByName (name):
'GL_EXT_geometry_point_size',
'GL_EXT_tessellation_shader',
'GL_EXT_geometry_shader',
+ 'GL_EXT_robustness',
'GL_EXT_texture_buffer',
'GL_EXT_texture_snorm',
'GL_EXT_primitive_bounding_box',