# \note PNG_LIBRARY and PNG_INCLUDE_PATH are promoted from external/libpng/CMakeLists.txt
endif ()
+# glslang
+add_subdirectory(external/glslang)
+
+# spirv-tools
+add_subdirectory(external/spirv-tools)
+
include_directories(${PNG_INCLUDE_PATH})
message(STATUS "DEQP_TARGET_NAME = ${DEQP_TARGET_NAME}")
framework/randomshaders
framework/egl
framework/egl/wrapper
+ external/vulkancts/framework/vulkan
)
if (DE_OS_IS_ANDROID OR DE_OS_IS_IOS)
endmacro (add_data_file)
add_subdirectory(framework)
+add_subdirectory(external/vulkancts/framework/vulkan)
if (DE_COMPILER_IS_MSC)
add_compile_options(/bigobj) # Required by glsBuiltinPrecisionTests.cpp
endif ()
add_subdirectory(modules)
+add_subdirectory(external/vulkancts/modules/vulkan)
# Single-binary targets
if (DE_OS_IS_ANDROID)
import android.app.Service;
import android.app.Notification;
+import android.app.Notification.Builder;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Binder;
PendingIntent pm = PendingIntent.getActivity(this, 0, launchIntent, 0);
// Start as foreground service.
- Notification notification = new Notification(R.drawable.deqp_app_small, "dEQP ExecServer", System.currentTimeMillis());
- notification.setLatestEventInfo(this, "dEQP ExecServer", "ExecServer is running in the background.", pm);
+ Notification.Builder builder = new Notification.Builder(this);
+ Notification notification = builder.setContentIntent(pm)
+ .setSmallIcon(R.drawable.deqp_app_small).setTicker("ExecServer is running in the background.")
+ .setWhen(System.currentTimeMillis()).setAutoCancel(true).setContentTitle("dEQP ExecServer")
+ .setContentText("ExecServer is running in the background.").build();
startForeground(1, notification);
return START_STICKY; // Keep us running until explictly stopped
NativeLib(21, "arm64-v8a", 'android-arm64'), # ARM64 v8a ABI
]
-ANDROID_JAVA_API = "android-13"
+ANDROID_JAVA_API = "android-22"
NATIVE_LIB_NAME = "libdeqp.so"
def selectNDKPath ():
--- /dev/null
+<style type="text/css">
+
+code,div.listingblock {
+ max-width: 68em;
+}
+
+p {
+ max-width: 50em;
+}
+
+table {
+ max-width: 50em;
+}
+
+table.tableblock {
+ border-width: 1px;
+}
+
+h2 {
+ max-width: 35em;
+}
+
+</style>
--- /dev/null
+// asciidoc -b html5 -d book -f apitests.conf apitests.adoc
+
+:toc:
+:numbered:
+:docinfo:
+:revnumber: 4
+
+Vulkan API Test Plan
+====================
+
+NOTE: Document currently targets API revision 0.138.0
+
+This document currently outlines Vulkan API testing plan. The document splits API into features, and for each the important testing objectives are described. The technical implementation is not currently planned or documented here, except in select cases.
+
+In the future this document will likely evolve into a description of various tests and test coverage.
+
+Test framework
+--------------
+
+Test framework will provide tests access to Vulkan platform interface. In addition a library of generic utilties will be provided.
+
+Test case base class
+~~~~~~~~~~~~~~~~~~~~
+
+Vulkan test cases will use a slightly different interface from traditional +tcu::TestCase+ to facilitate following:
+
+ * Ability to generate shaders in high-level language, and pre-compile them without running the tests
+ * Cleaner separation between test case parameters and execution instance
+
+[source,cpp]
+----
+class TestCase : public tcu::TestCase
+{
+public:
+ TestCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description);
+ TestCase (tcu::TestContext& testCtx, tcu::TestNodeType type, const std::string& name, const std::string& description);
+ virtual ~TestCase (void) {}
+
+ virtual void initPrograms (vk::ProgramCollection<glu::ProgramSources>& programCollection) const;
+ virtual TestInstance* createInstance (Context& context) const = 0;
+
+ IterateResult iterate (void) { DE_ASSERT(false); return STOP; } // Deprecated in this module
+};
+
+class TestInstance
+{
+public:
+ TestInstance (Context& context) : m_context(context) {}
+ virtual ~TestInstance (void) {}
+
+ virtual tcu::TestStatus iterate (void) = 0;
+
+protected:
+ Context& m_context;
+};
+----
+
+In addition for simple tests a utility to wrap a function as a test case is provided:
+
+[source,cpp]
+----
+tcu::TestStatus createSamplerTest (Context& context)
+{
+ TestLog& log = context.getTestContext().getLog();
+ const DefaultDevice device (context.getPlatformInterface(), context.getTestContext().getCommandLine());
+ const VkDevice vkDevice = device.getDevice();
+ const DeviceInterface& vk = device.getInterface();
+
+ {
+ const struct VkSamplerCreateInfo samplerInfo =
+ {
+ VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ VK_TEX_FILTER_NEAREST, // VkTexFilter magFilter;
+ VK_TEX_FILTER_NEAREST, // VkTexFilter minFilter;
+ VK_TEX_MIPMAP_MODE_BASE, // VkTexMipmapMode mipMode;
+ VK_TEX_ADDRESS_CLAMP, // VkTexAddress addressU;
+ VK_TEX_ADDRESS_CLAMP, // VkTexAddress addressV;
+ VK_TEX_ADDRESS_CLAMP, // VkTexAddress addressW;
+ 0.0f, // float mipLodBias;
+ 0u, // deUint32 maxAnisotropy;
+ VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp;
+ 0.0f, // float minLod;
+ 0.0f, // float maxLod;
+ VK_BORDER_COLOR_TRANSPARENT_BLACK, // VkBorderColor borderColor;
+ };
+
+ Move<VkSamplerT> tmpSampler = createSampler(vk, vkDevice, &samplerInfo);
+ }
+
+ return tcu::TestStatus::pass("Creating sampler succeeded");
+}
+
+tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> apiTests (new tcu::TestCaseGroup(testCtx, "api", "API Tests"));
+
+ addFunctionCase(apiTests.get(), "create_sampler", "", createSamplerTest);
+
+ return apiTests.release();
+}
+----
+
++vkt::Context+, which is passed to +vkt::TestInstance+ will provide access to Vulkan platform interface, and a default device instance. Most test cases should use default device instance:
+
+ * Creating device can take up to tens of milliseconds
+ * --deqp-vk-device-id=N command line option can be used to change device
+ * Framework can force validation layers (--deqp-vk-layers=validation,...)
+
+Other considerations:
+
+ * Rather than using default header, deqp uses custom header & interface wrappers
+ ** See +vk::PlatformInterface+ and +vk::DeviceInterface+
+ ** Enables optional run-time dependency to Vulkan driver (required for Android, useful in general)
+ ** Various logging & other analysis facilities can be layered on top of that interface
+ * Expose validation state to tests to be able to test validation
+ * Extensions are opt-in, some tests will require certain extensions to work
+ ** --deqp-vk-extensions? enable all by default?
+ ** Probably good to be able to override extensions as well (verify that tests report correct results without extensions)
+
+Common utilities
+~~~~~~~~~~~~~~~~
+
+Test case independent Vulkan utilities will be provided in +vk+ namespace, and can be found under +framework/vulkan+. These include:
+
+ * +Unique<T>+ and +Move<T>+ wrappers for Vulkan API objects
+ * Creating all types of work with configurable parameters:
+ ** Workload "size" (not really comparable between types)
+ ** Consume & produce memory contents
+ *** Simple checksumming / other verification against reference data typically fine
+
+.TODO
+ * Document important utilities (vkRef.hpp for example).
+ * Document Vulkan platform port.
+
+Object management
+-----------------
+
+Object management tests verify that the driver is able to create and destroy objects of all types. The tests don't attempt to use the objects (unless necessary for testing object construction) as that is covered by feature-specific tests. For all object types the object management tests cover:
+
+ * Creating objects with a relevant set of parameters
+ ** Not exhaustive, guided by what might actually make driver to take different path
+ * Allocating multiple objects of same type
+ ** Reasonable limit depends on object type
+ * Creating objects from multiple threads concurrently (where possible)
+ * Freeing objects from multiple threads
+
+NOTE: tests for various +vkCreate*()+ functions are documented in feature-specific sections.
+
+Multithreaded scaling
+---------------------
+
+Vulkan API is free-threaded and suggests that many operations (such as constructing command buffers) will scale with number of app threads. Tests are needed for proving that such scalability actually exists, and there are no locks in important functionality preventing that.
+
+NOTE: Khronos CTS has not traditionally included any performance testing, and the tests may not be part of conformance criteria. The tests may however be useful for IHVs for driver optimization, and could be enforced by platform-specific conformance tests, such as Android CTS.
+
+Destructor functions
+~~~~~~~~~~~~~~~~~~~~
+
+[source,c]
+----
+VkResult VKAPI vkDestroyInstance(
+ VkInstance instance);
+
+VkResult VKAPI vkDestroyDevice(
+ VkDevice device);
+
+VkResult VKAPI vkDestroyFence(
+ VkDevice device,
+ VkFence fence);
+
+VkResult VKAPI vkDestroySemaphore(
+ VkDevice device,
+ VkSemaphore semaphore);
+
+VkResult VKAPI vkDestroyEvent(
+ VkDevice device,
+ VkEvent event);
+
+VkResult VKAPI vkDestroyQueryPool(
+ VkDevice device,
+ VkQueryPool queryPool);
+
+VkResult VKAPI vkDestroyBuffer(
+ VkDevice device,
+ VkBuffer buffer);
+
+VkResult VKAPI vkDestroyBufferView(
+ VkDevice device,
+ VkBufferView bufferView);
+
+VkResult VKAPI vkDestroyImage(
+ VkDevice device,
+ VkImage image);
+
+VkResult VKAPI vkDestroyImageView(
+ VkDevice device,
+ VkImageView imageView);
+
+VkResult VKAPI vkDestroyAttachmentView(
+ VkDevice device,
+ VkAttachmentView attachmentView);
+
+VkResult VKAPI vkDestroyShaderModule(
+ VkDevice device,
+ VkShaderModule shaderModule);
+
+VkResult VKAPI vkDestroyShader(
+ VkDevice device,
+ VkShader shader);
+
+VkResult VKAPI vkDestroyPipelineCache(
+ VkDevice device,
+ VkPipelineCache pipelineCache);
+
+VkResult VKAPI vkDestroyPipeline(
+ VkDevice device,
+ VkPipeline pipeline);
+
+VkResult VKAPI vkDestroyPipelineLayout(
+ VkDevice device,
+ VkPipelineLayout pipelineLayout);
+
+VkResult VKAPI vkDestroySampler(
+ VkDevice device,
+ VkSampler sampler);
+
+VkResult VKAPI vkDestroyDescriptorSetLayout(
+ VkDevice device,
+ VkDescriptorSetLayout descriptorSetLayout);
+
+VkResult VKAPI vkDestroyDescriptorPool(
+ VkDevice device,
+ VkDescriptorPool descriptorPool);
+
+VkResult VKAPI vkDestroyDynamicViewportState(
+ VkDevice device,
+ VkDynamicViewportState dynamicViewportState);
+
+VkResult VKAPI vkDestroyDynamicRasterState(
+ VkDevice device,
+ VkDynamicRasterState dynamicRasterState);
+
+VkResult VKAPI vkDestroyDynamicColorBlendState(
+ VkDevice device,
+ VkDynamicColorBlendState dynamicColorBlendState);
+
+VkResult VKAPI vkDestroyDynamicDepthStencilState(
+ VkDevice device,
+ VkDynamicDepthStencilState dynamicDepthStencilState);
+
+VkResult VKAPI vkDestroyFramebuffer(
+ VkDevice device,
+ VkFramebuffer framebuffer);
+
+VkResult VKAPI vkDestroyRenderPass(
+ VkDevice device,
+ VkRenderPass renderPass);
+
+VkResult VKAPI vkDestroyCommandPool(
+ VkDevice device,
+ VkCmdPool cmdPool);
+
+VkResult VKAPI vkDestroyCommandBuffer(
+ VkDevice device,
+ VkCmdBuffer commandBuffer);
+----
+
+API Queries
+-----------
+
+Objective of API query tests is to validate that various +vkGet*+ functions return correct values. Generic checks that apply to all query types are:
+
+ * Returned value size is equal or multiple of relevant struct size
+ * Query doesn't write outside the provided pointer
+ * Query values (where expected) don't change between subsequent queries
+ * Concurrent queries from multiple threads work
+
+Platform queries
+~~~~~~~~~~~~~~~~
+
+Platform query tests will validate that all queries work as expected and return sensible values.
+
+ * Sensible device properties
+ ** May have some Android-specific requirements
+ *** TBD queue 0 must be universal queue (all command types supported)
+ * All required functions present
+ ** Both platform (physicalDevice = 0) and device-specific
+ ** Culled based on enabled extension list?
+
+[source,c]
+----
+// Physical devices
+
+VkResult VKAPI vkEnumeratePhysicalDevices(
+ VkInstance instance,
+ uint32_t* pPhysicalDeviceCount,
+ VkPhysicalDevice* pPhysicalDevices);
+
+VkResult VKAPI vkGetPhysicalDeviceFeatures(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceFeatures* pFeatures);
+
+// Properties & limits
+
+VkResult VKAPI vkGetPhysicalDeviceLimits(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceLimits* pLimits);
+
+typedef struct {
+ uint32_t apiVersion;
+ uint32_t driverVersion;
+ uint32_t vendorId;
+ uint32_t deviceId;
+ VkPhysicalDeviceType deviceType;
+ char deviceName[VK_MAX_PHYSICAL_DEVICE_NAME];
+ uint8_t pipelineCacheUUID[VK_UUID_LENGTH];
+} VkPhysicalDeviceProperties;
+
+VkResult VKAPI vkGetPhysicalDeviceProperties(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceProperties* pProperties);
+
+// Queue properties
+
+VkResult VKAPI vkGetPhysicalDeviceQueueCount(
+ VkPhysicalDevice physicalDevice,
+ uint32_t* pCount);
+
+typedef enum {
+ VK_QUEUE_GRAPHICS_BIT = 0x00000001,
+ VK_QUEUE_COMPUTE_BIT = 0x00000002,
+ VK_QUEUE_DMA_BIT = 0x00000004,
+ VK_QUEUE_SPARSE_MEMMGR_BIT = 0x00000008,
+ VK_QUEUE_EXTENDED_BIT = 0x40000000,
+} VkQueueFlagBits;
+typedef VkFlags VkQueueFlags;
+
+typedef struct {
+ VkQueueFlags queueFlags;
+ uint32_t queueCount;
+ VkBool32 supportsTimestamps;
+} VkPhysicalDeviceQueueProperties;
+
+VkResult VKAPI vkGetPhysicalDeviceQueueProperties(
+ VkPhysicalDevice physicalDevice,
+ uint32_t count,
+ VkPhysicalDeviceQueueProperties* pQueueProperties);
+
+// Memory properties
+
+typedef enum {
+ VK_MEMORY_PROPERTY_DEVICE_ONLY = 0,
+ VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT = 0x00000001,
+ VK_MEMORY_PROPERTY_HOST_NON_COHERENT_BIT = 0x00000002,
+ VK_MEMORY_PROPERTY_HOST_UNCACHED_BIT = 0x00000004,
+ VK_MEMORY_PROPERTY_HOST_WRITE_COMBINED_BIT = 0x00000008,
+ VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT = 0x00000010,
+} VkMemoryPropertyFlagBits;
+typedef VkFlags VkMemoryPropertyFlags;
+
+typedef enum {
+ VK_MEMORY_HEAP_HOST_LOCAL = 0x00000001,
+} VkMemoryHeapFlagBits;
+typedef VkFlags VkMemoryHeapFlags;
+
+typedef struct {
+ VkMemoryPropertyFlags propertyFlags;
+ uint32_t heapIndex;
+} VkMemoryType;
+
+typedef struct {
+ VkDeviceSize size;
+ VkMemoryHeapFlags flags;
+} VkMemoryHeap;
+
+typedef struct {
+ uint32_t memoryTypeCount;
+ VkMemoryType memoryTypes[VK_MAX_MEMORY_TYPES];
+ uint32_t memoryHeapCount;
+ VkMemoryHeap memoryHeaps[VK_MAX_MEMORY_HEAPS];
+} VkPhysicalDeviceMemoryProperties;
+
+VkResult VKAPI vkGetPhysicalDeviceMemoryProperties(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceMemoryProperties* pMemoryProperties);
+
+// Proc address queries
+
+PFN_vkVoidFunction VKAPI vkGetInstanceProcAddr(
+ VkInstance instance,
+ const char* pName);
+
+PFN_vkVoidFunction VKAPI vkGetDeviceProcAddr(
+ VkDevice device,
+ const char* pName);
+
+// Extension queries
+
+typedef struct {
+ char extName[VK_MAX_EXTENSION_NAME];
+ uint32_t specVersion;
+} VkExtensionProperties;
+
+VkResult VKAPI vkGetGlobalExtensionProperties(
+ const char* pLayerName,
+ uint32_t* pCount,
+ VkExtensionProperties* pProperties);
+
+VkResult VKAPI vkGetPhysicalDeviceExtensionProperties(
+ VkPhysicalDevice physicalDevice,
+ const char* pLayerName,
+ uint32_t* pCount,
+ VkExtensionProperties* pProperties);
+
+// Layer queries
+
+typedef struct {
+ char layerName[VK_MAX_EXTENSION_NAME];
+ uint32_t specVersion;
+ uint32_t implVersion;
+ const char* description[VK_MAX_DESCRIPTION];
+} VkLayerProperties;
+
+VkResult VKAPI vkGetGlobalLayerProperties(
+ uint32_t* pCount,
+ VkLayerProperties* pProperties);
+
+VkResult VKAPI vkGetPhysicalDeviceLayerProperties(
+ VkPhysicalDevice physicalDevice,
+ uint32_t* pCount,
+ VkLayerProperties* pProperties);
+----
+
+Device queries
+~~~~~~~~~~~~~~
+
+[source,c]
+----
+VkResult VKAPI vkGetDeviceQueue(
+ VkDevice device,
+ uint32_t queueFamilyIndex,
+ uint32_t queueIndex,
+ VkQueue* pQueue);
+
+VkResult VKAPI vkGetDeviceMemoryCommitment(
+ VkDevice device,
+ VkDeviceMemory memory,
+ VkDeviceSize* pCommittedMemoryInBytes);
+----
+
+Object queries
+~~~~~~~~~~~~~~
+
+ * Memory requirements: verify that for buffers the returned size is at least the size of the buffer
+
+[source,c]
+----
+typedef struct {
+ VkDeviceSize size;
+ VkDeviceSize alignment;
+ uint32_t memoryTypeBits;
+} VkMemoryRequirements;
+
+VkResult VKAPI vkGetBufferMemoryRequirements(
+ VkDevice device,
+ VkBuffer buffer,
+ VkMemoryRequirements* pMemoryRequirements);
+
+VkResult VKAPI vkGetImageMemoryRequirements(
+ VkDevice device,
+ VkImage image,
+ VkMemoryRequirements* pMemoryRequirements);
+----
+
+Format & image capabilities
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+[source,c]
+----
+typedef enum {
+ VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT = 0x00000001,
+ VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT = 0x00000002,
+ VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT = 0x00000004,
+ VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT = 0x00000008,
+ VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT = 0x00000010,
+ VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT = 0x00000020,
+ VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT = 0x00000040,
+ VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT = 0x00000080,
+ VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT = 0x00000100,
+ VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000200,
+ VK_FORMAT_FEATURE_CONVERSION_BIT = 0x00000400,
+} VkFormatFeatureFlagBits;
+typedef VkFlags VkFormatFeatureFlags;
+
+typedef struct {
+ VkFormatFeatureFlags linearTilingFeatures;
+ VkFormatFeatureFlags optimalTilingFeatures;
+} VkFormatProperties;
+
+VkResult VKAPI vkGetPhysicalDeviceFormatProperties(
+ VkPhysicalDevice physicalDevice,
+ VkFormat format,
+ VkFormatProperties* pFormatProperties);
+
+typedef struct {
+ uint64_t maxResourceSize;
+ uint32_t maxSamples;
+} VkImageFormatProperties;
+
+VkResult VKAPI vkGetPhysicalDeviceImageFormatProperties(
+ VkPhysicalDevice physicalDevice,
+ VkFormat format,
+ VkImageType type,
+ VkImageTiling tiling,
+ VkImageUsageFlags usage,
+ VkImageFormatProperties* pImageFormatProperties);
+----
+
+Memory management
+-----------------
+
+Memory management tests cover memory allocation, sub-allocation, access, and CPU and GPU cache control. Testing some areas such as cache control will require stress-testing memory accesses from CPU and various pipeline stages.
+
+Memory allocation
+~~~~~~~~~~~~~~~~~
+
+[source,c]
+----
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ VkDeviceSize allocationSize;
+ uint32_t memoryTypeIndex;
+} VkMemoryAllocInfo;
+
+VkResult VKAPI vkAllocMemory(
+ VkDevice device,
+ const VkMemoryAllocInfo* pAllocInfo,
+ VkDeviceMemory* pMem);
+
+VkResult VKAPI vkFreeMemory(
+ VkDevice device,
+ VkDeviceMemory mem);
+----
+
+ * Test combination of:
+ ** Various allocation sizes
+ ** All heaps
+ * Allocations that exceed total available memory size (expected to fail)
+ * Concurrent allocation and free from multiple threads
+ * Memory leak tests (may not work on platforms that overcommit)
+ ** Allocate memory until fails, free all and repeat
+ ** Total allocated memory size should remain stable over iterations
+ ** Allocate and free in random order
+
+.Spec issues
+
+What are the alignment guarantees for the returned memory allocation? Will it satisfy alignment requirements for all object types? If not, app needs to know the alignment, or alignment parameter needs to be added to +VkMemoryAllocInfo+.
+
+Minimum allocation size? If 1, presumably implementation has to round it up to next page size at least? Is there a query for that? What happens when accessing the added padding?
+
+Mapping memory and CPU access
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+[source,c]
+----
+VkResult VKAPI vkMapMemory(
+ VkDevice device,
+ VkDeviceMemory mem,
+ VkDeviceSize offset,
+ VkDeviceSize size,
+ VkMemoryMapFlags flags,
+ void** ppData);
+
+VkResult VKAPI vkUnmapMemory(
+ VkDevice device,
+ VkDeviceMemory mem);
+----
+
+ * Verify that mapping of all host-visible allocations succeed and accessing memory works
+ * Verify mapping of sub-ranges
+ * Access still works after un-mapping and re-mapping memory
+ * Attaching or detaching memory allocation from buffer/image doesn't affect mapped memory access or contents
+ ** Images: test with various formats, mip-levels etc.
+
+.Spec issues
+ * Man pages say vkMapMemory is thread-safe, but to what extent?
+ ** Mapping different VkDeviceMemory allocs concurrently?
+ ** Mapping different sub-ranges of same VkDeviceMemory?
+ ** Mapping overlapping sub-ranges of same VkDeviceMemory?
+ * Okay to re-map same or overlapping range? What pointers should be returned in that case?
+ * Can re-mapping same block return different virtual address?
+ * Alignment of returned CPU pointer?
+ ** Access using SIMD instructions can benefit from alignment
+
+CPU cache control
+~~~~~~~~~~~~~~~~~
+
+[source,c]
+----
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ VkDeviceMemory mem;
+ VkDeviceSize offset;
+ VkDeviceSize size;
+} VkMappedMemoryRange;
+
+VkResult VKAPI vkFlushMappedMemoryRanges(
+ VkDevice device,
+ uint32_t memRangeCount,
+ const VkMappedMemoryRange* pMemRanges);
+
+VkResult VKAPI vkInvalidateMappedMemoryRanges(
+ VkDevice device,
+ uint32_t memRangeCount,
+ const VkMappedMemoryRange* pMemRanges);
+----
+
+ * TODO Semantics discussed at https://cvs.khronos.org/bugzilla/show_bug.cgi?id=13690
+ ** Invalidate relevant for HOST_NON_COHERENT_BIT, flushes CPU read caches
+ ** Flush flushes CPU write caches?
+ * Test behavior with all possible mem alloc types & various sizes
+ * Corner-cases:
+ ** Empty list
+ ** Empty ranges
+ ** Same range specified multiple times
+ ** Partial overlap between ranges
+
+.Spec issues
+ * Thread-safety? Okay to flush different ranges concurrently?
+
+GPU cache control
+~~~~~~~~~~~~~~~~~
+
+Validate that GPU caches are invalidated where instructed. This includes visibility of memory writes made by both CPU and GPU to both CPU and GPU pipeline stages.
+
+[source,c]
+----
+typedef enum {
+ VK_MEMORY_OUTPUT_HOST_WRITE_BIT = 0x00000001,
+ VK_MEMORY_OUTPUT_SHADER_WRITE_BIT = 0x00000002,
+ VK_MEMORY_OUTPUT_COLOR_ATTACHMENT_BIT = 0x00000004,
+ VK_MEMORY_OUTPUT_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000008,
+ VK_MEMORY_OUTPUT_TRANSFER_BIT = 0x00000010,
+} VkMemoryOutputFlagBits;
+typedef VkFlags VkMemoryOutputFlags;
+
+typedef enum {
+ VK_MEMORY_INPUT_HOST_READ_BIT = 0x00000001,
+ VK_MEMORY_INPUT_INDIRECT_COMMAND_BIT = 0x00000002,
+ VK_MEMORY_INPUT_INDEX_FETCH_BIT = 0x00000004,
+ VK_MEMORY_INPUT_VERTEX_ATTRIBUTE_FETCH_BIT = 0x00000008,
+ VK_MEMORY_INPUT_UNIFORM_READ_BIT = 0x00000010,
+ VK_MEMORY_INPUT_SHADER_READ_BIT = 0x00000020,
+ VK_MEMORY_INPUT_COLOR_ATTACHMENT_BIT = 0x00000040,
+ VK_MEMORY_INPUT_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000080,
+ VK_MEMORY_INPUT_INPUT_ATTACHMENT_BIT = 0x00000100,
+ VK_MEMORY_INPUT_TRANSFER_BIT = 0x00000200,
+} VkMemoryInputFlagBits;
+typedef VkFlags VkMemoryInputFlags;
+
+typedef enum {
+ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT = 0x00000001,
+ VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT = 0x00000002,
+ VK_PIPELINE_STAGE_VERTEX_INPUT_BIT = 0x00000004,
+ VK_PIPELINE_STAGE_VERTEX_SHADER_BIT = 0x00000008,
+ VK_PIPELINE_STAGE_TESS_CONTROL_SHADER_BIT = 0x00000010,
+ VK_PIPELINE_STAGE_TESS_EVALUATION_SHADER_BIT = 0x00000020,
+ VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT = 0x00000040,
+ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT = 0x00000080,
+ VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT = 0x00000100,
+ VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT = 0x00000200,
+ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT = 0x00000400,
+ VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT = 0x00000800,
+ VK_PIPELINE_STAGE_TRANSFER_BIT = 0x00001000,
+ VK_PIPELINE_STAGE_TRANSITION_BIT = 0x00002000,
+ VK_PIPELINE_STAGE_HOST_BIT = 0x00004000,
+ VK_PIPELINE_STAGE_ALL_GRAPHICS = 0x000007FF,
+ VK_PIPELINE_STAGE_ALL_GPU_COMMANDS = 0x00003FFF,
+} VkPipelineStageFlagBits;
+typedef VkFlags VkPipelineStageFlags;
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ VkMemoryOutputFlags outputMask;
+ VkMemoryInputFlags inputMask;
+ uint32_t srcQueueFamilyIndex;
+ uint32_t destQueueFamilyIndex;
+ VkBuffer buffer;
+ VkDeviceSize offset;
+ VkDeviceSize size;
+} VkBufferMemoryBarrier;
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ VkMemoryOutputFlags outputMask;
+ VkMemoryInputFlags inputMask;
+ VkImageLayout oldLayout;
+ VkImageLayout newLayout;
+ uint32_t srcQueueFamilyIndex;
+ uint32_t destQueueFamilyIndex;
+ VkImage image;
+ VkImageSubresourceRange subresourceRange;
+} VkImageMemoryBarrier;
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ VkMemoryOutputFlags outputMask;
+ VkMemoryInputFlags inputMask;
+} VkMemoryBarrier;
+
+void VKAPI vkCmdPipelineBarrier(
+ VkCmdBuffer cmdBuffer,
+ VkPipelineStageFlags srcStageMask,
+ VkPipelineStageFlags destStageMask,
+ VkBool32 byRegion,
+ uint32_t memBarrierCount,
+ const void* const* ppMemBarriers);
+
+// \note vkCmdWaitEvents includes memory barriers as well
+----
+
+ * Image layout transitions may need special care
+
+Binding memory to objects
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+[source,c]
+----
+VkResult VKAPI vkBindBufferMemory(
+ VkDevice device,
+ VkBuffer buffer,
+ VkDeviceMemory mem,
+ VkDeviceSize memOffset);
+
+VkResult VKAPI vkBindImageMemory(
+ VkDevice device,
+ VkImage image,
+ VkDeviceMemory mem,
+ VkDeviceSize memOffset);
+----
+
+ * Buffers and images only
+ * Straightforward mapping where allocation size matches object size and memOffset = 0
+ * Sub-allocation of larger allocations
+ * Re-binding object to different memory allocation
+ * Binding multiple objects to same or partially overlapping memory ranges
+ ** Aliasing writable resources? Access granularity?
+ * Binding various (supported) types of memory allocations
+
+.Spec issues
+ * When binding multiple objects to same memory, will data in memory be visible for all objects?
+ ** Reinterpretation rules?
+ * Memory contents after re-binding memory to a different object?
+
+Sparse resources
+----------------
+
+Sparse memory resources are treated as separate feature from basic memory management. Details TBD still.
+
+[source,c]
+----
+typedef enum {
+ VK_SPARSE_MEMORY_BIND_REPLICATE_64KIB_BLOCK_BIT = 0x00000001,
+} VkSparseMemoryBindFlagBits;
+typedef VkFlags VkSparseMemoryBindFlags;
+
+typedef struct {
+ VkDeviceSize offset;
+ VkDeviceSize memOffset;
+ VkDeviceMemory mem;
+ VkSparseMemoryBindFlags flags;
+} VkSparseMemoryBindInfo;
+
+VkResult VKAPI vkQueueBindSparseBufferMemory(
+ VkQueue queue,
+ VkBuffer buffer,
+ uint32_t numBindings,
+ const VkSparseMemoryBindInfo* pBindInfo);
+
+VkResult VKAPI vkQueueBindSparseImageOpaqueMemory(
+ VkQueue queue,
+ VkImage image,
+ uint32_t numBindings,
+ const VkSparseMemoryBindInfo* pBindInfo);
+
+// Non-opaque sparse images
+
+typedef enum {
+ VK_SPARSE_IMAGE_FMT_SINGLE_MIPTAIL_BIT = 0x00000001,
+ VK_SPARSE_IMAGE_FMT_ALIGNED_MIP_SIZE_BIT = 0x00000002,
+ VK_SPARSE_IMAGE_FMT_NONSTD_BLOCK_SIZE_BIT = 0x00000004,
+} VkSparseImageFormatFlagBits;
+typedef VkFlags VkSparseImageFormatFlags;
+
+typedef struct {
+ VkImageAspect aspect;
+ VkExtent3D imageGranularity;
+ VkSparseImageFormatFlags flags;
+} VkSparseImageFormatProperties;
+
+VkResult VKAPI vkGetPhysicalDeviceSparseImageFormatProperties(
+ VkPhysicalDevice physicalDevice,
+ VkFormat format,
+ VkImageType type,
+ uint32_t samples,
+ VkImageUsageFlags usage,
+ VkImageTiling tiling,
+ uint32_t* pNumProperties,
+ VkSparseImageFormatProperties* pProperties);
+
+typedef struct {
+ VkSparseImageFormatProperties formatProps;
+ uint32_t imageMipTailStartLOD;
+ VkDeviceSize imageMipTailSize;
+ VkDeviceSize imageMipTailOffset;
+ VkDeviceSize imageMipTailStride;
+} VkSparseImageMemoryRequirements;
+
+VkResult VKAPI vkGetImageSparseMemoryRequirements(
+ VkDevice device,
+ VkImage image,
+ uint32_t* pNumRequirements,
+ VkSparseImageMemoryRequirements* pSparseMemoryRequirements);
+
+typedef struct {
+ VkImageSubresource subresource;
+ VkOffset3D offset;
+ VkExtent3D extent;
+ VkDeviceSize memOffset;
+ VkDeviceMemory mem;
+ VkSparseMemoryBindFlags flags;
+} VkSparseImageMemoryBindInfo;
+
+VkResult VKAPI vkQueueBindSparseImageMemory(
+ VkQueue queue,
+ VkImage image,
+ uint32_t numBindings,
+ const VkSparseImageMemoryBindInfo* pBindInfo);
+----
+
+Binding model
+-------------
+
+The objective of the binding model tests is to verify:
+
+ * All valid descriptor sets can be created
+ * Accessing resources from shaders using various layouts
+ * Descriptor updates
+ * Descriptor set chaining
+ * Descriptor set limits
+
+As a necessary side effect, the tests will provide coverage for allocating and accessing all types of resources from all shader stages.
+
+Descriptor set functions
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+[source,c]
+----
+// DescriptorSetLayout
+
+typedef struct {
+ VkDescriptorType descriptorType;
+ uint32_t arraySize;
+ VkShaderStageFlags stageFlags;
+ const VkSampler* pImmutableSamplers;
+} VkDescriptorSetLayoutBinding;
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t count;
+ const VkDescriptorSetLayoutBinding* pBinding;
+} VkDescriptorSetLayoutCreateInfo;
+
+VkResult VKAPI vkCreateDescriptorSetLayout(
+ VkDevice device,
+ const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
+ VkDescriptorSetLayout* pSetLayout);
+
+// DescriptorPool
+
+typedef struct {
+ VkDescriptorType type;
+ uint32_t count;
+} VkDescriptorTypeCount;
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t count;
+ const VkDescriptorTypeCount* pTypeCount;
+} VkDescriptorPoolCreateInfo;
+
+VkResult VKAPI vkCreateDescriptorPool(
+ VkDevice device,
+ VkDescriptorPoolUsage poolUsage,
+ uint32_t maxSets,
+ const VkDescriptorPoolCreateInfo* pCreateInfo,
+ VkDescriptorPool* pDescriptorPool);
+
+VkResult VKAPI vkResetDescriptorPool(
+ VkDevice device,
+ VkDescriptorPool descriptorPool);
+
+// DescriptorSet
+
+typedef struct {
+ VkBufferView bufferView;
+ VkSampler sampler;
+ VkImageView imageView;
+ VkAttachmentView attachmentView;
+ VkImageLayout imageLayout;
+} VkDescriptorInfo;
+
+VkResult VKAPI vkAllocDescriptorSets(
+ VkDevice device,
+ VkDescriptorPool descriptorPool,
+ VkDescriptorSetUsage setUsage,
+ uint32_t count,
+ const VkDescriptorSetLayout* pSetLayouts,
+ VkDescriptorSet* pDescriptorSets,
+ uint32_t* pCount);
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ VkDescriptorSet destSet;
+ uint32_t destBinding;
+ uint32_t destArrayElement;
+ uint32_t count;
+ VkDescriptorType descriptorType;
+ const VkDescriptorInfo* pDescriptors;
+} VkWriteDescriptorSet;
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ VkDescriptorSet srcSet;
+ uint32_t srcBinding;
+ uint32_t srcArrayElement;
+ VkDescriptorSet destSet;
+ uint32_t destBinding;
+ uint32_t destArrayElement;
+ uint32_t count;
+} VkCopyDescriptorSet;
+
+VkResult VKAPI vkUpdateDescriptorSets(
+ VkDevice device,
+ uint32_t writeCount,
+ const VkWriteDescriptorSet* pDescriptorWrites,
+ uint32_t copyCount,
+ const VkCopyDescriptorSet* pDescriptorCopies);
+----
+
+Pipeline layout functions
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Pipeline layouts will be covered mostly by tests that use various layouts, but in addition some corner-case tests are needed:
+
+ * Creating empty layouts for shaders that don't use any resources
+ ** For example: vertex data generated with +gl_VertexID+ only
+
+[source,c]
+----
+typedef struct {
+ VkShaderStageFlags stageFlags;
+ uint32_t start;
+ uint32_t length;
+} VkPushConstantRange;
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t descriptorSetCount;
+ const VkDescriptorSetLayout* pSetLayouts;
+ uint32_t pushConstantRangeCount;
+ const VkPushConstantRange* pPushConstantRanges;
+} VkPipelineLayoutCreateInfo;
+
+VkResult VKAPI vkCreatePipelineLayout(
+ VkDevice device,
+ const VkPipelineLayoutCreateInfo* pCreateInfo,
+ VkPipelineLayout* pPipelineLayout);
+----
+
+Multipass
+---------
+
+Multipass tests will verify:
+
+ * Various possible multipass data flow configurations
+ ** Target formats, number of targets, load, store, resolve, dependencies, ...
+ ** Exhaustive tests for selected dimensions
+ ** Randomized tests
+ * Interaction with other features
+ ** Blending
+ ** Tessellation, geometry shaders (esp. massive geometry expansion)
+ ** Barriers that may cause tiler flushes
+ ** Queries
+ * Large passes that may require tiler flushes
+
+[source,c]
+----
+// Framebuffer
+
+typedef struct {
+ VkAttachmentView view;
+ VkImageLayout layout;
+} VkAttachmentBindInfo;
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ VkRenderPass renderPass;
+ uint32_t attachmentCount;
+ const VkAttachmentBindInfo* pAttachments;
+ uint32_t width;
+ uint32_t height;
+ uint32_t layers;
+} VkFramebufferCreateInfo;
+
+VkResult VKAPI vkCreateFramebuffer(
+ VkDevice device,
+ const VkFramebufferCreateInfo* pCreateInfo,
+ VkFramebuffer* pFramebuffer);
+
+// RenderPass
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ VkFormat format;
+ uint32_t samples;
+ VkAttachmentLoadOp loadOp;
+ VkAttachmentStoreOp storeOp;
+ VkAttachmentLoadOp stencilLoadOp;
+ VkAttachmentStoreOp stencilStoreOp;
+ VkImageLayout initialLayout;
+ VkImageLayout finalLayout;
+} VkAttachmentDescription;
+
+typedef struct {
+ uint32_t attachment;
+ VkImageLayout layout;
+} VkAttachmentReference;
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineBindPoint pipelineBindPoint;
+ VkSubpassDescriptionFlags flags;
+ uint32_t inputCount;
+ const VkAttachmentReference* inputAttachments;
+ uint32_t colorCount;
+ const VkAttachmentReference* colorAttachments;
+ const VkAttachmentReference* resolveAttachments;
+ VkAttachmentReference depthStencilAttachment;
+ uint32_t preserveCount;
+ const VkAttachmentReference* preserveAttachments;
+} VkSubpassDescription;
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t srcSubpass;
+ uint32_t destSubpass;
+ VkPipelineStageFlags srcStageMask;
+ VkPipelineStageFlags destStageMask;
+ VkMemoryOutputFlags outputMask;
+ VkMemoryInputFlags inputMask;
+ VkBool32 byRegion;
+} VkSubpassDependency;
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t attachmentCount;
+ const VkAttachmentDescription* pAttachments;
+ uint32_t subpassCount;
+ const VkSubpassDescription* pSubpasses;
+ uint32_t dependencyCount;
+ const VkSubpassDependency* pDependencies;
+} VkRenderPassCreateInfo;
+
+VkResult VKAPI vkCreateRenderPass(
+ VkDevice device,
+ const VkRenderPassCreateInfo* pCreateInfo,
+ VkRenderPass* pRenderPass);
+
+VkResult VKAPI vkGetRenderAreaGranularity(
+ VkDevice device,
+ VkRenderPass renderPass,
+ VkExtent2D* pGranularity);
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ VkRenderPass renderPass;
+ VkFramebuffer framebuffer;
+ VkRect2D renderArea;
+ uint32_t attachmentCount;
+ const VkClearValue* pAttachmentClearValues;
+} VkRenderPassBeginInfo;
+
+typedef enum {
+ VK_RENDER_PASS_CONTENTS_INLINE = 0,
+ VK_RENDER_PASS_CONTENTS_SECONDARY_CMD_BUFFERS = 1,
+ VK_RENDER_PASS_CONTENTS_BEGIN_RANGE = VK_RENDER_PASS_CONTENTS_INLINE,
+ VK_RENDER_PASS_CONTENTS_END_RANGE = VK_RENDER_PASS_CONTENTS_SECONDARY_CMD_BUFFERS,
+ VK_RENDER_PASS_CONTENTS_NUM = (VK_RENDER_PASS_CONTENTS_SECONDARY_CMD_BUFFERS - VK_RENDER_PASS_CONTENTS_INLINE + 1),
+ VK_RENDER_PASS_CONTENTS_MAX_ENUM = 0x7FFFFFFF
+} VkRenderPassContents;
+
+void VKAPI vkCmdBeginRenderPass(
+ VkCmdBuffer cmdBuffer,
+ const VkRenderPassBeginInfo* pRenderPassBegin,
+ VkRenderPassContents contents);
+
+void VKAPI vkCmdNextSubpass(
+ VkCmdBuffer cmdBuffer,
+ VkRenderPassContents contents);
+
+void VKAPI vkCmdEndRenderPass(
+ VkCmdBuffer cmdBuffer);
+----
+
+Device initialization
+---------------------
+
+Device initialization tests verify that all reported devices can be created, with various possible configurations.
+
+[source,c]
+----
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ const char* pAppName;
+ uint32_t appVersion;
+ const char* pEngineName;
+ uint32_t engineVersion;
+ uint32_t apiVersion;
+} VkApplicationInfo;
+
+typedef void* (VKAPI *PFN_vkAllocFunction)(
+ void* pUserData,
+ size_t size,
+ size_t alignment,
+ VkSystemAllocType allocType);
+
+typedef void (VKAPI *PFN_vkFreeFunction)(
+ void* pUserData,
+ void* pMem);
+
+typedef struct {
+ void* pUserData;
+ PFN_vkAllocFunction pfnAlloc;
+ PFN_vkFreeFunction pfnFree;
+} VkAllocCallbacks;
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ const VkApplicationInfo* pAppInfo;
+ const VkAllocCallbacks* pAllocCb;
+ uint32_t layerCount;
+ const char*const* ppEnabledLayerNames;
+ uint32_t extensionCount;
+ const char*const* ppEnabledExtensionNames;
+} VkInstanceCreateInfo;
+
+VkResult VKAPI vkCreateInstance(
+ const VkInstanceCreateInfo* pCreateInfo,
+ VkInstance* pInstance);
+----
+
+ - +VkApplicationInfo+ parameters
+ * Arbitrary +pAppName+ / +pEngineName+ (spaces, utf-8, ...)
+ * +pAppName+ / +pEngineName+ = NULL?
+ * +appVersion+ / +engineVersion+ for 0, ~0, couple of values
+ * Valid +apiVersion+
+ * Invalid +apiVersion+ (expected to fail?)
+ - +VkAllocCallbacks+
+ * Want to be able to run all tests with and without callbacks?
+ ** See discussion about default device in framework section
+ * Custom allocators that provide guardbands and check them at free
+ * Override malloc / free and verify that driver doesn't call if callbacks provided
+ ** As part of object mgmt tests
+ * Must be inherited to all devices created from instance
+ - +VkInstanceCreateInfo+
+ * Empty extension list
+ * Unsupported extensions (expect VK_UNSUPPORTED)
+ * Various combinations of supported extensions
+ ** Any dependencies between extensions (enabling Y requires enabling X)?
+
+.Spec issues
+ * Only VkPhysicalDevice is passed to vkCreateDevice, ICD-specific magic needed for passing callbacks down to VkDevice instance
+
+[source,c]
+----
+typedef struct {
+ VkBool32 robustBufferAccess;
+ VkBool32 fullDrawIndexUint32;
+ VkBool32 imageCubeArray;
+ VkBool32 independentBlend;
+ VkBool32 geometryShader;
+ VkBool32 tessellationShader;
+ VkBool32 sampleRateShading;
+ VkBool32 dualSourceBlend;
+ VkBool32 logicOp;
+ VkBool32 instancedDrawIndirect;
+ VkBool32 depthClip;
+ VkBool32 depthBiasClamp;
+ VkBool32 fillModeNonSolid;
+ VkBool32 depthBounds;
+ VkBool32 wideLines;
+ VkBool32 largePoints;
+ VkBool32 textureCompressionETC2;
+ VkBool32 textureCompressionASTC_LDR;
+ VkBool32 textureCompressionBC;
+ VkBool32 pipelineStatisticsQuery;
+ VkBool32 vertexSideEffects;
+ VkBool32 tessellationSideEffects;
+ VkBool32 geometrySideEffects;
+ VkBool32 fragmentSideEffects;
+ VkBool32 shaderTessellationPointSize;
+ VkBool32 shaderGeometryPointSize;
+ VkBool32 shaderTextureGatherExtended;
+ VkBool32 shaderStorageImageExtendedFormats;
+ VkBool32 shaderStorageImageMultisample;
+ VkBool32 shaderStorageBufferArrayConstantIndexing;
+ VkBool32 shaderStorageImageArrayConstantIndexing;
+ VkBool32 shaderUniformBufferArrayDynamicIndexing;
+ VkBool32 shaderSampledImageArrayDynamicIndexing;
+ VkBool32 shaderStorageBufferArrayDynamicIndexing;
+ VkBool32 shaderStorageImageArrayDynamicIndexing;
+ VkBool32 shaderClipDistance;
+ VkBool32 shaderCullDistance;
+ VkBool32 shaderFloat64;
+ VkBool32 shaderInt64;
+ VkBool32 shaderFloat16;
+ VkBool32 shaderInt16;
+ VkBool32 shaderResourceResidency;
+ VkBool32 shaderResourceMinLOD;
+ VkBool32 sparse;
+ VkBool32 sparseResidencyBuffer;
+ VkBool32 sparseResidencyImage2D;
+ VkBool32 sparseResidencyImage3D;
+ VkBool32 sparseResidency2Samples;
+ VkBool32 sparseResidency4Samples;
+ VkBool32 sparseResidency8Samples;
+ VkBool32 sparseResidency16Samples;
+ VkBool32 sparseResidencyStandard2DBlockShape;
+ VkBool32 sparseResidencyStandard2DMSBlockShape;
+ VkBool32 sparseResidencyStandard3DBlockShape;
+ VkBool32 sparseResidencyAlignedMipSize;
+ VkBool32 sparseResidencyNonResident;
+ VkBool32 sparseResidencyNonResidentStrict;
+ VkBool32 sparseResidencyAliased;
+} VkPhysicalDeviceFeatures;
+
+typedef struct {
+ uint32_t queueFamilyIndex;
+ uint32_t queueCount;
+} VkDeviceQueueCreateInfo;
+
+typedef enum {
+ VK_DEVICE_CREATE_VALIDATION_BIT = 0x00000001,
+} VkDeviceCreateFlagBits;
+typedef VkFlags VkDeviceCreateFlags;
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t queueRecordCount;
+ const VkDeviceQueueCreateInfo* pRequestedQueues;
+ uint32_t layerCount;
+ const char*const* ppEnabledLayerNames;
+ uint32_t extensionCount;
+ const char*const* ppEnabledExtensionNames;
+ const VkPhysicalDeviceFeatures* pEnabledFeatures;
+ VkDeviceCreateFlags flags;
+} VkDeviceCreateInfo;
+
+VkResult VKAPI vkCreateDevice(
+ VkPhysicalDevice physicalDevice,
+ const VkDeviceCreateInfo* pCreateInfo,
+ VkDevice* pDevice);
+----
+
+ * Creating multiple devices from single physical device
+ * Different queue configurations
+ ** Combinations of supported node indexes
+ ** Use of all queues simultaneously for various operations
+ ** Various queue counts
+ * Various extension combinations
+ * Flags
+ ** Enabling validation (see spec issues)
+ ** VK_DEVICE_CREATE_MULTI_DEVICE_IQ_MATCH_BIT not relevant for Android
+
+.Spec issues
+ * Can same queue node index used multiple times in +pRequestedQueues+ list?
+ * VK_DEVICE_CREATE_VALIDATION_BIT vs. layers
+
+Queue functions
+---------------
+
+Queue functions (one currently) will have a lot of indicental coverage from other tests, so only targeted corner-case tests are needed:
+
+ * +cmdBufferCount+ = 0
+ * Submitting empty VkCmdBuffer
+
+[source,c]
+----
+VkResult VKAPI vkQueueSubmit(
+ VkQueue queue,
+ uint32_t cmdBufferCount,
+ const VkCmdBuffer* pCmdBuffers,
+ VkFence fence);
+----
+
+.Spec issues
+ * Can +fence+ be +NULL+ if app doesn't need it?
+
+Synchronization
+---------------
+
+Synchronization tests will verify that all execution ordering primitives provided by the API will function as expected. Testing scheduling and synchronization robustness will require generating non-trivial workloads and possibly randomization to reveal potential issues.
+
+[source,c]
+----
+VkResult VKAPI vkQueueWaitIdle(
+ VkQueue queue);
+
+VkResult VKAPI vkDeviceWaitIdle(
+ VkDevice device);
+----
+
+ * Verify that all sync objects signaled after *WaitIdle() returns
+ ** Fences (vkGetFenceStatus)
+ ** Events (vkEventGetStatus)
+ ** No way to query semaphore status?
+ * Threads blocking at vkWaitForFences() must be resumed
+ * Various amounts of work queued (from nothing to large command buffers)
+ * vkDeviceWaitIdle() concurrently with commands that submit more work
+ * all types of work
+
+Fences
+~~~~~~
+
+[source,c]
+----
+typedef enum {
+ VK_FENCE_CREATE_SIGNALED_BIT = 0x00000001,
+} VkFenceCreateFlagBits;
+typedef VkFlags VkFenceCreateFlags;
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ VkFenceCreateFlags flags;
+} VkFenceCreateInfo;
+
+VkResult VKAPI vkCreateFence(
+ VkDevice device,
+ const VkFenceCreateInfo* pCreateInfo,
+ VkFence* pFence);
+
+VkResult VKAPI vkResetFences(
+ VkDevice device,
+ uint32_t fenceCount,
+ const VkFence* pFences);
+
+VkResult VKAPI vkGetFenceStatus(
+ VkDevice device,
+ VkFence fence);
+
+VkResult VKAPI vkWaitForFences(
+ VkDevice device,
+ uint32_t fenceCount,
+ const VkFence* pFences,
+ VkBool32 waitAll,
+ uint64_t timeout);
+----
+
+ * Basic waiting on fences
+ ** All types of commands
+ ** Waiting on a different thread than the thread that submitted the work
+ * Reusing fences (vkResetFences)
+ * Waiting on a fence / querying status of a fence before it has been submitted to be signaled
+ * Waiting on a fence / querying status of a fence has just been created with CREATE_SIGNALED_BIT
+ ** Reuse in different queue
+ ** Different queues
+
+.Spec issues
+ * Using same fence in multiple vkQueueSubmit calls without waiting/resetting in between
+ ** Completion of first cmdbuf will reset fence and others won't do anything?
+ * Waiting on same fence from multiple threads?
+
+Semaphores
+~~~~~~~~~~
+
+[source,c]
+----
+typedef VkFlags VkSemaphoreCreateFlags;
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ VkSemaphoreCreateFlags flags;
+} VkSemaphoreCreateInfo;
+
+VkResult VKAPI vkCreateSemaphore(
+ VkDevice device,
+ const VkSemaphoreCreateInfo* pCreateInfo,
+ VkSemaphore* pSemaphore);
+
+VkResult VKAPI vkQueueSignalSemaphore(
+ VkQueue queue,
+ VkSemaphore semaphore);
+
+VkResult VKAPI vkQueueWaitSemaphore(
+ VkQueue queue,
+ VkSemaphore semaphore);
+----
+
+ * All types of commands waiting & signaling semaphore
+ * Cross-queue semaphores
+ * Queuing wait on initially signaled semaphore
+ * Queuing wait immediately after queuing signaling
+ * vkQueueWaitIdle & vkDeviceWaitIdle waiting on semaphore
+ * Multiple queues waiting on same semaphore
+
+NOTE: Semaphores might change; counting is causing problems for some IHVs.
+
+Events
+~~~~~~
+
+[source,c]
+----
+typedef VkFlags VkEventCreateFlags;
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ VkEventCreateFlags flags;
+} VkEventCreateInfo;
+
+VkResult VKAPI vkCreateEvent(
+ VkDevice device,
+ const VkEventCreateInfo* pCreateInfo,
+ VkEvent* pEvent);
+
+VkResult VKAPI vkGetEventStatus(
+ VkDevice device,
+ VkEvent event);
+
+VkResult VKAPI vkSetEvent(
+ VkDevice device,
+ VkEvent event);
+
+VkResult VKAPI vkResetEvent(
+ VkDevice device,
+ VkEvent event);
+
+void VKAPI vkCmdSetEvent(
+ VkCmdBuffer cmdBuffer,
+ VkEvent event,
+ VkPipelineStageFlags stageMask);
+
+void VKAPI vkCmdResetEvent(
+ VkCmdBuffer cmdBuffer,
+ VkEvent event,
+ VkPipelineStageFlags stageMask);
+
+void VKAPI vkCmdWaitEvents(
+ VkCmdBuffer cmdBuffer,
+ uint32_t eventCount,
+ const VkEvent* pEvents,
+ VkPipelineStageFlags srcStageMask,
+ VkPipelineStageFlags destStageMask,
+ uint32_t memBarrierCount,
+ const void* const* ppMemBarriers);
+----
+
+ * All types of work waiting on all types of events
+ ** Including signaling from CPU side (vkSetEvent)
+ ** Memory barrier
+ * Polling event status (vkGetEventStatus)
+ * Memory barriers (see also GPU cache control)
+ * Corner-cases:
+ ** Re-setting event before it has been signaled
+ ** Polling status of event concurrently with signaling it or re-setting it from another thread
+ ** Multiple commands (maybe multiple queues as well) setting same event
+ *** Presumably first set will take effect, rest have no effect before event is re-set
+
+Pipeline queries
+----------------
+
+Pipeline query test details TBD. These are of lower priority initially.
+
+NOTE: Currently contains only exact occlusion query as mandatory. Might be problematic for some, and may change?
+
+[source,c]
+----
+typedef enum {
+ VK_QUERY_TYPE_OCCLUSION = 0,
+ VK_QUERY_TYPE_PIPELINE_STATISTICS = 1,
+ VK_QUERY_TYPE_BEGIN_RANGE = VK_QUERY_TYPE_OCCLUSION,
+ VK_QUERY_TYPE_END_RANGE = VK_QUERY_TYPE_PIPELINE_STATISTICS,
+ VK_QUERY_TYPE_NUM = (VK_QUERY_TYPE_PIPELINE_STATISTICS - VK_QUERY_TYPE_OCCLUSION + 1),
+ VK_QUERY_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkQueryType;
+
+typedef enum {
+ VK_QUERY_PIPELINE_STATISTIC_IA_VERTICES_BIT = 0x00000001,
+ VK_QUERY_PIPELINE_STATISTIC_IA_PRIMITIVES_BIT = 0x00000002,
+ VK_QUERY_PIPELINE_STATISTIC_VS_INVOCATIONS_BIT = 0x00000004,
+ VK_QUERY_PIPELINE_STATISTIC_GS_INVOCATIONS_BIT = 0x00000008,
+ VK_QUERY_PIPELINE_STATISTIC_GS_PRIMITIVES_BIT = 0x00000010,
+ VK_QUERY_PIPELINE_STATISTIC_C_INVOCATIONS_BIT = 0x00000020,
+ VK_QUERY_PIPELINE_STATISTIC_C_PRIMITIVES_BIT = 0x00000040,
+ VK_QUERY_PIPELINE_STATISTIC_FS_INVOCATIONS_BIT = 0x00000080,
+ VK_QUERY_PIPELINE_STATISTIC_TCS_PATCHES_BIT = 0x00000100,
+ VK_QUERY_PIPELINE_STATISTIC_TES_INVOCATIONS_BIT = 0x00000200,
+ VK_QUERY_PIPELINE_STATISTIC_CS_INVOCATIONS_BIT = 0x00000400,
+} VkQueryPipelineStatisticFlagBits;
+typedef VkFlags VkQueryPipelineStatisticFlags;
+
+typedef enum {
+ VK_QUERY_RESULT_DEFAULT = 0,
+ VK_QUERY_RESULT_64_BIT = 0x00000001,
+ VK_QUERY_RESULT_WAIT_BIT = 0x00000002,
+ VK_QUERY_RESULT_WITH_AVAILABILITY_BIT = 0x00000004,
+ VK_QUERY_RESULT_PARTIAL_BIT = 0x00000008,
+} VkQueryResultFlagBits;
+typedef VkFlags VkQueryResultFlags;
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ VkQueryType queryType;
+ uint32_t slots;
+ VkQueryPipelineStatisticFlags pipelineStatistics;
+} VkQueryPoolCreateInfo;
+
+VkResult VKAPI vkCreateQueryPool(
+ VkDevice device,
+ const VkQueryPoolCreateInfo* pCreateInfo,
+ VkQueryPool* pQueryPool);
+
+VkResult VKAPI vkGetQueryPoolResults(
+ VkDevice device,
+ VkQueryPool queryPool,
+ uint32_t startQuery,
+ uint32_t queryCount,
+ size_t* pDataSize,
+ void* pData,
+ VkQueryResultFlags flags);
+
+void VKAPI vkCmdBeginQuery(
+ VkCmdBuffer cmdBuffer,
+ VkQueryPool queryPool,
+ uint32_t slot,
+ VkQueryControlFlags flags);
+
+void VKAPI vkCmdEndQuery(
+ VkCmdBuffer cmdBuffer,
+ VkQueryPool queryPool,
+ uint32_t slot);
+
+void VKAPI vkCmdResetQueryPool(
+ VkCmdBuffer cmdBuffer,
+ VkQueryPool queryPool,
+ uint32_t startQuery,
+ uint32_t queryCount);
+
+void VKAPI vkCmdCopyQueryPoolResults(
+ VkCmdBuffer cmdBuffer,
+ VkQueryPool queryPool,
+ uint32_t startQuery,
+ uint32_t queryCount,
+ VkBuffer destBuffer,
+ VkDeviceSize destOffset,
+ VkDeviceSize destStride,
+ VkQueryResultFlags flags);
+----
+
+Buffers
+-------
+
+Buffers will have a lot of coverage from memory management and access tests. Targeted buffer tests need to verify that various corner-cases and more exotic configurations work as expected.
+
+[source,c]
+----
+typedef enum {
+ VK_BUFFER_USAGE_TRANSFER_SOURCE_BIT = 0x00000001,
+ VK_BUFFER_USAGE_TRANSFER_DESTINATION_BIT = 0x00000002,
+ VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT = 0x00000004,
+ VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT = 0x00000008,
+ VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT = 0x00000010,
+ VK_BUFFER_USAGE_STORAGE_BUFFER_BIT = 0x00000020,
+ VK_BUFFER_USAGE_INDEX_BUFFER_BIT = 0x00000040,
+ VK_BUFFER_USAGE_VERTEX_BUFFER_BIT = 0x00000080,
+ VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT = 0x00000100,
+} VkBufferUsageFlagBits;
+typedef VkFlags VkBufferUsageFlags;
+
+typedef enum {
+ VK_BUFFER_CREATE_SPARSE_BIT = 0x00000001,
+ VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT = 0x00000002,
+ VK_BUFFER_CREATE_SPARSE_ALIASED_BIT = 0x00000004,
+} VkBufferCreateFlagBits;
+typedef VkFlags VkBufferCreateFlags;
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ VkDeviceSize size;
+ VkBufferUsageFlags usage;
+ VkBufferCreateFlags flags;
+ VkSharingMode sharingMode;
+ uint32_t queueFamilyCount;
+ const uint32_t* pQueueFamilyIndices;
+} VkBufferCreateInfo;
+
+VkResult VKAPI vkCreateBuffer(
+ VkDevice device,
+ const VkBufferCreateInfo* pCreateInfo,
+ VkBuffer* pBuffer);
+----
+
+ * All combinations of create and usage flags work
+ ** There are total 511 combinations of usage flags and 7 combinations of create flags
+ * Buffers of various sizes can be created and they report sensible memory requirements
+ ** Test with different sizes:
+ *** 0 Byte
+ *** 1181 Byte
+ *** 15991 Byte
+ *** 16 kByte
+ *** Device limit (maxTexelBufferSize)
+ * Sparse buffers: very large (limit TBD) buffers can be created
+
+[source,c]
+----
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ VkBuffer buffer;
+ VkFormat format;
+ VkDeviceSize offset;
+ VkDeviceSize range;
+} VkBufferViewCreateInfo;
+
+VkResult VKAPI vkCreateBufferView(
+ VkDevice device,
+ const VkBufferViewCreateInfo* pCreateInfo,
+ VkBufferView* pView);
+----
+
+ * Buffer views of all (valid) types and formats can be created from all (compatible) buffers
+ ** There are 2 buffer types and 173 different formats.
+ * Various view sizes
+ ** Complete buffer
+ ** Partial buffer
+ * View can be created before and after attaching memory to buffer
+ ** 2 tests for each bufferView
+ * Changing memory binding makes memory contents visible in already created views
+ ** Concurrently changing memory binding and creating views
+
+.Spec issues
+ * Alignment or size requirements for buffer views?
+
+Images
+------
+
+Like buffers, images will have significant coverage from other test groups that focus on various ways to access image data. Additional coverage not provided by those tests will be included in this feature group.
+
+Image functions
+~~~~~~~~~~~~~~~
+
+.Spec issues
+ * +VK_IMAGE_USAGE_GENERAL+?
+
+[source,c]
+----
+typedef enum {
+ VK_IMAGE_TYPE_1D = 0,
+ VK_IMAGE_TYPE_2D = 1,
+ VK_IMAGE_TYPE_3D = 2,
+ VK_IMAGE_TYPE_BEGIN_RANGE = VK_IMAGE_TYPE_1D,
+ VK_IMAGE_TYPE_END_RANGE = VK_IMAGE_TYPE_3D,
+ VK_IMAGE_TYPE_NUM = (VK_IMAGE_TYPE_3D - VK_IMAGE_TYPE_1D + 1),
+ VK_IMAGE_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkImageType;
+
+typedef enum {
+ VK_IMAGE_TILING_LINEAR = 0,
+ VK_IMAGE_TILING_OPTIMAL = 1,
+ VK_IMAGE_TILING_BEGIN_RANGE = VK_IMAGE_TILING_LINEAR,
+ VK_IMAGE_TILING_END_RANGE = VK_IMAGE_TILING_OPTIMAL,
+ VK_IMAGE_TILING_NUM = (VK_IMAGE_TILING_OPTIMAL - VK_IMAGE_TILING_LINEAR + 1),
+ VK_IMAGE_TILING_MAX_ENUM = 0x7FFFFFFF
+} VkImageTiling;
+
+typedef enum {
+ VK_IMAGE_USAGE_GENERAL = 0,
+ VK_IMAGE_USAGE_TRANSFER_SOURCE_BIT = 0x00000001,
+ VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT = 0x00000002,
+ VK_IMAGE_USAGE_SAMPLED_BIT = 0x00000004,
+ VK_IMAGE_USAGE_STORAGE_BIT = 0x00000008,
+ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT = 0x00000010,
+ VK_IMAGE_USAGE_DEPTH_STENCIL_BIT = 0x00000020,
+ VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT = 0x00000040,
+ VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT = 0x00000080,
+} VkImageUsageFlagBits;
+typedef VkFlags VkImageUsageFlags;
+
+typedef enum {
+ VK_IMAGE_CREATE_SPARSE_BIT = 0x00000001,
+ VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT = 0x00000002,
+ VK_IMAGE_CREATE_SPARSE_ALIASED_BIT = 0x00000004,
+ VK_IMAGE_CREATE_INVARIANT_DATA_BIT = 0x00000008,
+ VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT = 0x00000010,
+ VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT = 0x00000020,
+} VkImageCreateFlagBits;
+typedef VkFlags VkImageCreateFlags;
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ VkImageType imageType;
+ VkFormat format;
+ VkExtent3D extent;
+ uint32_t mipLevels;
+ uint32_t arraySize;
+ uint32_t samples;
+ VkImageTiling tiling;
+ VkImageUsageFlags usage;
+ VkImageCreateFlags flags;
+ VkSharingMode sharingMode;
+ uint32_t queueFamilyCount;
+ const uint32_t* pQueueFamilyIndices;
+} VkImageCreateInfo;
+
+VkResult VKAPI vkCreateImage(
+ VkDevice device,
+ const VkImageCreateInfo* pCreateInfo,
+ VkImage* pImage);
+
+VkResult VKAPI vkGetImageSubresourceLayout(
+ VkDevice device,
+ VkImage image,
+ const VkImageSubresource* pSubresource,
+ VkSubresourceLayout* pLayout);
+----
+
+ * All valid and supported combinations of image parameters
+ ** Sampling verification with nearest only (other modes will be covered separately)
+ * Various image sizes
+ * Linear-layout images & writing data from CPU
+ * Copying data between identical opaque-layout images on CPU?
+
+Image view functions
+~~~~~~~~~~~~~~~~~~~~
+
+.Spec issues
+ * What are format compatibility rules?
+ * Can color/depth/stencil attachments to write to image which has different format?
+ ** Can I create DS view of RGBA texture and write to only one component by creating VkDepthStencilView for example?
+ * Image view granularity
+ ** All sub-rects allowed? In all use cases (RTs for example)?
+ * Memory access granularity
+ ** Writing concurrently to different areas of same memory backed by same/different image or view
+
+[source,c]
+----
+typedef struct {
+ VkChannelSwizzle r;
+ VkChannelSwizzle g;
+ VkChannelSwizzle b;
+ VkChannelSwizzle a;
+} VkChannelMapping;
+
+typedef struct {
+ VkImageAspect aspect;
+ uint32_t baseMipLevel;
+ uint32_t mipLevels;
+ uint32_t baseArraySlice;
+ uint32_t arraySize;
+} VkImageSubresourceRange;
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ VkImage image;
+ VkImageViewType viewType;
+ VkFormat format;
+ VkChannelMapping channels;
+ VkImageSubresourceRange subresourceRange;
+} VkImageViewCreateInfo;
+
+VkResult VKAPI vkCreateImageView(
+ VkDevice device,
+ const VkImageViewCreateInfo* pCreateInfo,
+ VkImageView* pView);
+----
+
+ * Image views of all (valid) types and formats can be created from all (compatible) images
+ * Channel swizzles
+ * Depth- and stencil-mode
+ * Different formats
+ * Various view sizes
+ ** Complete image
+ ** Partial image (mip- or array slice)
+ * View can be created before and after attaching memory to image
+ * Changing memory binding makes memory contents visible in already created views
+ ** Concurrently changing memory binding and creating views
+
+[source,c]
+----
+typedef enum {
+ VK_ATTACHMENT_VIEW_CREATE_READ_ONLY_DEPTH_BIT = 0x00000001,
+ VK_ATTACHMENT_VIEW_CREATE_READ_ONLY_STENCIL_BIT = 0x00000002,
+} VkAttachmentViewCreateFlagBits;
+typedef VkFlags VkAttachmentViewCreateFlags;
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ VkImage image;
+ VkFormat format;
+ uint32_t mipLevel;
+ uint32_t baseArraySlice;
+ uint32_t arraySize;
+ VkAttachmentViewCreateFlags flags;
+} VkAttachmentViewCreateInfo;
+
+VkResult VKAPI vkCreateAttachmentView(
+ VkDevice device,
+ const VkAttachmentViewCreateInfo* pCreateInfo,
+ VkAttachmentView* pView);
+----
+
+ * Writing to color/depth/stencil attachments in various view configurations
+ ** Multipass tests will contain some coverage for this
+ ** Image layout
+ ** View size
+ ** Image mip- or array sub-range
+ * +msaaResolveImage+
+ ** TODO What is exactly this?
+
+Shaders
+-------
+
+Shader API test will verify that shader loading functions behave as expected. Verifying that various SPIR-V constructs are accepted and executed correctly however is not an objective; that will be covered more extensively by a separate SPIR-V test set.
+
+[source,c]
+----
+typedef VkFlags VkShaderModuleCreateFlags;
+typedef VkFlags VkShaderCreateFlags;
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ size_t codeSize;
+ const void* pCode;
+ VkShaderModuleCreateFlags flags;
+} VkShaderModuleCreateInfo;
+
+VkResult VKAPI vkCreateShaderModule(
+ VkDevice device,
+ const VkShaderModuleCreateInfo* pCreateInfo,
+ VkShaderModule* pShaderModule);
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ VkShaderModule module;
+ const char* pName;
+ VkShaderCreateFlags flags;
+} VkShaderCreateInfo;
+
+VkResult VKAPI vkCreateShader(
+ VkDevice device,
+ const VkShaderCreateInfo* pCreateInfo,
+ VkShader* pShader);
+----
+
+Pipelines
+---------
+
+Construction
+~~~~~~~~~~~~
+
+Pipeline tests will create various pipelines and verify that rendering results appear to match (resulting HW pipeline is correct). Fixed-function unit corner-cases nor accuracy is verified. It is not possible to exhaustively test all pipeline configurations so tests have to test some areas in isolation and extend coverage with randomized tests.
+
+[source,c]
+----
+typedef enum {
+ VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT = 0x00000001,
+ VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT = 0x00000002,
+ VK_PIPELINE_CREATE_DERIVATIVE_BIT = 0x00000004,
+} VkPipelineCreateFlagBits;
+typedef VkFlags VkPipelineCreateFlags;
+
+typedef struct {
+ uint32_t constantId;
+ size_t size;
+ uint32_t offset;
+} VkSpecializationMapEntry;
+
+typedef struct {
+ uint32_t mapEntryCount;
+ const VkSpecializationMapEntry* pMap;
+ const size_t dataSize;
+ const void* pData;
+} VkSpecializationInfo;
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ VkShaderStage stage;
+ VkShader shader;
+ const VkSpecializationInfo* pSpecializationInfo;
+} VkPipelineShaderStageCreateInfo;
+
+typedef struct {
+ uint32_t binding;
+ uint32_t strideInBytes;
+ VkVertexInputStepRate stepRate;
+} VkVertexInputBindingDescription;
+
+typedef struct {
+ uint32_t location;
+ uint32_t binding;
+ VkFormat format;
+ uint32_t offsetInBytes;
+} VkVertexInputAttributeDescription;
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t bindingCount;
+ const VkVertexInputBindingDescription* pVertexBindingDescriptions;
+ uint32_t attributeCount;
+ const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
+} VkPipelineVertexInputStateCreateInfo;
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ VkPrimitiveTopology topology;
+ VkBool32 primitiveRestartEnable;
+} VkPipelineInputAssemblyStateCreateInfo;
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t patchControlPoints;
+} VkPipelineTessellationStateCreateInfo;
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t viewportCount;
+} VkPipelineViewportStateCreateInfo;
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ VkBool32 depthClipEnable;
+ VkBool32 rasterizerDiscardEnable;
+ VkFillMode fillMode;
+ VkCullMode cullMode;
+ VkFrontFace frontFace;
+} VkPipelineRasterStateCreateInfo;
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t rasterSamples;
+ VkBool32 sampleShadingEnable;
+ float minSampleShading;
+ VkSampleMask sampleMask;
+} VkPipelineMultisampleStateCreateInfo;
+
+typedef struct {
+ VkStencilOp stencilFailOp;
+ VkStencilOp stencilPassOp;
+ VkStencilOp stencilDepthFailOp;
+ VkCompareOp stencilCompareOp;
+} VkStencilOpState;
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ VkBool32 depthTestEnable;
+ VkBool32 depthWriteEnable;
+ VkCompareOp depthCompareOp;
+ VkBool32 depthBoundsEnable;
+ VkBool32 stencilTestEnable;
+ VkStencilOpState front;
+ VkStencilOpState back;
+} VkPipelineDepthStencilStateCreateInfo;
+
+typedef struct {
+ VkBool32 blendEnable;
+ VkBlend srcBlendColor;
+ VkBlend destBlendColor;
+ VkBlendOp blendOpColor;
+ VkBlend srcBlendAlpha;
+ VkBlend destBlendAlpha;
+ VkBlendOp blendOpAlpha;
+ VkChannelFlags channelWriteMask;
+} VkPipelineColorBlendAttachmentState;
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ VkBool32 alphaToCoverageEnable;
+ VkBool32 logicOpEnable;
+ VkLogicOp logicOp;
+ uint32_t attachmentCount;
+ const VkPipelineColorBlendAttachmentState* pAttachments;
+} VkPipelineColorBlendStateCreateInfo;
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t stageCount;
+ const VkPipelineShaderStageCreateInfo* pStages;
+ const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
+ const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
+ const VkPipelineTessellationStateCreateInfo* pTessellationState;
+ const VkPipelineViewportStateCreateInfo* pViewportState;
+ const VkPipelineRasterStateCreateInfo* pRasterState;
+ const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
+ const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
+ const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
+ VkPipelineCreateFlags flags;
+ VkPipelineLayout layout;
+ VkRenderPass renderPass;
+ uint32_t subpass;
+ VkPipeline basePipelineHandle;
+ int32_t basePipelineIndex;
+} VkGraphicsPipelineCreateInfo;
+
+VkResult VKAPI vkCreateGraphicsPipelines(
+ VkDevice device,
+ VkPipelineCache pipelineCache,
+ uint32_t count,
+ const VkGraphicsPipelineCreateInfo* pCreateInfos,
+ VkPipeline* pPipelines);
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineShaderStageCreateInfo cs;
+ VkPipelineCreateFlags flags;
+ VkPipelineLayout layout;
+ VkPipeline basePipelineHandle;
+ int32_t basePipelineIndex;
+} VkComputePipelineCreateInfo;
+
+VkResult VKAPI vkCreateComputePipelines(
+ VkDevice device,
+ VkPipelineCache pipelineCache,
+ uint32_t count,
+ const VkComputePipelineCreateInfo* pCreateInfos,
+ VkPipeline* pPipelines);
+----
+
+Pipeline caches
+^^^^^^^^^^^^^^^
+
+Extend pipeline tests to cases to use pipeline caches, test that pipelines created from pre-populated cache still produce identical results to pipelines created with empty cache.
+
+Verify that maximum cache size is not exceeded.
+
+[source,c]
+----
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ size_t initialSize;
+ const void* initialData;
+ size_t maxSize;
+} VkPipelineCacheCreateInfo;
+
+VkResult VKAPI vkCreatePipelineCache(
+ VkDevice device,
+ const VkPipelineCacheCreateInfo* pCreateInfo,
+ VkPipelineCache* pPipelineCache);
+
+size_t VKAPI vkGetPipelineCacheSize(
+ VkDevice device,
+ VkPipelineCache pipelineCache);
+
+VkResult VKAPI vkGetPipelineCacheData(
+ VkDevice device,
+ VkPipelineCache pipelineCache,
+ void* pData);
+
+VkResult VKAPI vkMergePipelineCaches(
+ VkDevice device,
+ VkPipelineCache destCache,
+ uint32_t srcCacheCount,
+ const VkPipelineCache* pSrcCaches);
+----
+
+Pipeline state
+~~~~~~~~~~~~~~
+
+Pipeline tests, as they need to verify rendering results, will provide a lot of coverage for pipeline state manipulation. In addition some corner-case tests are needed:
+
+ * Re-setting pipeline state bits before use
+ * Carrying / manipulating only part of state over draw calls
+ * Submitting command buffers that have only pipeline state manipulation calls (should be no-op)
+
+.Spec issues
+ * Does vkCmdBindPipeline invalidate other state bits?
+
+[source,c]
+----
+void VKAPI vkCmdBindPipeline(
+ VkCmdBuffer cmdBuffer,
+ VkPipelineBindPoint pipelineBindPoint,
+ VkPipeline pipeline);
+
+void VKAPI vkCmdBindDescriptorSets(
+ VkCmdBuffer cmdBuffer,
+ VkPipelineBindPoint pipelineBindPoint,
+ VkPipelineLayout layout,
+ uint32_t firstSet,
+ uint32_t setCount,
+ const VkDescriptorSet* pDescriptorSets,
+ uint32_t dynamicOffsetCount,
+ const uint32_t* pDynamicOffsets);
+
+void VKAPI vkCmdBindIndexBuffer(
+ VkCmdBuffer cmdBuffer,
+ VkBuffer buffer,
+ VkDeviceSize offset,
+ VkIndexType indexType);
+
+void VKAPI vkCmdBindVertexBuffers(
+ VkCmdBuffer cmdBuffer,
+ uint32_t startBinding,
+ uint32_t bindingCount,
+ const VkBuffer* pBuffers,
+ const VkDeviceSize* pOffsets);
+----
+
+Samplers
+--------
+
+Sampler tests verify that sampler parameters are mapped to correct HW state. That will be verified by sampling various textures in certain configurations (as listed below). More exhaustive texture filtering verification will be done separately.
+
+ * All valid sampler state configurations
+ * Selected texture formats (RGBA8, FP16, integer textures)
+ * All texture types
+ * Mip-mapping with explicit and implicit LOD
+
+[source,c]
+----
+typedef enum {
+ VK_TEX_FILTER_NEAREST = 0,
+ VK_TEX_FILTER_LINEAR = 1,
+ VK_TEX_FILTER_BEGIN_RANGE = VK_TEX_FILTER_NEAREST,
+ VK_TEX_FILTER_END_RANGE = VK_TEX_FILTER_LINEAR,
+ VK_TEX_FILTER_NUM = (VK_TEX_FILTER_LINEAR - VK_TEX_FILTER_NEAREST + 1),
+ VK_TEX_FILTER_MAX_ENUM = 0x7FFFFFFF
+} VkTexFilter;
+
+typedef enum {
+ VK_TEX_MIPMAP_MODE_BASE = 0,
+ VK_TEX_MIPMAP_MODE_NEAREST = 1,
+ VK_TEX_MIPMAP_MODE_LINEAR = 2,
+ VK_TEX_MIPMAP_MODE_BEGIN_RANGE = VK_TEX_MIPMAP_MODE_BASE,
+ VK_TEX_MIPMAP_MODE_END_RANGE = VK_TEX_MIPMAP_MODE_LINEAR,
+ VK_TEX_MIPMAP_MODE_NUM = (VK_TEX_MIPMAP_MODE_LINEAR - VK_TEX_MIPMAP_MODE_BASE + 1),
+ VK_TEX_MIPMAP_MODE_MAX_ENUM = 0x7FFFFFFF
+} VkTexMipmapMode;
+
+typedef enum {
+ VK_TEX_ADDRESS_WRAP = 0,
+ VK_TEX_ADDRESS_MIRROR = 1,
+ VK_TEX_ADDRESS_CLAMP = 2,
+ VK_TEX_ADDRESS_MIRROR_ONCE = 3,
+ VK_TEX_ADDRESS_CLAMP_BORDER = 4,
+ VK_TEX_ADDRESS_BEGIN_RANGE = VK_TEX_ADDRESS_WRAP,
+ VK_TEX_ADDRESS_END_RANGE = VK_TEX_ADDRESS_CLAMP_BORDER,
+ VK_TEX_ADDRESS_NUM = (VK_TEX_ADDRESS_CLAMP_BORDER - VK_TEX_ADDRESS_WRAP + 1),
+ VK_TEX_ADDRESS_MAX_ENUM = 0x7FFFFFFF
+} VkTexAddress;
+
+typedef enum {
+ VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK = 0,
+ VK_BORDER_COLOR_INT_TRANSPARENT_BLACK = 1,
+ VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK = 2,
+ VK_BORDER_COLOR_INT_OPAQUE_BLACK = 3,
+ VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE = 4,
+ VK_BORDER_COLOR_INT_OPAQUE_WHITE = 5,
+ VK_BORDER_COLOR_BEGIN_RANGE = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,
+ VK_BORDER_COLOR_END_RANGE = VK_BORDER_COLOR_INT_OPAQUE_WHITE,
+ VK_BORDER_COLOR_NUM = (VK_BORDER_COLOR_INT_OPAQUE_WHITE - VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK + 1),
+ VK_BORDER_COLOR_MAX_ENUM = 0x7FFFFFFF
+} VkBorderColor;
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ VkTexFilter magFilter;
+ VkTexFilter minFilter;
+ VkTexMipmapMode mipMode;
+ VkTexAddress addressU;
+ VkTexAddress addressV;
+ VkTexAddress addressW;
+ float mipLodBias;
+ float maxAnisotropy;
+ VkBool32 compareEnable;
+ VkCompareOp compareOp;
+ float minLod;
+ float maxLod;
+ VkBorderColor borderColor;
+} VkSamplerCreateInfo;
+
+VkResult VKAPI vkCreateSampler(
+ VkDevice device,
+ const VkSamplerCreateInfo* pCreateInfo,
+ VkSampler* pSampler);
+----
+
+Dynamic state objects
+---------------------
+
+Pipeline tests will include coverage for most dynamic state object usage as some pipeline configurations need corresponding dynamic state objects. In addition there are couple of corner-cases worth exploring separately:
+
+ * Re-setting dynamic state bindings one or more times before first use
+ * Dynamic state object binding persistence over pipeline changes
+ * Large amounts of unique dynamic state objects in a command buffer, pass, or multipass
+
+[source,c]
+----
+// Viewport
+
+typedef struct {
+ float originX;
+ float originY;
+ float width;
+ float height;
+ float minDepth;
+ float maxDepth;
+} VkViewport;
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t viewportAndScissorCount;
+ const VkViewport* pViewports;
+ const VkRect2D* pScissors;
+} VkDynamicViewportStateCreateInfo;
+
+VkResult VKAPI vkCreateDynamicViewportState(
+ VkDevice device,
+ const VkDynamicViewportStateCreateInfo* pCreateInfo,
+ VkDynamicViewportState* pState);
+
+void VKAPI vkCmdBindDynamicViewportState(
+ VkCmdBuffer cmdBuffer,
+ VkDynamicViewportState dynamicViewportState);
+
+// Raster
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ float depthBias;
+ float depthBiasClamp;
+ float slopeScaledDepthBias;
+ float lineWidth;
+} VkDynamicRasterStateCreateInfo;
+
+VkResult VKAPI vkCreateDynamicRasterState(
+ VkDevice device,
+ const VkDynamicRasterStateCreateInfo* pCreateInfo,
+ VkDynamicRasterState* pState);
+
+void VKAPI vkCmdBindDynamicRasterState(
+ VkCmdBuffer cmdBuffer,
+ VkDynamicRasterState dynamicRasterState);
+
+// Color blend
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ float blendConst[4];
+} VkDynamicColorBlendStateCreateInfo;
+
+VkResult VKAPI vkCreateDynamicColorBlendState(
+ VkDevice device,
+ const VkDynamicColorBlendStateCreateInfo* pCreateInfo,
+ VkDynamicColorBlendState* pState);
+
+void VKAPI vkCmdBindDynamicColorBlendState(
+ VkCmdBuffer cmdBuffer,
+ VkDynamicColorBlendState dynamicColorBlendState);
+
+// Depth & stencil
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ float minDepthBounds;
+ float maxDepthBounds;
+ uint32_t stencilReadMask;
+ uint32_t stencilWriteMask;
+ uint32_t stencilFrontRef;
+ uint32_t stencilBackRef;
+} VkDynamicDepthStencilStateCreateInfo;
+
+VkResult VKAPI vkCreateDynamicDepthStencilState(
+ VkDevice device,
+ const VkDynamicDepthStencilStateCreateInfo* pCreateInfo,
+ VkDynamicDepthStencilState* pState);
+
+void VKAPI vkCmdBindDynamicDepthStencilState(
+ VkCmdBuffer cmdBuffer,
+ VkDynamicDepthStencilState dynamicDepthStencilState);
+----
+
+Command buffers
+---------------
+
+Tests for various rendering features will provide significant coverage for command buffer recording. Additional coverage will be needed for:
+
+ * Re-setting command buffers
+ * Very small (empty) and large command buffers
+ * Various optimize flags combined with various command buffer sizes and contents
+ ** Forcing optimize flags in other tests might be useful for finding cases that may break
+
+[source,c]
+----
+typedef enum {
+ VK_CMD_BUFFER_LEVEL_PRIMARY = 0,
+ VK_CMD_BUFFER_LEVEL_SECONDARY = 1,
+ VK_CMD_BUFFER_LEVEL_BEGIN_RANGE = VK_CMD_BUFFER_LEVEL_PRIMARY,
+ VK_CMD_BUFFER_LEVEL_END_RANGE = VK_CMD_BUFFER_LEVEL_SECONDARY,
+ VK_CMD_BUFFER_LEVEL_NUM = (VK_CMD_BUFFER_LEVEL_SECONDARY - VK_CMD_BUFFER_LEVEL_PRIMARY + 1),
+ VK_CMD_BUFFER_LEVEL_MAX_ENUM = 0x7FFFFFFF
+} VkCmdBufferLevel;
+
+typedef VkFlags VkCmdBufferCreateFlags;
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ VkCmdPool cmdPool;
+ VkCmdBufferLevel level;
+ VkCmdBufferCreateFlags flags;
+} VkCmdBufferCreateInfo;
+
+VkResult VKAPI vkCreateCommandBuffer(
+ VkDevice device,
+ const VkCmdBufferCreateInfo* pCreateInfo,
+ VkCmdBuffer* pCmdBuffer);
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ VkCmdBufferOptimizeFlags flags;
+ VkRenderPass renderPass;
+ VkFramebuffer framebuffer;
+} VkCmdBufferBeginInfo;
+
+typedef enum {
+ VK_CMD_BUFFER_OPTIMIZE_SMALL_BATCH_BIT = 0x00000001,
+ VK_CMD_BUFFER_OPTIMIZE_PIPELINE_SWITCH_BIT = 0x00000002,
+ VK_CMD_BUFFER_OPTIMIZE_ONE_TIME_SUBMIT_BIT = 0x00000004,
+ VK_CMD_BUFFER_OPTIMIZE_DESCRIPTOR_SET_SWITCH_BIT = 0x00000008,
+ VK_CMD_BUFFER_OPTIMIZE_NO_SIMULTANEOUS_USE_BIT = 0x00000010,
+} VkCmdBufferOptimizeFlagBits;
+typedef VkFlags VkCmdBufferOptimizeFlags;
+
+VkResult VKAPI vkBeginCommandBuffer(
+ VkCmdBuffer cmdBuffer,
+ const VkCmdBufferBeginInfo* pBeginInfo);
+
+VkResult VKAPI vkEndCommandBuffer(
+ VkCmdBuffer cmdBuffer);
+
+typedef enum {
+ VK_CMD_BUFFER_RESET_RELEASE_RESOURCES = 0x00000001,
+} VkCmdBufferResetFlagBits;
+typedef VkFlags VkCmdBufferResetFlags;
+
+VkResult VKAPI vkResetCommandBuffer(
+ VkCmdBuffer cmdBuffer,
+ VkCmdBufferResetFlags flags);
+----
+
+Command pools
+~~~~~~~~~~~~~
+
+TODO
+
+[source,c]
+----
+typedef enum {
+ VK_CMD_POOL_CREATE_TRANSIENT_BIT = 0x00000001,
+ VK_CMD_POOL_CREATE_RESET_COMMAND_BUFFER_BIT = 0x00000002,
+} VkCmdPoolCreateFlagBits;
+typedef VkFlags VkCmdPoolCreateFlags;
+
+typedef struct {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t queueFamilyIndex;
+ VkCmdPoolCreateFlags flags;
+} VkCmdPoolCreateInfo;
+
+VkResult VKAPI vkCreateCommandPool(
+ VkDevice device,
+ const VkCmdPoolCreateInfo* pCreateInfo,
+ VkCmdPool* pCmdPool);
+
+typedef enum {
+ VK_CMD_POOL_RESET_RELEASE_RESOURCES = 0x00000001,
+} VkCmdPoolResetFlagBits;
+typedef VkFlags VkCmdPoolResetFlags;
+
+VkResult VKAPI vkResetCommandPool(
+ VkDevice device,
+ VkCmdPool cmdPool,
+ VkCmdPoolResetFlags flags);
+----
+
+2-level command buffers
+~~~~~~~~~~~~~~~~~~~~~~~
+
+TODO
+
+[source,c]
+----
+void VKAPI vkCmdExecuteCommands(
+ VkCmdBuffer cmdBuffer,
+ uint32_t cmdBuffersCount,
+ const VkCmdBuffer* pCmdBuffers);
+----
+
+Draw commands
+-------------
+
+Draw command tests verify that all draw parameters are respected (including vertex input state) and various draw call sizes work correctly. The tests won't however validate that all side effects of shader invocations happen as intended (covered by feature-specific tests) nor that primitive rasterization is fully correct (will be covered by separate targeted tests).
+
+[source,c]
+----
+void VKAPI vkCmdDraw(
+ VkCmdBuffer cmdBuffer,
+ uint32_t firstVertex,
+ uint32_t vertexCount,
+ uint32_t firstInstance,
+ uint32_t instanceCount);
+
+void VKAPI vkCmdDrawIndexed(
+ VkCmdBuffer cmdBuffer,
+ uint32_t firstIndex,
+ uint32_t indexCount,
+ int32_t vertexOffset,
+ uint32_t firstInstance,
+ uint32_t instanceCount);
+
+void VKAPI vkCmdDrawIndirect(
+ VkCmdBuffer cmdBuffer,
+ VkBuffer buffer,
+ VkDeviceSize offset,
+ uint32_t count,
+ uint32_t stride);
+
+void VKAPI vkCmdDrawIndexedIndirect(
+ VkCmdBuffer cmdBuffer,
+ VkBuffer buffer,
+ VkDeviceSize offset,
+ uint32_t count,
+ uint32_t stride);
+----
+
+Compute
+-------
+
+Like draw tests, compute dispatch tests will validate that call parameters have desired effects. In addition compute tests need to verify that various dispatch parameters (number of work groups, invocation IDs) are passed correctly to the shader invocations.
+
+NOTE: Assuming that compute-specific shader features, such as shared memory access, is covered by SPIR-V tests.
+
+[source,c]
+----
+void VKAPI vkCmdDispatch(
+ VkCmdBuffer cmdBuffer,
+ uint32_t x,
+ uint32_t y,
+ uint32_t z);
+
+void VKAPI vkCmdDispatchIndirect(
+ VkCmdBuffer cmdBuffer,
+ VkBuffer buffer,
+ VkDeviceSize offset);
+----
+
+Copies and blits
+----------------
+
+Buffer copies
+~~~~~~~~~~~~~
+
+Buffer copy tests need to validate that copies and updates happen as expected for both simple and more complex cases:
+
+ * Whole-buffer, partial copies
+ * Small (1 byte) to very large copies and updates
+ * Copies between objects backed by same memory
+
+NOTE: GPU cache control tests need to verify copy source and destination visibility as well.
+
+.Spec issues
+ * Overlapping copies?
+ ** Simple overlap (same buffer)
+ ** Backed by same memory object
+
+[source,c]
+----
+typedef struct {
+ VkDeviceSize srcOffset;
+ VkDeviceSize destOffset;
+ VkDeviceSize copySize;
+} VkBufferCopy;
+
+void VKAPI vkCmdCopyBuffer(
+ VkCmdBuffer cmdBuffer,
+ VkBuffer srcBuffer,
+ VkBuffer destBuffer,
+ uint32_t regionCount,
+ const VkBufferCopy* pRegions);
+
+void VKAPI vkCmdUpdateBuffer(
+ VkCmdBuffer cmdBuffer,
+ VkBuffer destBuffer,
+ VkDeviceSize destOffset,
+ VkDeviceSize dataSize,
+ const uint32_t* pData);
+
+void VKAPI vkCmdFillBuffer(
+ VkCmdBuffer cmdBuffer,
+ VkBuffer destBuffer,
+ VkDeviceSize destOffset,
+ VkDeviceSize fillSize,
+ uint32_t data);
+----
+
+Image copies
+~~~~~~~~~~~~
+
+.Spec issues
+ * What kind of copies are allowed? Blits?
+ * Copy is simply reinterpretation of data?
+ * Does blit unpack & pack data like in GL?
+ ** sRGB conversions
+
+[source,c]
+----
+typedef struct {
+ VkImageSubresource srcSubresource;
+ VkOffset3D srcOffset;
+ VkImageSubresource destSubresource;
+ VkOffset3D destOffset;
+ VkExtent3D extent;
+} VkImageCopy;
+
+typedef struct {
+ VkImageSubresource srcSubresource;
+ VkOffset3D srcOffset;
+ VkExtent3D srcExtent;
+ VkImageSubresource destSubresource;
+ VkOffset3D destOffset;
+ VkExtent3D destExtent;
+} VkImageBlit;
+
+void VKAPI vkCmdCopyImage(
+ VkCmdBuffer cmdBuffer,
+ VkImage srcImage,
+ VkImageLayout srcImageLayout,
+ VkImage destImage,
+ VkImageLayout destImageLayout,
+ uint32_t regionCount,
+ const VkImageCopy* pRegions);
+
+void VKAPI vkCmdBlitImage(
+ VkCmdBuffer cmdBuffer,
+ VkImage srcImage,
+ VkImageLayout srcImageLayout,
+ VkImage destImage,
+ VkImageLayout destImageLayout,
+ uint32_t regionCount,
+ const VkImageBlit* pRegions,
+ VkTexFilter filter);
+----
+
+Copies between buffers and images
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+[source,c]
+----
+typedef struct {
+ VkDeviceSize bufferOffset;
+ uint32_t bufferRowLength;
+ uint32_t bufferImageHeight;
+ VkImageSubresource imageSubresource;
+ VkOffset3D imageOffset;
+ VkExtent3D imageExtent;
+} VkBufferImageCopy;
+
+void VKAPI vkCmdCopyBufferToImage(
+ VkCmdBuffer cmdBuffer,
+ VkBuffer srcBuffer,
+ VkImage destImage,
+ VkImageLayout destImageLayout,
+ uint32_t regionCount,
+ const VkBufferImageCopy* pRegions);
+
+void VKAPI vkCmdCopyImageToBuffer(
+ VkCmdBuffer cmdBuffer,
+ VkImage srcImage,
+ VkImageLayout srcImageLayout,
+ VkBuffer destBuffer,
+ uint32_t regionCount,
+ const VkBufferImageCopy* pRegions);
+----
+
+Clearing images
+~~~~~~~~~~~~~~~
+
+[source,c]
+----
+typedef union {
+ float f32[4];
+ int32_t s32[4];
+ uint32_t u32[4];
+} VkClearColorValue;
+
+typedef struct {
+ float depth;
+ uint32_t stencil;
+} VkClearDepthStencilValue;
+
+typedef union {
+ VkClearColorValue color;
+ VkClearDepthStencilValue ds;
+} VkClearValue;
+
+void VKAPI vkCmdClearColorImage(
+ VkCmdBuffer cmdBuffer,
+ VkImage image,
+ VkImageLayout imageLayout,
+ const VkClearColorValue* pColor,
+ uint32_t rangeCount,
+ const VkImageSubresourceRange* pRanges);
+
+void VKAPI vkCmdClearDepthStencilImage(
+ VkCmdBuffer cmdBuffer,
+ VkImage image,
+ VkImageLayout imageLayout,
+ float depth,
+ uint32_t stencil,
+ uint32_t rangeCount,
+ const VkImageSubresourceRange* pRanges);
+
+void VKAPI vkCmdClearColorAttachment(
+ VkCmdBuffer cmdBuffer,
+ uint32_t colorAttachment,
+ VkImageLayout imageLayout,
+ const VkClearColorValue* pColor,
+ uint32_t rectCount,
+ const VkRect3D* pRects);
+
+void VKAPI vkCmdClearDepthStencilAttachment(
+ VkCmdBuffer cmdBuffer,
+ VkImageAspectFlags imageAspectMask,
+ VkImageLayout imageLayout,
+ float depth,
+ uint32_t stencil,
+ uint32_t rectCount,
+ const VkRect3D* pRects);
+----
+
+Multisample resolve
+~~~~~~~~~~~~~~~~~~~
+
+[source,c]
+----
+typedef struct {
+ VkImageSubresource srcSubresource;
+ VkOffset3D srcOffset;
+ VkImageSubresource destSubresource;
+ VkOffset3D destOffset;
+ VkExtent3D extent;
+} VkImageResolve;
+
+void VKAPI vkCmdResolveImage(
+ VkCmdBuffer cmdBuffer,
+ VkImage srcImage,
+ VkImageLayout srcImageLayout,
+ VkImage destImage,
+ VkImageLayout destImageLayout,
+ uint32_t regionCount,
+ const VkImageResolve* pRegions);
+----
+
+Push constants
+--------------
+
+TODO
+
+[source,c]
+----
+void VKAPI vkCmdPushConstants(
+ VkCmdBuffer cmdBuffer,
+ VkPipelineLayout layout,
+ VkShaderStageFlags stageFlags,
+ uint32_t start,
+ uint32_t length,
+ const void* values);
+----
+
+GPU timestamps
+--------------
+
+[source,c]
+----
+typedef enum {
+ VK_TIMESTAMP_TYPE_TOP = 0,
+ VK_TIMESTAMP_TYPE_BOTTOM = 1,
+ VK_TIMESTAMP_TYPE_BEGIN_RANGE = VK_TIMESTAMP_TYPE_TOP,
+ VK_TIMESTAMP_TYPE_END_RANGE = VK_TIMESTAMP_TYPE_BOTTOM,
+ VK_TIMESTAMP_TYPE_NUM = (VK_TIMESTAMP_TYPE_BOTTOM - VK_TIMESTAMP_TYPE_TOP + 1),
+ VK_TIMESTAMP_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkTimestampType;
+
+void VKAPI vkCmdWriteTimestamp(
+ VkCmdBuffer cmdBuffer,
+ VkTimestampType timestampType,
+ VkBuffer destBuffer,
+ VkDeviceSize destOffset);
+----
+
+ * All timestamp types
+ * Various commands before and after timestamps
+ * Command buffers that only record timestamps
+ * Sanity check (to the extent possible) for timestamps
+ ** TOP >= BOTTOM
+
+.Spec issues
+ * How many bytes timestamp is? Do we need to support both 32-bit and 64-bit?
+ * destOffset probably needs to be aligned?
+ * TOP vs. BOTTOM not well specified
+
+Validation layer tests
+----------------------
+
+Validation layer tests exercise all relevant invalid API usage patterns and verify that correct return values and error messages are generated. In addition validation tests would try to load invalid SPIR-V binaries and verify that all generic SPIR-V, and Vulkan SPIR-V environment rules are checked.
+
+Android doesn't plan to ship validation layer as part of the system image so validation tests are not required by Android CTS and thus are of very low priority currently.
--- /dev/null
+[attributes]\r
+newline=\n\r
+\r
+[replacements]\r
+\+\/-=±\r
pushWorkingDir(fullDstPath)
try:
- execute(["git", "fetch", self.url])
+ execute(["git", "fetch", self.url, "+refs/heads/*:refs/remotes/origin/*"])
execute(["git", "checkout", self.revision])
finally:
popWorkingDir()
"a18233c99e1dc59a256180e6871d9305a42e91b3f98799b3ceb98e87e9ec5e31",
"libpng",
postExtract = postExtractLibpng),
+ GitRepo(
+ "git@gitlab.khronos.org:spirv/spirv-tools.git",
+ "4e5bc928c0430b6015bd7836c598113f7076af20",
+ "spirv-tools"),
+ GitRepo(
+ "git@gitlab.khronos.org:GLSL/glslang.git",
+ "9e1d1465801ace8edd95c951a3d4a9ada75306ed",
+ "glslang"),
]
def parseArgs ():
--- /dev/null
+# cmake file for glslang
+
+if (NOT DE_DEFS)
+ message(FATAL_ERROR "Include Defs.cmake")
+endif ()
+
+if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/SPIRV/GlslangToSpv.cpp")
+ set(DEFAULT_GLSLANG_SRC_PATH ${CMAKE_CURRENT_SOURCE_DIR}/src)
+else ()
+ set(DEFAULT_GLSLANG_SRC_PATH "../glslang")
+endif ()
+
+set(GLSLANG_SRC_PATH ${DEFAULT_GLSLANG_SRC_PATH} CACHE STRING "Path to glslang source tree")
+
+if (IS_ABSOLUTE ${GLSLANG_SRC_PATH})
+ set(GLSLANG_ABS_PATH ${GLSLANG_SRC_PATH})
+else ()
+ set(GLSLANG_ABS_PATH "${CMAKE_SOURCE_DIR}/${GLSLANG_SRC_PATH}")
+endif ()
+
+find_package(BISON)
+
+# \todo [2015-06-24 pyry] Full C++11 support on Android requires using CLang + libc++
+if (NOT BISON_FOUND AND DE_OS_IS_WIN32 AND EXISTS ${GLSLANG_ABS_PATH}/tools/bison.exe)
+ message(STATUS "Using pre-built bison executable")
+ set(BISON_EXECUTABLE ${GLSLANG_ABS_PATH}/tools/bison.exe)
+ set(BISON_FOUND ON)
+endif ()
+
+if (BISON_FOUND AND EXISTS ${GLSLANG_ABS_PATH}/glslang/GenericCodeGen/CodeGen.cpp AND NOT DE_OS_IS_ANDROID)
+ message(STATUS "glslang found; building with DEQP_SUPPORT_GLSLANG")
+
+ include_directories(
+ ${GLSLANG_ABS_PATH}
+ ${GLSLANG_ABS_PATH}/glslang
+ ${GLSLANG_ABS_PATH}/glslang/Include
+ ${GLSLANG_ABS_PATH}/glslang/Public
+ ${GLSLANG_ABS_PATH}/glslang/MachineIndependent
+ ${GLSLANG_ABS_PATH}/glslang/GenericCodeGen
+ ${GLSLANG_ABS_PATH}/glslang/OSDependent
+ ${GLSLANG_ABS_PATH}/OGLCompilersDLL
+ ${GLSLANG_ABS_PATH}/SPIRV
+ ${CMAKE_CURRENT_BINARY_DIR}
+ )
+
+ set(GLSLANG_SRCS
+ ${GLSLANG_ABS_PATH}/glslang/MachineIndependent/Constant.cpp
+ ${GLSLANG_ABS_PATH}/glslang/MachineIndependent/InfoSink.cpp
+ ${GLSLANG_ABS_PATH}/glslang/MachineIndependent/Initialize.cpp
+ ${GLSLANG_ABS_PATH}/glslang/MachineIndependent/IntermTraverse.cpp
+ ${GLSLANG_ABS_PATH}/glslang/MachineIndependent/Intermediate.cpp
+ ${GLSLANG_ABS_PATH}/glslang/MachineIndependent/ParseHelper.cpp
+ ${GLSLANG_ABS_PATH}/glslang/MachineIndependent/PoolAlloc.cpp
+ ${GLSLANG_ABS_PATH}/glslang/MachineIndependent/RemoveTree.cpp
+ ${GLSLANG_ABS_PATH}/glslang/MachineIndependent/Scan.cpp
+ ${GLSLANG_ABS_PATH}/glslang/MachineIndependent/ShaderLang.cpp
+ ${GLSLANG_ABS_PATH}/glslang/MachineIndependent/SymbolTable.cpp
+ ${GLSLANG_ABS_PATH}/glslang/MachineIndependent/Versions.cpp
+ ${GLSLANG_ABS_PATH}/glslang/MachineIndependent/intermOut.cpp
+ ${GLSLANG_ABS_PATH}/glslang/MachineIndependent/limits.cpp
+ ${GLSLANG_ABS_PATH}/glslang/MachineIndependent/linkValidate.cpp
+ ${GLSLANG_ABS_PATH}/glslang/MachineIndependent/parseConst.cpp
+ ${GLSLANG_ABS_PATH}/glslang/MachineIndependent/reflection.cpp
+ ${GLSLANG_ABS_PATH}/glslang/MachineIndependent/preprocessor/Pp.cpp
+ ${GLSLANG_ABS_PATH}/glslang/MachineIndependent/preprocessor/PpAtom.cpp
+ ${GLSLANG_ABS_PATH}/glslang/MachineIndependent/preprocessor/PpContext.cpp
+ ${GLSLANG_ABS_PATH}/glslang/MachineIndependent/preprocessor/PpMemory.cpp
+ ${GLSLANG_ABS_PATH}/glslang/MachineIndependent/preprocessor/PpScanner.cpp
+ ${GLSLANG_ABS_PATH}/glslang/MachineIndependent/preprocessor/PpSymbols.cpp
+ ${GLSLANG_ABS_PATH}/glslang/MachineIndependent/preprocessor/PpTokens.cpp
+ ${GLSLANG_ABS_PATH}/glslang/GenericCodeGen/CodeGen.cpp
+ ${GLSLANG_ABS_PATH}/glslang/GenericCodeGen/Link.cpp
+ ${GLSLANG_ABS_PATH}/OGLCompilersDLL/InitializeDll.cpp
+
+ ${GLSLANG_ABS_PATH}/SPIRV/GlslangToSpv.cpp
+ ${GLSLANG_ABS_PATH}/SPIRV/SpvBuilder.cpp
+ ${GLSLANG_ABS_PATH}/SPIRV/SPVRemapper.cpp
+ ${GLSLANG_ABS_PATH}/SPIRV/doc.cpp
+ ${GLSLANG_ABS_PATH}/SPIRV/disassemble.cpp
+
+ ${CMAKE_CURRENT_BINARY_DIR}/glslang_tab.cpp
+ ${CMAKE_CURRENT_BINARY_DIR}/glslang_tab.cpp.h
+
+ osinclude.cpp
+ )
+
+ set(CMAKE_C_FLAGS ${DE_3RD_PARTY_C_FLAGS})
+ set(CMAKE_CXX_FLAGS ${DE_3RD_PARTY_CXX_FLAGS})
+
+ if (DE_COMPILER_IS_GCC OR DE_COMPILER_IS_CLANG)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+ endif ()
+
+ add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/glslang_tab.cpp ${CMAKE_CURRENT_BINARY_DIR}/glslang_tab.cpp.h
+ COMMAND ${BISON_EXECUTABLE} --defines=${CMAKE_CURRENT_BINARY_DIR}/glslang_tab.cpp.h -t MachineIndependent/glslang.y -o ${CMAKE_CURRENT_BINARY_DIR}/glslang_tab.cpp
+ MAIN_DEPENDENCY ${GLSLANG_ABS_PATH}/glslang/MachineIndependent/glslang.y
+ WORKING_DIRECTORY ${GLSLANG_ABS_PATH}/glslang)
+
+ add_library(glslang STATIC ${GLSLANG_SRCS})
+ target_link_libraries(glslang dethread ${ZLIB_LIBRARY})
+
+ set(GLSLANG_INCLUDE_PATH ${GLSLANG_ABS_PATH} PARENT_SCOPE)
+ set(GLSLANG_LIBRARY glslang PARENT_SCOPE)
+ set(DEQP_HAVE_GLSLANG ON PARENT_SCOPE)
+
+else ()
+ message(STATUS "glslang not found; GLSL to SPIR-V compilation not available")
+
+ set(DEQP_HAVE_GLSLANG OFF PARENT_SCOPE)
+
+endif ()
--- /dev/null
+/*-------------------------------------------------------------------------
+ * dEQP glslang integration
+ * ------------------------
+ *
+ * Copyright 2015 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 glslang OS interface.
+ *//*--------------------------------------------------------------------*/
+
+#include "osinclude.h"
+
+#include "deThread.h"
+#include "deThreadLocal.h"
+
+namespace glslang
+{
+
+DE_STATIC_ASSERT(sizeof(deThreadLocal) == sizeof(OS_TLSIndex));
+DE_STATIC_ASSERT(sizeof(deThread) == sizeof(void*));
+
+// Thread-local
+
+OS_TLSIndex OS_AllocTLSIndex (void)
+{
+ return (OS_TLSIndex)deThreadLocal_create();
+}
+
+bool OS_SetTLSValue (OS_TLSIndex nIndex, void* lpvValue)
+{
+ deThreadLocal_set((deThreadLocal)nIndex, lpvValue);
+ return true;
+}
+
+bool OS_FreeTLSIndex (OS_TLSIndex nIndex)
+{
+ deThreadLocal_destroy((deThreadLocal)nIndex);
+ return true;
+}
+
+void* OS_GetTLSValue (OS_TLSIndex nIndex)
+{
+ return deThreadLocal_get((deThreadLocal)nIndex);
+}
+
+// Global lock - not used
+
+void InitGlobalLock (void)
+{
+}
+
+void GetGlobalLock (void)
+{
+}
+
+void ReleaseGlobalLock (void)
+{
+}
+
+// Threading
+
+DE_STATIC_ASSERT(sizeof(void*) >= sizeof(deThread));
+
+static void EnterGenericThread (void* entry)
+{
+ ((TThreadEntrypoint)entry)(DE_NULL);
+}
+
+void* OS_CreateThread (TThreadEntrypoint entry)
+{
+ return (void*)(deUintptr)deThread_create(EnterGenericThread, (void*)entry, DE_NULL);
+}
+
+void OS_WaitForAllThreads (void* threads, int numThreads)
+{
+ for (int ndx = 0; ndx < numThreads; ndx++)
+ {
+ const deThread thread = (deThread)(deUintptr)((void**)threads)[ndx];
+ deThread_join(thread);
+ deThread_destroy(thread);
+ }
+}
+
+void OS_Sleep (int milliseconds)
+{
+ deSleep(milliseconds);
+}
+
+void OS_DumpMemoryCounters (void)
+{
+ // Not used
+}
+
+} // glslang
--- /dev/null
+# cmake file for spirv-tools
+
+if (NOT DE_DEFS)
+ message(FATAL_ERROR "Include Defs.cmake")
+endif ()
+
+if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/include/libspirv/libspirv.h")
+ set(DEFAULT_SPIRV_TOOLS_SRC_PATH ${CMAKE_CURRENT_SOURCE_DIR}/src)
+else ()
+ set(DEFAULT_SPIRV_TOOLS_SRC_PATH "../spirv-tools")
+endif ()
+
+set(SPIRV_TOOLS_SRC_PATH ${DEFAULT_SPIRV_TOOLS_SRC_PATH} CACHE STRING "Path to spirv-tools source tree")
+if (IS_ABSOLUTE ${SPIRV_TOOLS_SRC_PATH})
+ set(SPIRV_TOOLS_ABS_PATH ${SPIRV_TOOLS_SRC_PATH})
+else ()
+ set(SPIRV_TOOLS_ABS_PATH "${CMAKE_SOURCE_DIR}/${SPIRV_TOOLS_SRC_PATH}")
+endif ()
+
+if (EXISTS ${SPIRV_TOOLS_ABS_PATH}/source/opcode.cpp)
+ message(STATUS "spirv-tools found; building with DEQP_HAVE_SPIRV_TOOLS")
+ set(CMAKE_C_FLAGS ${DE_3RD_PARTY_C_FLAGS})
+ set(CMAKE_CXX_FLAGS ${DE_3RD_PARTY_CXX_FLAGS})
+
+ set(DEQP_HAVE_SPIRV_TOOLS ON PARENT_SCOPE)
+ set(SPIRV_SKIP_EXECUTABLES ON CACHE BOOL "" FORCE)
+ add_subdirectory(${SPIRV_TOOLS_ABS_PATH} spirv-tools)
+else ()
+ message(STATUS "spirv-tools not found; SPIR-V assembly not available")
+ set(DEQP_HAVE_SPIRV_TOOLS OFF PARENT_SCOPE)
+endif ()
--- /dev/null
+
+Copyright (c) 2015 Google Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and/or associated documentation files (the
+"Materials"), to deal in the Materials without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Materials, and to
+permit persons to whom the Materials are furnished to do so, subject to
+the following conditions:
+
+The above copyright notice(s) and this permission notice shall be
+included in all copies or substantial portions of the Materials.
+
+The Materials are Confidential Information as defined by the
+Khronos Membership Agreement until designated non-confidential by
+Khronos, at which point this condition clause shall be removed.
+
+THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
--- /dev/null
+Vulkan CTS README
+=================
+
+This document describes how to build and run Vulkan Conformance Test suite.
+
+Vulkan CTS is built on dEQP framework. General dEQP documentation is available
+at http://source.android.com/devices/graphics/testing.html
+
+
+Requirements
+------------
+
+Common:
+ * Git (for checking out sources)
+ * Python 2.7.x (all recent versions in 2.x should work, 3.x is not supported)
+ * CMake 2.8 or newer
+
+Win32:
+ * Visual Studio 2013 (glslang uses several C++11 features)
+
+Linux:
+ * Standard toolchain (make, gcc/clang)
+
+
+Building
+--------
+
+To build dEQP, you need first to download sources for zlib, libpng, glslang,
+and spirv-tools.
+
+To download sources, run:
+
+$ python external/fetch_sources.py
+
+You may need to re-run fetch_sources.py to update to the latest glslang and
+spirv-tools revisions occasionally.
+
+NOTE: glslang integration is not yet available on Android due to a toolchain
+bug, so pre-compiled SPIR-V binaries must be used. See instructions below.
+
+
+Running
+-------
+
+Win32:
+
+> cd builddir/external/vulkancts/modules/vulkan
+> Debug/deqp-vk.exe
+
+Linux:
+
+$ cd builddir/external/vulkancts/modules/vulkan
+$ ./deqp-vk
+
+Android:
+
+Using Cherry is recommended. Alternatively you can follow instructions at
+http://source.android.com/devices/graphics/run-tests.html
+
+
+Pre-compiling SPIR-V binaries
+-----------------------------
+
+For distribution, and platforms that don't support GLSL to SPIR-V compilation,
+SPIR-V binaries must be pre-built with following command:
+
+$ python external/vulkancts/build_spirv_binaries.py
+
+Binaries will be written to external/vulkancts/data/vulkan/prebuilt/.
+
+Test modules (or in case of Android, the APK) must be re-built after building
+SPIR-V programs in order for the binaries to be available.
+
+
+Vulkan platform port
+--------------------
+
+Vulkan support from Platform implementation requires providing
+getVulkanPlatform() method in tcu::Platform class implementation.
+
+See framework/common/tcuPlatform.hpp and examples in
+framework/platform/win32/tcuWin32Platform.cpp and
+framework/platform/android/tcuAndroidPlatform.cpp.
+
+
+Null (dummy) driver
+-------------------
+
+For testing and development purposes it might be useful to be able to run
+tests on dummy Vulkan implementation. One such implementation is provided in
+vkNullDriver.cpp. To use that, implement vk::Platform::createLibrary() with
+vk::createNullDriver().
+
+
+Cherry GUI
+----------
+
+Vulkan test module can be used with Cherry (GUI for test execution and
+analysis). Cherry is available at
+https://android.googlesource.com/platform/external/cherry. Please follow
+instructions in README to get started.
+
+To enable support for Vulkan tests, dEQP-VK module must be added to list of
+test packages.
+
+In cherry/testrunner.go, add following line to testPackageDescriptors list
+(line 608 in NewTestRunner function):
+
+{"dEQP-VK", "deqp-vk", "../external/vulkancts/modules/vulkan", dataDir + "dEQP-VK-cases.xml"},
+
+Before first launch, and every time test hierarchy has been modified, test
+case list must be refreshed by running:
+
+$ python scripts/build_caselists.py path/to/cherry/data
+
+Cherry must be restarted for the case list update to take effect.
--- /dev/null
+# -*- coding: utf-8 -*-
+
+#-------------------------------------------------------------------------
+# Vulkan CTS
+# ----------
+#
+# Copyright (c) 2015 Google Inc.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and/or associated documentation files (the
+# "Materials"), to deal in the Materials without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Materials, and to
+# permit persons to whom the Materials are furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice(s) and this permission notice shall be
+# included in all copies or substantial portions of the Materials.
+#
+# The Materials are Confidential Information as defined by the
+# Khronos Membership Agreement until designated non-confidential by
+# Khronos, at which point this condition clause shall be removed.
+#
+# THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+#
+#-------------------------------------------------------------------------
+
+import os
+import sys
+import string
+import argparse
+import tempfile
+import shutil
+import fnmatch
+
+sys.path.append(os.path.join(os.path.dirname(__file__), "..", "..", "scripts"))
+
+from build.common import *
+from build.config import *
+from build.build import *
+
+class Module:
+ def __init__ (self, name, dirName, binName):
+ self.name = name
+ self.dirName = dirName
+ self.binName = binName
+
+VULKAN_MODULE = Module("dEQP-VK", "../external/vulkancts/modules/vulkan", "deqp-vk")
+DEFAULT_BUILD_DIR = os.path.join(tempfile.gettempdir(), "spirv-binaries", "{targetName}-{buildType}")
+DEFAULT_TARGET = "null"
+DEFAULT_DST_DIR = os.path.join(DEQP_DIR, "external", "vulkancts", "data", "vulkan", "prebuilt")
+
+def getBuildConfig (buildPathPtrn, targetName, buildType):
+ buildPath = buildPathPtrn.format(
+ targetName = targetName,
+ buildType = buildType)
+
+ return BuildConfig(buildPath, buildType, ["-DDEQP_TARGET=%s" % targetName])
+
+def cleanDstDir (dstPath):
+ binFiles = [f for f in os.listdir(dstPath) if os.path.isfile(os.path.join(dstPath, f)) and fnmatch.fnmatch(f, "*.spirv")]
+
+ for binFile in binFiles:
+ print "Removing %s" % os.path.join(dstPath, binFile)
+ os.remove(os.path.join(dstPath, binFile))
+
+def execBuildPrograms (buildCfg, generator, module, mode, dstPath):
+ workDir = os.path.join(buildCfg.getBuildDir(), "modules", module.dirName)
+
+ pushWorkingDir(workDir)
+
+ try:
+ binPath = generator.getBinaryPath(buildCfg.getBuildType(), os.path.join(".", "vk-build-programs"))
+ execute([binPath, "--mode", mode, "--dst-path", dstPath])
+ finally:
+ popWorkingDir()
+
+def parseArgs ():
+ parser = argparse.ArgumentParser(description = "Build SPIR-V programs",
+ formatter_class=argparse.ArgumentDefaultsHelpFormatter)
+ parser.add_argument("-b",
+ "--build-dir",
+ dest="buildDir",
+ default=DEFAULT_BUILD_DIR,
+ help="Temporary build directory")
+ parser.add_argument("-t",
+ "--build-type",
+ dest="buildType",
+ default="Debug",
+ help="Build type")
+ parser.add_argument("-c",
+ "--deqp-target",
+ dest="targetName",
+ default=DEFAULT_TARGET,
+ help="dEQP build target")
+ parser.add_argument("--mode",
+ dest="mode",
+ default="build",
+ help="Build mode (build or verify)")
+ parser.add_argument("-d",
+ "--dst-path",
+ dest="dstPath",
+ default=DEFAULT_DST_DIR,
+ help="Destination path")
+ return parser.parse_args()
+
+if __name__ == "__main__":
+ args = parseArgs()
+
+ generator = ANY_GENERATOR
+ buildCfg = getBuildConfig(args.buildDir, args.targetName, args.buildType)
+ module = VULKAN_MODULE
+
+ build(buildCfg, generator, ["vk-build-programs"])
+
+ if args.mode == "build":
+ if os.path.exists(args.dstPath):
+ cleanDstDir(args.dstPath)
+ else:
+ os.makedirs(args.dstPath)
+
+ execBuildPrograms(buildCfg, generator, module, args.mode, args.dstPath)
--- /dev/null
+#X1. Type: float[5] // An array type with 5 elements
+#X2. Return value: float[5] func() { ... } // Function with a 5-element array return value
+#X3. Array constructor: float[3] (1.0, 2.0, 5.5) // 3-element array with given elements
+# // Fails with array of matrices!
+#X4. As unnamed parameter: void func(float[5]);
+#X5. Variable declaration: float[5] a; // Equivalent to float a[5]; (?)
+#X6. Empty brackets: float x[] = float[] (1.0, 2.0, 3.0); // Size of x is 3
+# float y[] = float[3] (1.0, 2.0, 3.0); // Size of y is 3 (equivalent)
+# float z[] = y; // Size of z is 3
+#X7. Testing that 2-dimensional arrays don't work: float a[5][3]; // Illegal
+# float[5] a[3]; // Illegal
+#X8. Testing that array declaration with dynamic variables as array size won't work.
+#X9. Testing length() operator: z.length(); // Returns 3 for z defined before
+#X10. Test C/C++ style {}-constructor
+#X11. Test struct arrays
+#X12. Test array element access at initialization with const/dynamic values
+
+group constructor "Array constructors"
+
+ case float3
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) | vec3(7.4, -1.0, 2.0) | vec3(3.0, 1.6, -2.0) ];
+ output vec3 out0 = [ vec3(2.0, 0.5, 1.0) | vec3(2.0, 7.4, -1.0) | vec3(-2.0, 3.0, 1.6) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float[3] x;
+ x = float[3] (in0.z, in0.x, in0.y);
+ out0 = vec3(x[0], x[1], x[2]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float4
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.5, 1.0, 2.0, 0.2) | vec4(7.4, -1.0, 2.0, -1.3) | vec4(3.0, 1.6, -2.0, 0.5) ];
+ output vec4 out0 = [ vec4(2.0, 0.5, 0.2, 1.0) | vec4(2.0, 7.4, -1.3, -1.0) | vec4(-2.0, 3.0, 0.5, 1.6) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float[4] x;
+ x = float[4] (in0.z, in0.x, in0.w, in0.y);
+ out0 = vec4(x[0], x[1], x[2], x[3]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int3
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 1, 2) | ivec3(7, -1, 2) | ivec3(3, 1, -2) ];
+ output ivec3 out0 = [ ivec3(2, 0, 1) | ivec3(2, 7, -1) | ivec3(-2, 3, 1) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump int;
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ int[3] x;
+ x = int[3] (in0.z, in0.x, in0.y);
+ out0 = ivec3(x[0], x[1], x[2]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int4
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 1, 2, 0) | ivec4(7, -1, 2, -1) | ivec4(3, 1, -2, 0) ];
+ output ivec4 out0 = [ ivec4(2, 0, 0, 1) | ivec4(2, 7, -1, -1) | ivec4(-2, 3, 0, 1) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump int;
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ int[4] x;
+ x = int[4] (in0.z, in0.x, in0.w, in0.y);
+ out0 = ivec4(x[0], x[1], x[2], x[3]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool3
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, true, false) ];
+ output bvec3 out0 = [ bvec3(false, true, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bool[3] x;
+ x = bool[3] (in0.z, in0.x, in0.y);
+ out0 = bvec3(x[0], x[1], x[2]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool4
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, true, false, false) ];
+ output bvec4 out0 = [ bvec4(false, true, true, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bool[4] x;
+ x = bool[4] (in0.z, in0.x, in0.y, in0.w);
+ out0 = bvec4(x[0], x[1], x[2], x[3]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case struct3
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) ];
+ output vec3 out0 = [ vec3(2.0, -0.5, -1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+
+
+ void main()
+ {
+ ${SETUP}
+
+ struct test
+ {
+ float f;
+ vec3 v;
+ };
+
+ test a = test(in0.z, vec3(in0.x, in0.y, in0.z));
+ test b = test(in0.y, vec3(-in0.z, -in0.x, -in0.y));
+ test c = test(in0.x, vec3(-in0.y, in0.z, -in0.x));
+
+ test[3] x = test[3] (a, b, c);
+
+ out0 = vec3(x[0].f, x[1].v.y, x[2].v.x);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case struct4
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.5, 1.0, 2.0, 1.5) ];
+ output vec4 out0 = [ vec4(2.0, -0.5, -1.0, -1.5) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+
+ void main()
+ {
+ ${SETUP}
+
+
+ struct test
+ {
+ float f;
+ vec3 v;
+ };
+
+ test a = test(in0.z, vec3(in0.x, in0.y, in0.z));
+ test b = test(in0.y, vec3(-in0.z, -in0.x, -in0.y));
+ test c = test(in0.x, vec3(-in0.y, in0.z, -in0.x));
+ test d = test(-in0.w, vec3(-in0.w, -in0.x, -in0.z));
+
+ test[4] x = test[4] (a, b, c, d);
+
+ out0 = vec4(x[0].f, x[1].v.y, x[2].v.x, x[3].v.x);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case float_vec3
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) | vec3(7.4, -1.0, 2.0) | vec3(3.0, 1.6, -2.0) ];
+ output vec3 out0 = [ vec3(0.5, -2.0, 1.0) | vec3(7.4, -2.0, -1.0) | vec3(3.0, 2.0, 1.6) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+
+ vec3[3] x;
+ x = vec3[3] ( vec3(in0.x, in0.y, in0.z) ,
+ vec3(-in0.y, -in0.z, -in0.x),
+ vec3(in0.z, in0.x, in0.y) );
+ out0 = vec3(x[0].x, x[1].y, x[2].z);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_vec3
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(5, 1, 2) | ivec3(7, -1, 2) | ivec3(3, 1, -2) ];
+ output ivec3 out0 = [ ivec3(5, -2, 1) | ivec3(7, -2, -1) | ivec3(3, 2, 1) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump int;
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+
+ ivec3[3] x;
+ x = ivec3[3] ( ivec3(in0.x, in0.y, in0.z) ,
+ ivec3(-in0.y, -in0.z, -in0.x),
+ ivec3(in0.z, in0.x, in0.y) );
+ out0 = ivec3(x[0].x, x[1].y, x[2].z);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_vec3
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, true) ];
+ output bvec3 out0 = [ bvec3(true, true, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+
+ bvec3[3] x;
+ x = bvec3[3] ( bvec3(in0.x, in0.y, in0.z) ,
+ bvec3(in0.y, in0.z, in0.x),
+ bvec3(in0.z, in0.x, in0.y) );
+ out0 = bvec3(x[0].x, x[1].y, x[2].z);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_mat3
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) | vec3(-1.5, 0.0, -2.3) ];
+ output vec3 out0 = [ vec3(0.5, -1.0, 1.0) | vec3(-1.5, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ mat3[3] a = mat3[3] ( mat3( in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z) ,
+ mat3( in0.z, in0.x, -in0.y,
+ in0.z, in0.x, -in0.y,
+ in0.z, in0.x, -in0.y) ,
+ mat3( -in0.z, -in0.z, in0.z,
+ -in0.y, -in0.y, in0.y,
+ -in0.x, -in0.x, in0.x) );
+
+ mat3 a0 = a[0];
+ mat3 a1 = a[1];
+ mat3 a2 = a[2];
+
+ float ret0 = a0[2][0];
+ float ret1 = a1[0][2];
+ float ret2 = a2[1][2];
+
+ out0 = vec3(ret0, ret1, ret2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_mat3
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 1, 2) | ivec3(-1, 0, -2) ];
+ output ivec3 out0 = [ ivec3(0, -1, 1) | ivec3(-1, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump int;
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ mat3[3] a = mat3[3] ( mat3( in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z) ,
+ mat3( in0.z, in0.x, -in0.y,
+ in0.z, in0.x, -in0.y,
+ in0.z, in0.x, -in0.y) ,
+ mat3( -in0.z, -in0.z, in0.z,
+ -in0.y, -in0.y, in0.y,
+ -in0.x, -in0.x, in0.x) );
+
+ mat3 a0 = a[0];
+ mat3 a1 = a[1];
+ mat3 a2 = a[2];
+
+ float ret0 = a0[2][0];
+ float ret1 = a1[0][2];
+ float ret2 = a2[1][2];
+
+ out0 = ivec3(ret0, ret1, ret2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_mat3
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, true) ];
+ output bvec3 out0 = [ bvec3(true, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ mat3[3] a = mat3[3] ( mat3( in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z) ,
+ mat3( in0.z, in0.x, in0.y,
+ in0.z, in0.x, in0.y,
+ in0.z, in0.x, in0.y) ,
+ mat3( in0.z, in0.z, in0.z,
+ in0.y, in0.y, in0.y,
+ in0.x, in0.x, in0.x) );
+
+ mat3 a0 = a[0];
+ mat3 a1 = a[1];
+ mat3 a2 = a[2];
+
+ float ret0 = a0[2][0];
+ float ret1 = a1[0][2];
+ float ret2 = a2[1][2];
+
+ out0 = bvec3(ret0, ret1, ret2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # type
+
+group return "Arrays as return value"
+
+ case float
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) | vec3(7.4, -1.0, 2.0) | vec3(3.0, 1.6, -2.0) ];
+ output vec3 out0 = [ vec3(2.0, -0.5, 1.0) | vec3(2.0, -7.4, -1.0) | vec3(-2.0, -3.0, 1.6) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float[3] func(vec3 a)
+ {
+ return float[3] (a.z, -a.x, a.y);
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float[3] x = func(in0);
+ out0 = vec3(x[0], x[1], x[2]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(4, 1, 2) | ivec3(7, -1, 2) | ivec3(3, 1, -2) ];
+ output ivec3 out0 = [ ivec3(2, -4, 1) | ivec3(2, -7, -1) | ivec3(-2, -3, 1) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump int;
+ precision mediump float;
+ ${DECLARATIONS}
+
+ int[3] func(ivec3 a)
+ {
+ return int[3] (a.z, -a.x, a.y);
+ }
+
+ void main()
+ {
+ ${SETUP}
+ int[3] x = func(in0);
+ out0 = ivec3(x[0], x[1], x[2]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(false, true, true) ];
+ output bvec3 out0 = [ bvec3(true, false, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ bool[3] func(bvec3 a)
+ {
+ return bool[3] (a.z, a.x, a.y);
+ }
+
+ void main()
+ {
+ ${SETUP}
+ bool[3] x = func(in0);
+ out0 = bvec3(x[0], x[1], x[2]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+
+ case float_vec3
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) | vec3(-0.5, 11.2, -1.0) ];
+ output vec3 out0 = [ vec3(1.0, 0.5, -2.0) | vec3(11.2, -0.5, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ vec3[3] func(vec3[3] a)
+ {
+ return vec3[3] (a[1], a[2], a[0]);
+ }
+
+ void main()
+ {
+ ${SETUP}
+ vec3[3] x = vec3[3](vec3(in0.x, in0.y, -in0.z) ,
+ vec3(in0.y, -in0.z, in0.x) ,
+ vec3(-in0.z, in0.x, in0.y) );
+ x = func(x);
+ out0 = vec3(x[0].x, x[1].y, x[2].z);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case struct
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) ];
+ output vec3 out0 = [ vec3(-1.0, 2.0, 0.5) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ struct test
+ {
+ float f;
+ vec3 v;
+ };
+
+ test[3] func(test[3] a)
+ {
+ return test[3] (a[1], a[2], a[0]);
+ }
+
+ void main()
+ {
+ ${SETUP}
+
+ test a = test(in0.z, vec3(in0.x, in0.y, in0.z));
+ test b = test(in0.y, vec3(-in0.z, -in0.x, -in0.y));
+ test c = test(in0.x, vec3(-in0.y, in0.z, -in0.x));
+
+ test[3] t = test[3] (a, b, c);
+ test[3] x = func(t);
+
+ out0 = vec3(x[0].v.z, x[1].v.y, x[2].v.x);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_vec3
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(5, 1, 2) | ivec3(-5, 11, -1) ];
+ output ivec3 out0 = [ ivec3(1, 5, -2) | ivec3(11, -5, 1) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump int;
+ precision mediump float;
+ ${DECLARATIONS}
+
+ ivec3[3] func(ivec3[3] a)
+ {
+ return ivec3[3] (a[1], a[2], a[0]);
+ }
+
+ void main()
+ {
+ ${SETUP}
+ ivec3[3] x = ivec3[3]( ivec3(in0.x, in0.y, -in0.z) ,
+ ivec3(in0.y, -in0.z, in0.x) ,
+ ivec3(-in0.z, in0.x, in0.y) );
+ x = func(x);
+ out0 = ivec3(x[0].x, x[1].y, x[2].z);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_vec3
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) ];
+ output bvec3 out0 = [ bvec3(false, true, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump int;
+ precision mediump float;
+ ${DECLARATIONS}
+
+ bvec3[3] func(bvec3[3] a)
+ {
+ return bvec3[3] (a[1], a[2], a[0]);
+ }
+
+ void main()
+ {
+ ${SETUP}
+ bvec3[3] x = bvec3[3]( bvec3(in0.x, in0.y, in0.z) ,
+ bvec3(in0.y, in0.z, in0.x) ,
+ bvec3(in0.z, in0.x, in0.y) );
+ x = func(x);
+ out0 = bvec3(x[0].x, x[1].y, x[2].z);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_mat3
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) | vec3(-1.5, 0.0, -2.3) ];
+ output vec3 out0 = [ vec3(2.0, -1.0, 2.0) | vec3(-2.3, 0.0, -2.3) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ mat3[3] func(mat3[3] x)
+ {
+ mat3[3] r;
+ r[0] = x[1];
+ r[1] = x[2];
+ r[2] = x[0];
+ return r;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ mat3[3] a, b;
+ a[0] = mat3(in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z);
+ a[1] = mat3(in0.z, in0.x, -in0.y,
+ in0.z, in0.x, -in0.y,
+ in0.z, in0.x, -in0.y);
+ a[2] = mat3(-in0.z, -in0.z, in0.z,
+ -in0.y, -in0.y, in0.y,
+ -in0.x, -in0.x, in0.x);
+
+ b = func(a);
+
+ mat3 b0 = b[0];
+ mat3 b1 = b[1];
+ mat3 b2 = b[2];
+
+ float ret0 = b0[0][0];
+ float ret1 = b1[1][1];
+ float ret2 = b2[2][2];
+
+ out0 = vec3(ret0, ret1, ret2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_mat3
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(5, 1, 2) | ivec3(-1, 0, -2) ];
+ output ivec3 out0 = [ ivec3(2, -1, 2) | ivec3(-2, 0, -2) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump int;
+ precision mediump float;
+ ${DECLARATIONS}
+
+ mat3[3] func(mat3[3] x)
+ {
+ mat3[3] r;
+ r[0] = x[1];
+ r[1] = x[2];
+ r[2] = x[0];
+ return r;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ mat3[3] a, b;
+ a[0] = mat3(in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z);
+ a[1] = mat3(in0.z, in0.x, -in0.y,
+ in0.z, in0.x, -in0.y,
+ in0.z, in0.x, -in0.y);
+ a[2] = mat3(-in0.z, -in0.z, in0.z,
+ -in0.y, -in0.y, in0.y,
+ -in0.x, -in0.x, in0.x);
+
+ b = func(a);
+
+ mat3 b0 = b[0];
+ mat3 b1 = b[1];
+ mat3 b2 = b[2];
+
+ float ret0 = b0[0][0];
+ float ret1 = b1[1][1];
+ float ret2 = b2[2][2];
+
+ out0 = ivec3(ret0, ret1, ret2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_mat3
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, true) | bvec3(true, true, false) ];
+ output bvec3 out0 = [ bvec3(true, false, true) | bvec3(false, true, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ mat3[3] func(mat3[3] x)
+ {
+ mat3[3] r;
+ r[0] = x[1];
+ r[1] = x[2];
+ r[2] = x[0];
+ return r;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ mat3[3] a, b;
+ a[0] = mat3(in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z);
+ a[1] = mat3(in0.z, in0.x, in0.y,
+ in0.z, in0.x, in0.y,
+ in0.z, in0.x, in0.y);
+ a[2] = mat3(in0.z, in0.z, in0.z,
+ in0.y, in0.y, in0.y,
+ in0.x, in0.x, in0.x);
+
+ b = func(a);
+
+ mat3 b0 = b[0];
+ mat3 b1 = b[1];
+ mat3 b2 = b[2];
+
+ float ret0 = b0[0][0];
+ float ret1 = b1[1][1];
+ float ret2 = b2[2][2];
+
+ out0 = bvec3(ret0, ret1, ret2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # return
+
+group unnamed_parameter "Array type as unnamed parameter of a function prototype"
+
+ case float
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) | vec3(7.4, -1.0, 2.0) | vec3(3.0, 1.6, -2.0) ];
+ output vec3 out0 = [ vec3(2.0, 0.5, 1.0) | vec3(2.0, 7.4, -1.0) | vec3(-2.0, 3.0, 1.6) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float[3] func(float[3]);
+
+ void main()
+ {
+ ${SETUP}
+ float[3] a = float[3] (in0.x, in0.y, in0.z);
+ float[3] b = func(a);
+ out0 = vec3(b[0], b[1], b[2]);
+ ${OUTPUT}
+ }
+
+ float[3] func(float[3] a)
+ {
+ return float[3] (a[2], a[0], a[1]);
+ }
+
+ ""
+ end
+
+ case int
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 1, 2) | ivec3(7, -1, 2) | ivec3(3, 1, -2) ];
+ output ivec3 out0 = [ ivec3(2, 0, 1) | ivec3(2, 7, -1) | ivec3(-2, 3, 1) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump int;
+ precision mediump float;
+ ${DECLARATIONS}
+
+ int[3] func(int[3]);
+
+ void main()
+ {
+ ${SETUP}
+ int[3] a = int[3] (in0.x, in0.y, in0.z);
+ int[3] b = func(a);
+ out0 = ivec3(b[0], b[1], b[2]);
+ ${OUTPUT}
+ }
+
+ int[3] func(int[3] a)
+ {
+ return int[3] (a[2], a[0], a[1]);
+ }
+
+ ""
+ end
+
+ case bool
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(false, true, true) ];
+ output bvec3 out0 = [ bvec3(true, false, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ bool[3] func(bool[3]);
+
+ void main()
+ {
+ ${SETUP}
+ bool[3] a = bool[3] (in0.x, in0.y, in0.z);
+ bool[3] b = func(a);
+ out0 = bvec3(b[0], b[1], b[2]);
+ ${OUTPUT}
+ }
+
+ bool[3] func(bool[3] a)
+ {
+ return bool[3] (a[2], a[0], a[1]);
+ }
+
+ ""
+ end
+
+ case struct
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) ];
+ output vec3 out0 = [ vec3(-1.0, 2.0, 0.5) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ struct test
+ {
+ float f;
+ vec3 v;
+ };
+
+ test[3] func(test[3]);
+
+ void main()
+ {
+ ${SETUP}
+
+ test a = test(in0.z, vec3(in0.x, in0.y, in0.z));
+ test b = test(in0.y, vec3(-in0.z, -in0.x, -in0.y));
+ test c = test(in0.x, vec3(-in0.y, in0.z, -in0.x));
+
+ test[3] t = test[3] (a, b, c);
+ test[3] x = func(t);
+ out0 = vec3(x[0].v.z, x[1].v.y, x[2].v.x);
+ ${OUTPUT}
+ }
+
+ test[3] func(test[3] a)
+ {
+ return test[3] (a[1], a[2], a[0]);
+ }
+
+ ""
+ end
+
+ case float_vec3
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) | vec3(-0.5, 11.2, -1.0) ];
+ output vec3 out0 = [ vec3(1.0, 0.5, -2.0) | vec3(11.2, -0.5, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ vec3[3] func(vec3[3]);
+
+ void main()
+ {
+ ${SETUP}
+ vec3[3] x = vec3[3](vec3(in0.x, in0.y, -in0.z) ,
+ vec3(in0.y, -in0.z, in0.x) ,
+ vec3(-in0.z, in0.x, in0.y) );
+ x = func(x);
+ out0 = vec3(x[0].x, x[1].y, x[2].z);
+ ${OUTPUT}
+ }
+
+ vec3[3] func(vec3[3] a)
+ {
+ return vec3[3] (a[1], a[2], a[0]);
+ }
+ ""
+ end
+
+ case int_vec3
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(5, 1, 2) | ivec3(-5, 11, -1) ];
+ output ivec3 out0 = [ ivec3(1, 5, -2) | ivec3(11, -5, 1) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump int;
+ precision mediump float;
+ ${DECLARATIONS}
+
+ ivec3[3] func(ivec3[3]);
+
+ void main()
+ {
+ ${SETUP}
+ ivec3[3] x = ivec3[3]( ivec3(in0.x, in0.y, -in0.z) ,
+ ivec3(in0.y, -in0.z, in0.x) ,
+ ivec3(-in0.z, in0.x, in0.y) );
+ x = func(x);
+ out0 = ivec3(x[0].x, x[1].y, x[2].z);
+ ${OUTPUT}
+ }
+
+ ivec3[3] func(ivec3[3] a)
+ {
+ return ivec3[3] (a[1], a[2], a[0]);
+ }
+ ""
+ end
+
+ case bool_vec3
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) ];
+ output bvec3 out0 = [ bvec3(false, true, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump int;
+ precision mediump float;
+ ${DECLARATIONS}
+
+ bvec3[3] func(bvec3[3]);
+
+ void main()
+ {
+ ${SETUP}
+ bvec3[3] x = bvec3[3]( bvec3(in0.x, in0.y, in0.z) ,
+ bvec3(in0.y, in0.z, in0.x) ,
+ bvec3(in0.z, in0.x, in0.y) );
+ x = func(x);
+ out0 = bvec3(x[0].x, x[1].y, x[2].z);
+ ${OUTPUT}
+ }
+
+ bvec3[3] func(bvec3[3] a)
+ {
+ return bvec3[3] (a[1], a[2], a[0]);
+ }
+
+ ""
+ end
+
+ case float_mat3
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) | vec3(-1.5, 0.0, -2.3) ];
+ output vec3 out0 = [ vec3(2.0, -1.0, 2.0) | vec3(-2.3, 0.0, -2.3) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ mat3[3] func(mat3[3]);
+
+ void main()
+ {
+ ${SETUP}
+ mat3[3] a, b;
+ a[0] = mat3(in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z);
+ a[1] = mat3(in0.z, in0.x, -in0.y,
+ in0.z, in0.x, -in0.y,
+ in0.z, in0.x, -in0.y);
+ a[2] = mat3(-in0.z, -in0.z, in0.z,
+ -in0.y, -in0.y, in0.y,
+ -in0.x, -in0.x, in0.x);
+
+ b = func(a);
+
+ mat3 b0 = b[0];
+ mat3 b1 = b[1];
+ mat3 b2 = b[2];
+
+ float ret0 = b0[0][0];
+ float ret1 = b1[1][1];
+ float ret2 = b2[2][2];
+
+ out0 = vec3(ret0, ret1, ret2);
+ ${OUTPUT}
+ }
+
+ mat3[3] func(mat3[3] x)
+ {
+ mat3[3] r;
+ r[0] = x[1];
+ r[1] = x[2];
+ r[2] = x[0];
+ return r;
+ }
+ ""
+ end
+
+ case int_mat3
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(5, 1, 2) | ivec3(-1, 0, -2) ];
+ output ivec3 out0 = [ ivec3(2, -1, 2) | ivec3(-2, 0, -2) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump int;
+ precision mediump float;
+ ${DECLARATIONS}
+
+ mat3[3] func(mat3[3]);
+
+ void main()
+ {
+ ${SETUP}
+ mat3[3] a, b;
+ a[0] = mat3(in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z);
+ a[1] = mat3(in0.z, in0.x, -in0.y,
+ in0.z, in0.x, -in0.y,
+ in0.z, in0.x, -in0.y);
+ a[2] = mat3(-in0.z, -in0.z, in0.z,
+ -in0.y, -in0.y, in0.y,
+ -in0.x, -in0.x, in0.x);
+
+ b = func(a);
+
+ mat3 b0 = b[0];
+ mat3 b1 = b[1];
+ mat3 b2 = b[2];
+
+ float ret0 = b0[0][0];
+ float ret1 = b1[1][1];
+ float ret2 = b2[2][2];
+
+ out0 = ivec3(ret0, ret1, ret2);
+ ${OUTPUT}
+ }
+
+ mat3[3] func(mat3[3] x)
+ {
+ mat3[3] r;
+ r[0] = x[1];
+ r[1] = x[2];
+ r[2] = x[0];
+ return r;
+ }
+ ""
+ end
+
+ case bool_mat3
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, true) | bvec3(true, true, false) ];
+ output bvec3 out0 = [ bvec3(true, false, true) | bvec3(false, true, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ mat3[3] func(mat3[3]);
+ void main()
+ {
+ ${SETUP}
+ mat3[3] a, b;
+ a[0] = mat3(in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z);
+ a[1] = mat3(in0.z, in0.x, in0.y,
+ in0.z, in0.x, in0.y,
+ in0.z, in0.x, in0.y);
+ a[2] = mat3(in0.z, in0.z, in0.z,
+ in0.y, in0.y, in0.y,
+ in0.x, in0.x, in0.x);
+
+ b = func(a);
+
+ mat3 b0 = b[0];
+ mat3 b1 = b[1];
+ mat3 b2 = b[2];
+
+ float ret0 = b0[0][0];
+ float ret1 = b1[1][1];
+ float ret2 = b2[2][2];
+
+ out0 = bvec3(ret0, ret1, ret2);
+ ${OUTPUT}
+ }
+
+ mat3[3] func(mat3[3] x)
+ {
+ mat3[3] r;
+ r[0] = x[1];
+ r[1] = x[2];
+ r[2] = x[0];
+ return r;
+ }
+ ""
+ end
+
+end # unnamed_parameter
+
+group declaration "Declaring arrays"
+
+ case implicit_size_float
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) | vec3(7.4, -1.0, 2.0) | vec3(3.0, 1.6, -2.0) ];
+ output vec3 out0 = [ vec3(2.0, 0.5, 1.0) | vec3(2.0, 7.4, -1.0) | vec3(-2.0, 3.0, 1.6) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float[] x = float[] (in0.z, in0.x, in0.y);
+ float[] y = x;
+
+ out0 = vec3(y[0], y[1], y[2]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case implicit_size_int
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 1, 2) | ivec3(7, -1, 2) | ivec3(3, 1, -2) ];
+ output ivec3 out0 = [ ivec3(2, 0, 1) | ivec3(2, 7, -1) | ivec3(-2, 3, 1) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump int;
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ int[] x = int[] (in0.z, in0.x, in0.y);
+ int[] y = x;
+
+ out0 = ivec3(y[0], y[1], y[2]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case implicit_size_bool
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(false, true, true) ];
+ output bvec3 out0 = [ bvec3(true, false, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bool[] x = bool[] (in0.z, in0.x, in0.y);
+ bool[] y = x;
+
+ out0 = bvec3(y[0], y[1], y[2]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case implicit_size_struct
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) ];
+ output vec3 out0 = [ vec3(-1.0, -0.5, 2.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ struct test
+ {
+ float f;
+ vec3 v;
+ };
+
+ void main()
+ {
+ ${SETUP}
+
+ test a = test(in0.z, vec3(in0.x, in0.y, in0.z));
+ test b = test(in0.y, vec3(-in0.z, -in0.x, -in0.y));
+ test c = test(in0.x, vec3(-in0.y, in0.z, -in0.x));
+
+ test[] x = test[] (c, b, a);
+ test[] y = x;
+
+ out0 = vec3(y[0].v.x, y[1].v.y, y[2].v.z);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case implicit_size_float_vec3
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) | vec3(-0.5, 11.2, -1.0) ];
+ output vec3 out0 = [ vec3(0.5, -2.0, 1.0) | vec3(-0.5, 1.0, 11.2) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ vec3[] x = vec3[] ( vec3(in0.x, in0.y, -in0.z) ,
+ vec3(in0.y, -in0.z, in0.x) ,
+ vec3(-in0.z, in0.x, in0.y) );
+ vec3[] y = x;
+ out0 = vec3(y[0].x, y[1].y, y[2].z);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case implicit_size_int_ivec3
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 1, 2) | ivec3(5, 11, -1) ];
+ output ivec3 out0 = [ ivec3(0, -2, 1) | ivec3(5, 1, 11) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump int;
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ ivec3[] x = ivec3[] ( ivec3(in0.x, in0.y, -in0.z) ,
+ ivec3(in0.y, -in0.z, in0.x) ,
+ ivec3(-in0.z, in0.x, in0.y) );
+ ivec3[] y = x;
+ out0 = ivec3(y[0].x, y[1].y, y[2].z);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case implicit_size_bool_bvec3
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, true) ];
+ output bvec3 out0 = [ bvec3(true, true, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bvec3[] x = bvec3[] ( bvec3(in0.x, in0.y, in0.z) ,
+ bvec3(in0.y, in0.z, in0.x) ,
+ bvec3(in0.z, in0.x, in0.y) );
+ bvec3[] y = x;
+ out0 = bvec3(y[0].x, y[1].y, y[2].z);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case implicit_size_float_mat3
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) | vec3(-1.5, 0.0, -2.3) ];
+ output vec3 out0 = [ vec3(0.5, -1.0, 1.0) | vec3(-1.5, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ mat3[] a = mat3[] ( mat3( in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z) ,
+ mat3( in0.z, in0.x, -in0.y,
+ in0.z, in0.x, -in0.y,
+ in0.z, in0.x, -in0.y) ,
+ mat3( -in0.z, -in0.z, in0.z,
+ -in0.y, -in0.y, in0.y,
+ -in0.x, -in0.x, in0.x) );
+
+ mat3 a0 = a[0];
+ mat3 a1 = a[1];
+ mat3 a2 = a[2];
+
+ float ret0 = a0[2][0];
+ float ret1 = a1[0][2];
+ float ret2 = a2[1][2];
+
+ out0 = vec3(ret0, ret1, ret2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case implicit_size_int_mat3
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 1, 2) | ivec3(-1, 0, -2) ];
+ output ivec3 out0 = [ ivec3(0, -1, 1) | ivec3(-1, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump int;
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ mat3[] a = mat3[] ( mat3( in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z) ,
+ mat3( in0.z, in0.x, -in0.y,
+ in0.z, in0.x, -in0.y,
+ in0.z, in0.x, -in0.y) ,
+ mat3( -in0.z, -in0.z, in0.z,
+ -in0.y, -in0.y, in0.y,
+ -in0.x, -in0.x, in0.x) );
+
+ mat3 a0 = a[0];
+ mat3 a1 = a[1];
+ mat3 a2 = a[2];
+
+ float ret0 = a0[2][0];
+ float ret1 = a1[0][2];
+ float ret2 = a2[1][2];
+
+ out0 = ivec3(ret0, ret1, ret2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case implicit_size_bool_mat3
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, true) ];
+ output bvec3 out0 = [ bvec3(true, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ mat3[] a = mat3[] ( mat3( in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z,
+ in0.x, in0.y, in0.z) ,
+ mat3( in0.z, in0.x, in0.y,
+ in0.z, in0.x, in0.y,
+ in0.z, in0.x, in0.y) ,
+ mat3( in0.z, in0.z, in0.z,
+ in0.y, in0.y, in0.y,
+ in0.x, in0.x, in0.x) );
+
+ mat3 a0 = a[0];
+ mat3 a1 = a[1];
+ mat3 a2 = a[2];
+
+ float ret0 = a0[2][0];
+ float ret1 = a1[0][2];
+ float ret2 = a2[1][2];
+
+ out0 = bvec3(ret0, ret1, ret2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case constant_expression_array_size
+ version 310 es
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ const int a = 4;
+
+ void main ()
+ {
+ const int b = 5;
+ float[a] array1;
+ float[b] array2;
+ float[array1.length()] array3;
+ float[a+b] array4;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case constant_expression_array_access
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) ];
+ output vec3 out0 = [ vec3(-2.0, -1.0, -0.5) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ const int a = 3;
+
+ void main ()
+ {
+ ${SETUP}
+ const int b = 2;
+ float x = float[] (in0.x, in0.y, in0.z, -in0.z, -in0.y, -in0.x) [a];
+ float y = float[] (in0.x, in0.y, in0.z, -in0.z, -in0.y, -in0.x) [b+2];
+ float z = float[] (in0.x, in0.y, in0.z, -in0.z, -in0.y, -in0.x) [5];
+ out0 = vec3(x, y, z);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case dynamic_expression_array_access
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) ];
+ input ivec2 in1 = ivec2(3, 2);
+ output vec3 out0 = [ vec3(-2.0, -1.0, -0.5) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ ${SETUP}
+ float x = float[] (in0.x, in0.y, in0.z, -in0.z, -in0.y, -in0.x) [in1.x];
+ float y = float[] (in0.x, in0.y, in0.z, -in0.z, -in0.y, -in0.x) [in1.y+2];
+ float z = float[] (in0.x, in0.y, in0.z, -in0.z, -in0.y, -in0.x) [in1.x+in1.y];
+ out0 = vec3(x, y, z);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case multiple_declarations_single_statement_explicit
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) ];
+ output vec3 out0 = [ vec3(2.0, -1.0, 0.5) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ ${SETUP}
+ float[] x = float[6] (in0.x, in0.y, in0.z, -in0.z, -in0.y, -in0.x),
+ y = float[2] (in0.x, -in0.y);
+ out0 = vec3(x[2], y[1], x[0]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case multiple_declarations_single_statement_implicit
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(5, 1, 2) ];
+ output ivec3 out0 = [ ivec3(2, -1, 5) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main ()
+ {
+ ${SETUP}
+ int[] x = int[] (in0.x, in0.y, in0.z, -in0.z, -in0.y, -in0.x),
+ y = int[] (in0.x, -in0.y);
+ out0 = ivec3(x[2], y[1], x[0]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # declaration
+
+group length "Array length method"
+
+ case float
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) ];
+ output ivec3 out0 = [ ivec3(3, 5, 13) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ float[] x = float[3] (in0.z, in0.x, in0.y);
+ float[] y = float[] (in0.z, in0.x, in0.y, in0.x, in0.y);
+ float[13] z;
+
+ out0 = ivec3(x.length(), y.length(), z.length());
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 1, 2) ];
+ output ivec3 out0 = [ ivec3(3, 5, 13) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump int;
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ int[] x = int[3] (in0.z, in0.x, in0.y);
+ int[] y = int[] (in0.z, in0.x, in0.y, in0.x, in0.y);
+ int[13] z;
+
+ out0 = ivec3(x.length(), y.length(), z.length());
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, true) ];
+ output ivec3 out0 = [ ivec3(3, 5, 13) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ bool[] x = bool[3] (in0.z, in0.x, in0.y);
+ bool[] y = bool[] (in0.z, in0.x, in0.y, in0.x, in0.y);
+ bool[13] z;
+
+ out0 = ivec3(x.length(), y.length(), z.length());
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case struct
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 1.0, 2.0) ];
+ output ivec3 out0 = [ ivec3(3, 5, 13) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ struct test
+ {
+ float f;
+ vec3 v;
+ };
+
+ void main()
+ {
+ ${SETUP}
+
+ test a = test(in0.z, vec3(in0.x, in0.y, in0.z));
+ test b = test(in0.y, vec3(-in0.z, -in0.x, -in0.y));
+ test c = test(in0.x, vec3(-in0.y, in0.z, -in0.x));
+
+ test[] x = test[3] (a, b, c);
+ test[] y = test[] (c, a, b, b, a);
+ test[13] z;
+
+ out0 = ivec3(x.length(), y.length(), z.length());
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # length
--- /dev/null
+group if "If Statements"
+
+ case single_statement
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 ];
+ output float out0 = [ 0.0 | 1.0 | 1.0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 0.0;
+ if (in0 >= 1.0)
+ out0 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case compound_statement
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 ];
+ output float out0 = [ 0.0 | 1.0 | 1.0 ];
+ output float out1 = [ 1.0 | 0.0 | 0.0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 0.0;
+ out1 = 1.0;
+ if (in0 >= 1.0)
+ {
+ out0 = 1.0;
+ out1 = 0.0;
+ }
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case sequence_statements
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 ];
+ output float out0 = [ 0.0 | 1.0 | 1.0 ];
+ output float out1 = [ 1.0 | 0.0 | 0.0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 0.0;
+ out1 = 1.0;
+ if (in0 >= 1.0)
+ out0 = 1.0, out1 = 0.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case sequence_condition
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 ];
+ output float out0 = [ 0.0 | 1.0 | 1.0 ];
+ output float out1 = [ 1.0 | 0.0 | 0.0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 0.0;
+ out1 = 1.0;
+ if (false, in0 >= 1.0)
+ out0 = 1.0, out1 = 0.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case complex_condition
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 ];
+ output float out0 = [ 0.0 | 1.0 | 1.0 ];
+ output float out1 = [ 1.0 | 0.0 | 0.0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 0.0;
+ out1 = 1.0;
+ if (false || (in0 >= 1.0) && (in0 - 2.0*in0 < 0.0))
+ out0 = 1.0, out1 = 0.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case if_else
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 ];
+ output float out0 = [ 0.0 | 1.0 | 1.0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ if (in0 >= 1.0)
+ out0 = 1.0;
+ else
+ out0 = 0.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case if_elseif
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 ];
+ output float out0 = [ 0.0 | 1.0 | 2.0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 0.0;
+ if (in0 >= 2.0)
+ out0 = 2.0;
+ else if (in0 >= 1.0)
+ out0 = 1.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case if_elseif_else
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 ];
+ output float out0 = [ 0.0 | 1.0 | 2.0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ if (in0 >= 2.0)
+ out0 = 2.0;
+ else if (in0 >= 1.0)
+ out0 = 1.0;
+ else
+ out0 = 0.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mixed_if_elseif_else
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 ];
+ output float out0 = [ 0.0 | 1.0 | 2.0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ if (in0 >= 2.0)
+ {
+ out0 = 2.0;
+ }
+ else if (in0 >= 1.0)
+ out0 = 2.0, out0 = 1.0;
+ else
+ out0 = 0.0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # if
--- /dev/null
+group trivial "Trivial expressions"
+
+ case float
+ version 310 es
+ values { output float out0 = 5.0; }
+ both ""
+ #version 310 es
+ precision highp float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const float a = 5.0;
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int
+ version 310 es
+ values { output int out0 = 5; }
+ both ""
+ #version 310 es
+ precision highp float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const int a = 5;
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool
+ version 310 es
+ values { output bool out0 = true; }
+ both ""
+ #version 310 es
+ precision highp float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const bool a = true;
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case cast
+ version 310 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 310 es
+ precision highp float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const float a = float(int(bool(true)));
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # trivial
+
+group operators "Operators"
+
+ case math_float
+ version 310 es
+ values { output float out0 = 2.19; }
+ both ""
+ #version 310 es
+ precision highp float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const float a = 6.0/3.5 + 1.8*2.6 - 4.2;
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case math_vec
+ version 310 es
+ values { output float out0 = 15.0; }
+ both ""
+ #version 310 es
+ precision highp float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const vec3 a = (vec4(1.0, 2.0, 3.0, 4.0).zyx * vec3(1.0, 1.5, 3.0).xyz).xzy + (vec2(5.0)/vec2(2.5)).xxy;
+ out0 = a.x + a.y + a.z;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case math_int
+ version 310 es
+ values { output int out0 = 7; }
+ both ""
+ #version 310 es
+ precision highp int;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const int a = 25%7 + 2*3 - 9/3;
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case math_ivec
+ version 310 es
+ values { output int out0 = 21; }
+ both ""
+ #version 310 es
+ precision highp int;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const ivec3 a = ivec2(25%7, 4).xxy + ivec4(1*3, 9/3, 1+2, 8/4).xyz;
+ out0 = a.x + a.y + a.z;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case math_mat
+ version 310 es
+ values { output float out0 = 8.0; }
+ both ""
+ #version 310 es
+ precision highp float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const mat3 a = mat3(3.0) * mat3(4.0);
+ const mat4 b = mat4(a[1][1])*2.0;
+ const mat2 c = mat2(b[0][0]) / 3.0;
+ out0 = c[0][0]+c[1][0];
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bitwise
+ version 310 es
+ values { output int out0 = 678332; }
+ both ""
+ #version 310 es
+ precision highp int;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const int a = (((0xABBA<<4) ^ 0xCAFE) | (0xDCBA & (0xABCD>>2))) ^ (~0xDEAD & 0xBEEF);
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case logical
+ version 310 es
+ values { output bool out0 = true; }
+ both ""
+ #version 310 es
+ precision highp int;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const bool a = (!false || false) && (true ^^ false);
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case compare
+ version 310 es
+ values { output bool out0 = true; }
+ both ""
+ #version 310 es
+ precision highp int;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const bool a = (false == false) && (true != false) && (1 < 2) && (3 <= 3) && ((1 > 1) != (1 >= 1));
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case selection
+ version 310 es
+ values { output float out0 = 5.3; }
+ both ""
+ #version 310 es
+ precision highp float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const float a = false ? 0.0 : (true ? 5.3 : 1.0);
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # operators
+
+group complex_types "Arrays & Structs"
+
+ case struct
+ version 310 es
+ values { output float out0 = 260.922; }
+ both ""
+ #version 310 es
+ precision highp float;
+ ${DECLARATIONS}
+
+ struct S
+ {
+ vec4 a;
+ int b;
+ };
+
+ void main()
+ {
+ const S s = S(vec4(1.5), 123);
+ out0 = length(s.a.xy)*float(s.b);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case nested_struct
+ version 310 es
+ values { output float out0 = 965.9; }
+ both ""
+ #version 310 es
+ precision highp float;
+ ${DECLARATIONS}
+
+ struct S
+ {
+ vec4 v;
+ int i;
+ };
+
+ struct T
+ {
+ S s;
+ bool b;
+ int i;
+ };
+
+ struct U
+ {
+ S s;
+ T t;
+ };
+
+ void main()
+ {
+ const S s = S(vec4(1.5), 123);
+ const T t = T(s, false, 3);
+ const U u = U(s, t);
+ const U v = U(S(vec4(1.3), 4), T(S(vec4(2.0), 5), true, 6));
+ out0 = float(u.s.i*v.t.i + v.t.s.i)*v.s.v.x; // float(123*6 + 5)*1.3
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case array_size
+ version 310 es
+ values { output int out0 = 1; }
+ both ""
+ #version 310 es
+ precision highp float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const int a[max(-1, 1)] = int[1](1);
+ out0 = a[0];
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case array_length
+ version 310 es
+ values { output int out0 = 2; }
+ both ""
+ #version 310 es
+ precision highp float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const int a[1] = int[1](1);
+ out0 = a.length() + a[0];
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case array
+ version 310 es
+ values { output float out0 = 4.0; }
+ both ""
+ #version 310 es
+ precision highp float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const float a[1+2+5] = float[8](0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0);
+ const float f = a[1+2+4];
+ out0 = f + float(a.length()-8);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # complex_types
+
+group other "Other operations"
+
+ case switch_case
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.0 | 4.0 | 5.0 ];
+ output int out0 = [ 0 | 1 | 2 | 3 | 4 | 10];
+ }
+
+ both ""
+ #version 310 es
+ precision highp float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const int _0 = 0;
+ const int _1 = 1;
+ const int _2 = 2;
+ const int _3 = 3;
+ const int _4 = 4;
+
+ switch(int(in0))
+ {
+ case _0:
+ out0 = 0;
+ break;
+ case _1:
+ out0 = 1;
+ break;
+ case _2:
+ out0 = 2;
+ break;
+ case _3:
+ out0 = 3;
+ break;
+ case _4:
+ out0 = 4;
+ break;
+ case 5:
+ out0 = 10;
+ break;
+ default:
+ out0 = 100;
+
+ }
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case nested_builtin_funcs
+ version 310 es
+ values { output float out0 = 3.05; }
+ both ""
+ #version 310 es
+ precision highp float;
+ ${DECLARATIONS}
+
+ void main()
+ {
+ const float a = sqrt( atan(sin(1.5)/cos(1.5)) /*1.5*/ * log2(exp2(log(exp(6.2) + 0.1)) + 0.1) /*~6.2*/);
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case complex
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.0 | 4.0 | 5.0 ];
+ output int out0 = [ 0 | 1 | 2 | 3 | 4 | 10];
+ }
+
+ both ""
+ #version 310 es
+ precision highp float;
+ ${DECLARATIONS}
+
+ struct T
+ {
+ vec4 v;
+ };
+
+ struct S
+ {
+ T t;
+ int i;
+ bool b;
+ };
+
+ void main()
+ {
+ const T t = T(vec4(1.0));
+ const S s = S(t, 42, true);
+ const int _0 = int(sin(0.0));
+ const int _1 = int(1.0);
+ const int _2 = 2 + int(float(_0>_1));
+ const int _3 = min(gl_MaxVertexAttribs, 16)/4 - 1;
+ const int _4 = min(gl_MaxDrawBuffers, 4);
+ const ivec4 nums = ivec4(0, 1, 2, 3);
+
+ switch(int(in0))
+ {
+ case int(float(_0)):
+ out0 = ((true!=false) && (!false)) ? 0 : 25;
+ break;
+ case ivec3(_1).x:
+ out0 = 3*18/9-5;
+ break;
+ case nums[_2]:
+ out0 = int(length(vec4(1.0))+0.001);
+ break;
+ case _3:
+ out0 = 3;
+ break;
+ case clamp(_4, 1, 6):
+ out0 = (s.i-2)/10;
+ break;
+ case max(3, 5):
+ out0 = 10;
+ break;
+ default:
+ out0 = 100;
+
+ }
+ ${OUTPUT}
+ }
+ ""
+ end
+end
--- /dev/null
+case float_input
+ version 310 es
+ values
+ {
+ input float in0 = [ 1.123 | 0.75 | -512.0 | -72.13 | 199.91 | -1.123 | -0.75 | 512.0 | -72.13 | -199.91 ];
+ output float out0 = [ 1.123 | 0.75 | -512.0 | -72.13 | 199.91 | -1.123 | -0.75 | 512.0 | -72.13 | -199.91 ];
+ }
+
+ both ""
+ #version 310 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = in0;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case float_uniform
+ version 310 es
+ values
+ {
+ uniform float uni0 = [ 1.123 | 0.75 | -512.0 | -72.13 | 199.91 ];
+ output float out0 = [ 1.123 | 0.75 | -512.0 | -72.13 | 199.91 ];
+ }
+
+ both ""
+ #version 310 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = uni0;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case float_0
+ version 310 es
+ values { output float out0 = 1.123; }
+ both ""
+ #version 310 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = +1.123;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case float_1
+ version 310 es
+ values { output float out0 = -1.123; }
+ both ""
+ #version 310 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = -1.123;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case float_2
+ version 310 es
+ values { output float out0 = 123.0; }
+ both ""
+ #version 310 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 123.;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case float_3
+ version 310 es
+ values { output float out0 = 0.123; }
+ both ""
+ #version 310 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = .123;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case float_4
+ version 310 es
+ values { output float out0 = 123.0; }
+ both ""
+ #version 310 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 1.23e+2;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case float_5
+ version 310 es
+ values { output float out0 = -123.0; }
+ both ""
+ #version 310 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = -1.23E+2;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case float_6
+ version 310 es
+ values { output float out0 = -123.0; }
+ both ""
+ #version 310 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = -1.23e2;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case float_7
+ version 310 es
+ values { output float out0 = 0.123; }
+ both ""
+ #version 310 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 1.23e-1;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case float_8
+ version 310 es
+ values { output float out0 = 1000.0; }
+ both ""
+ #version 310 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 1e3;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case float_f_suffix_0
+ version 310 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main ()
+ {
+ ${SETUP}
+ float value = 1.0f;
+ out0 = value;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case float_f_suffix_1
+ version 310 es
+ values { output float out0 = 1.0; }
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main ()
+ {
+ ${SETUP}
+ float value = 1.0F;
+ out0 = value;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case int_0
+ version 310 es
+ values { output int out0 = 123; }
+ both ""
+ #version 310 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 123;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case int_1
+ version 310 es
+ values { output int out0 = -321; }
+ both ""
+ #version 310 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = -321;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case int_2
+ version 310 es
+ values { output int out0 = 123; }
+ both ""
+ #version 310 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 0x7B;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case int_3
+ version 310 es
+ values { output int out0 = 123; }
+ both ""
+ #version 310 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 0X7b;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case int_4
+ version 310 es
+ values { output int out0 = 123; }
+ both ""
+ #version 310 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = 0173;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case bool_0
+ version 310 es
+ values { output bool out0 = true; }
+ both ""
+ #version 310 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = true;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case bool_1
+ version 310 es
+ values { output bool out0 = false; }
+ both ""
+ #version 310 es
+ precision highp float;
+ ${DECLARATIONS}
+ void main()
+ {
+ out0 = false;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_global
+ version 310 es
+ values { output float out0 = 1000.0; }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+ const float theConstant = 1000.0;
+ void main()
+ {
+ out0 = theConstant;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_main
+ version 310 es
+ values { output float out0 = -1000.0; }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ const float theConstant = -1000.0;
+ out0 = theConstant;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_function
+ version 310 es
+ values { output float out0 = -0.012; }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+ float func()
+ {
+ const float theConstant = -0.012;
+ return theConstant;
+ }
+ void main()
+ {
+ out0 = func();
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_scope
+ version 310 es
+ values { output float out0 = 1.0; }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ {
+ const float theConstant = 1.0;
+ out0 = theConstant;
+ }
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_scope_shawdowing_1
+ version 310 es
+ values { output float out0 = 1.0; }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ const float theConstant = 100.0;
+ {
+ const float theConstant = 1.0;
+ out0 = theConstant;
+ }
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_scope_shawdowing_2
+ version 310 es
+ values { output float out0 = 1.0; }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+ const float theConstant = 100.0;
+ void main()
+ {
+ {
+ const float theConstant = 1.0;
+ out0 = theConstant;
+ }
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_scope_shawdowing_3
+ version 310 es
+ values { output float out0 = 1.0; }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+ const float theConstant = 100.0;
+ void main()
+ {
+ const float theConstant = -100.0;
+ {
+ const float theConstant = 1.0;
+ out0 = theConstant;
+ }
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_scope_shawdowing_4
+ version 310 es
+ values { output float out0 = 2.0; }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+ const float theConstant = 100.0;
+ float func()
+ {
+ const float theConstant = 2.0;
+ return theConstant;
+ }
+ void main()
+ {
+ const float theConstant = -100.0;
+ {
+ const float theConstant = 1.0;
+ out0 = func();
+ }
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_operations_with_const
+ version 310 es
+ values { output float out0 = 21.0; }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+ const float theGlobalConstant = 10.0;
+ float func()
+ {
+ const float theConstant = 2.0;
+ return theConstant;
+ }
+ void main()
+ {
+ const float theConstant = -100.0;
+ {
+ const float theConstant = 1.0;
+ out0 = func() * theGlobalConstant + theConstant;
+ }
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_assignment_1
+ version 310 es
+ values { output float out0 = 10.0; }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ const float theConstant1 = 10.0;
+ const float theConstant2 = theConstant1;
+ out0 = theConstant2;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_assignment_2
+ version 310 es
+ values { output float out0 = 10.0; }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ const float theConstant1 = 10.0;
+ {
+ const float theConstant2 = theConstant1;
+ out0 = theConstant2;
+ }
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_assignment_3
+ version 310 es
+ values { output float out0 = 10.0; }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+ const float theConstant1 = 10.0;
+ void main()
+ {
+ const float theConstant2 = theConstant1;
+ out0 = theConstant2;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_assignment_4
+ version 310 es
+ values { output float out0 = 10.0; }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+ const float theConstant1 = 10.0;
+ float func()
+ {
+ const float theConstant2 = theConstant1;
+ return theConstant2;
+ }
+ void main()
+ {
+ out0 = func();
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_from_int
+ version 310 es
+ values { output float out0 = 10.0; }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+ const float theConstant = float(10);
+ void main()
+ {
+ out0 = theConstant;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_from_vec2
+ version 310 es
+ values { output float out0 = 10.0; }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+ const float theConstant = vec2(1.0, 10.0).y;
+ void main()
+ {
+ out0 = theConstant;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_from_vec3
+ version 310 es
+ values { output float out0 = 10.0; }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+ const float theConstant = vec3(1.0, 10.0, 20.0).y;
+ void main()
+ {
+ out0 = theConstant;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case const_float_from_vec4
+ version 310 es
+ values { output float out0 = 10.0; }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+ const float theConstant = vec4(1.0, 10.0, 20.0, -10.0).y;
+ void main()
+ {
+ out0 = theConstant;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case int_decimal
+ version 310 es
+ values { output int out0 = 7; }
+ both ""
+ #version 310 es
+ ${DECLARATIONS}
+ void main ()
+ {
+ ${SETUP}
+ int value = 7;
+ out0 = value;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case int_octal
+ version 310 es
+ values { output int out0 = 15; }
+ both ""
+ #version 310 es
+ ${DECLARATIONS}
+ void main ()
+ {
+ ${SETUP}
+ int value = 017;
+ out0 = value;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case int_hexadecimal_0
+ version 310 es
+ values { output int out0 = 47; }
+ both ""
+ #version 310 es
+ ${DECLARATIONS}
+ void main ()
+ {
+ ${SETUP}
+ int value = 0x2f;
+ out0 = value;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case int_hexadecimal_1
+ version 310 es
+ values { output int out0 = 47; }
+ both ""
+ #version 310 es
+ ${DECLARATIONS}
+ void main ()
+ {
+ ${SETUP}
+ int value = 0X2f;
+ out0 = value;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case uint_decimal_0
+ version 310 es
+ values { output uint out0 = 7; }
+ both ""
+ #version 310 es
+ ${DECLARATIONS}
+ void main ()
+ {
+ ${SETUP}
+ uint value = 7u;
+ out0 = value;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case uint_decimal_1
+ version 310 es
+ values { output uint out0 = 7; }
+ both ""
+ #version 310 es
+ ${DECLARATIONS}
+ void main ()
+ {
+ ${SETUP}
+ uint value = 7U;
+ out0 = value;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case uint_decimal_2
+ version 310 es
+ values { output uint out0 = 0; }
+ both ""
+ #version 310 es
+ ${DECLARATIONS}
+ void main ()
+ {
+ ${SETUP}
+ uint value = 0u;
+ out0 = value;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case uint_decimal_3
+ version 310 es
+ values { output uint out0 = 0; }
+ both ""
+ #version 310 es
+ ${DECLARATIONS}
+ void main ()
+ {
+ ${SETUP}
+ uint value = 0U;
+ out0 = value;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case uint_octal_0
+ version 310 es
+ values { output uint out0 = 15; }
+ both ""
+ #version 310 es
+ ${DECLARATIONS}
+ void main ()
+ {
+ ${SETUP}
+ uint value = 017u;
+ out0 = value;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case uint_octal_1
+ version 310 es
+ values { output uint out0 = 15; }
+ both ""
+ #version 310 es
+ ${DECLARATIONS}
+ void main ()
+ {
+ ${SETUP}
+ uint value = 017U;
+ out0 = value;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case uint_hexadecimal_0
+ version 310 es
+ values { output uint out0 = 47; }
+ both ""
+ #version 310 es
+ ${DECLARATIONS}
+ void main ()
+ {
+ ${SETUP}
+ uint value = 0x2fU;
+ out0 = value;
+ ${OUTPUT}
+ }
+ ""
+end
+
+case uint_hexadecimal_1
+ version 310 es
+ values { output uint out0 = 47; }
+ both ""
+ #version 310 es
+ ${DECLARATIONS}
+ void main ()
+ {
+ ${SETUP}
+ uint value = 0X2fu;
+ out0 = value;
+ ${OUTPUT}
+ }
+ ""
+end
--- /dev/null
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+
+group scalar_to_scalar "Scalar to Scalar Conversions"
+
+ case float_to_float
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output float out0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_int
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output int out0 = [ 0 | 1 | 2 | 3 | 0 | -8 | -20 | 36 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_bool
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output bool out0 = [ false | true | true | true | true | true | true | true ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_float
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output float out0 = [ 0.0 | 1.0 | 2.0 | 5.0 | 8.0 | 11.0 | -12.0 | -66.0 | -192.0 | 255.0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_int
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output int out0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_bool
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output bool out0 = [ false | true | true | true | true | true | true | true | true | true ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_float
+ version 310 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output float out0 = [ 0.0 | 2.0 | 3.0 | 8.0 | 9.0 | 12.0 | 10.0 | 45.0 | 193.0 | 255.0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_int
+ version 310 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output int out0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_bool
+ version 310 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output bool out0 = [ false | true | true | true | true | true | true | true | true | true ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_float
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output float out0 = [ 1.0 | 0.0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_int
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output int out0 = [ 1 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_bool
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output bool out0 = [ true | false ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_uint
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | 0.5 | 8.25 | 20.125 | 36.8125 ];
+ output uint out0 = [ 0 | 1 | 2 | 3 | 0 | 8 | 20 | 36 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_uint
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | 12 | 66 | 192 | 255 ];
+ output uint out0 = [ 0 | 1 | 2 | 5 | 8 | 11 | 12 | 66 | 192 | 255 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_uint
+ version 310 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output uint out0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_uint
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output uint out0 = [ 1 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # scalar_to_scalar
+group scalar_to_vector "Scalar to Vector Conversions"
+
+ case float_to_vec2
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(2.0, 2.0) | vec2(3.5, 3.5) | vec2(-0.5, -0.5) | vec2(-8.25, -8.25) | vec2(-20.125, -20.125) | vec2(36.8125, 36.8125) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_vec3
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(2.0, 2.0, 2.0) | vec3(3.5, 3.5, 3.5) | vec3(-0.5, -0.5, -0.5) | vec3(-8.25, -8.25, -8.25) | vec3(-20.125, -20.125, -20.125) | vec3(36.8125, 36.8125, 36.8125) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_vec4
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 0.0, 0.0) | vec4(1.0, 1.0, 1.0, 1.0) | vec4(2.0, 2.0, 2.0, 2.0) | vec4(3.5, 3.5, 3.5, 3.5) | vec4(-0.5, -0.5, -0.5, -0.5) | vec4(-8.25, -8.25, -8.25, -8.25) | vec4(-20.125, -20.125, -20.125, -20.125) | vec4(36.8125, 36.8125, 36.8125, 36.8125) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_ivec2
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(2, 2) | ivec2(3, 3) | ivec2(0, 0) | ivec2(-8, -8) | ivec2(-20, -20) | ivec2(36, 36) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_ivec3
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(2, 2, 2) | ivec3(3, 3, 3) | ivec3(0, 0, 0) | ivec3(-8, -8, -8) | ivec3(-20, -20, -20) | ivec3(36, 36, 36) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_ivec4
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(2, 2, 2, 2) | ivec4(3, 3, 3, 3) | ivec4(0, 0, 0, 0) | ivec4(-8, -8, -8, -8) | ivec4(-20, -20, -20, -20) | ivec4(36, 36, 36, 36) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_bvec2
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_bvec3
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_bvec4
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_vec2
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(2.0, 2.0) | vec2(5.0, 5.0) | vec2(8.0, 8.0) | vec2(11.0, 11.0) | vec2(-12.0, -12.0) | vec2(-66.0, -66.0) | vec2(-192.0, -192.0) | vec2(255.0, 255.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_vec3
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(2.0, 2.0, 2.0) | vec3(5.0, 5.0, 5.0) | vec3(8.0, 8.0, 8.0) | vec3(11.0, 11.0, 11.0) | vec3(-12.0, -12.0, -12.0) | vec3(-66.0, -66.0, -66.0) | vec3(-192.0, -192.0, -192.0) | vec3(255.0, 255.0, 255.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_vec4
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 0.0, 0.0) | vec4(1.0, 1.0, 1.0, 1.0) | vec4(2.0, 2.0, 2.0, 2.0) | vec4(5.0, 5.0, 5.0, 5.0) | vec4(8.0, 8.0, 8.0, 8.0) | vec4(11.0, 11.0, 11.0, 11.0) | vec4(-12.0, -12.0, -12.0, -12.0) | vec4(-66.0, -66.0, -66.0, -66.0) | vec4(-192.0, -192.0, -192.0, -192.0) | vec4(255.0, 255.0, 255.0, 255.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_ivec2
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(2, 2) | ivec2(5, 5) | ivec2(8, 8) | ivec2(11, 11) | ivec2(-12, -12) | ivec2(-66, -66) | ivec2(-192, -192) | ivec2(255, 255) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_ivec3
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(2, 2, 2) | ivec3(5, 5, 5) | ivec3(8, 8, 8) | ivec3(11, 11, 11) | ivec3(-12, -12, -12) | ivec3(-66, -66, -66) | ivec3(-192, -192, -192) | ivec3(255, 255, 255) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_ivec4
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(2, 2, 2, 2) | ivec4(5, 5, 5, 5) | ivec4(8, 8, 8, 8) | ivec4(11, 11, 11, 11) | ivec4(-12, -12, -12, -12) | ivec4(-66, -66, -66, -66) | ivec4(-192, -192, -192, -192) | ivec4(255, 255, 255, 255) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_bvec2
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_bvec3
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_bvec4
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_vec2
+ version 310 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(2.0, 2.0) | vec2(3.0, 3.0) | vec2(8.0, 8.0) | vec2(9.0, 9.0) | vec2(12.0, 12.0) | vec2(10.0, 10.0) | vec2(45.0, 45.0) | vec2(193.0, 193.0) | vec2(255.0, 255.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_vec3
+ version 310 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(2.0, 2.0, 2.0) | vec3(3.0, 3.0, 3.0) | vec3(8.0, 8.0, 8.0) | vec3(9.0, 9.0, 9.0) | vec3(12.0, 12.0, 12.0) | vec3(10.0, 10.0, 10.0) | vec3(45.0, 45.0, 45.0) | vec3(193.0, 193.0, 193.0) | vec3(255.0, 255.0, 255.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_vec4
+ version 310 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 0.0, 0.0) | vec4(2.0, 2.0, 2.0, 2.0) | vec4(3.0, 3.0, 3.0, 3.0) | vec4(8.0, 8.0, 8.0, 8.0) | vec4(9.0, 9.0, 9.0, 9.0) | vec4(12.0, 12.0, 12.0, 12.0) | vec4(10.0, 10.0, 10.0, 10.0) | vec4(45.0, 45.0, 45.0, 45.0) | vec4(193.0, 193.0, 193.0, 193.0) | vec4(255.0, 255.0, 255.0, 255.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_ivec2
+ version 310 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(2, 2) | ivec2(3, 3) | ivec2(8, 8) | ivec2(9, 9) | ivec2(12, 12) | ivec2(10, 10) | ivec2(45, 45) | ivec2(193, 193) | ivec2(255, 255) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_ivec3
+ version 310 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(2, 2, 2) | ivec3(3, 3, 3) | ivec3(8, 8, 8) | ivec3(9, 9, 9) | ivec3(12, 12, 12) | ivec3(10, 10, 10) | ivec3(45, 45, 45) | ivec3(193, 193, 193) | ivec3(255, 255, 255) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_ivec4
+ version 310 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(2, 2, 2, 2) | ivec4(3, 3, 3, 3) | ivec4(8, 8, 8, 8) | ivec4(9, 9, 9, 9) | ivec4(12, 12, 12, 12) | ivec4(10, 10, 10, 10) | ivec4(45, 45, 45, 45) | ivec4(193, 193, 193, 193) | ivec4(255, 255, 255, 255) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_bvec2
+ version 310 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_bvec3
+ version 310 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_bvec4
+ version 310 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_vec2
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output vec2 out0 = [ vec2(1.0, 1.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_vec3
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output vec3 out0 = [ vec3(1.0, 1.0, 1.0) | vec3(0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_vec4
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output vec4 out0 = [ vec4(1.0, 1.0, 1.0, 1.0) | vec4(0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_ivec2
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output ivec2 out0 = [ ivec2(1, 1) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_ivec3
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output ivec3 out0 = [ ivec3(1, 1, 1) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_ivec4
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output ivec4 out0 = [ ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_bvec2
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_bvec3
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_bvec4
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_uvec2
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | 0.5 | 8.25 | 20.125 | 36.8125 ];
+ output uvec2 out0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(2, 2) | uvec2(3, 3) | uvec2(0, 0) | uvec2(8, 8) | uvec2(20, 20) | uvec2(36, 36) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_uvec3
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | 0.5 | 8.25 | 20.125 | 36.8125 ];
+ output uvec3 out0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(2, 2, 2) | uvec3(3, 3, 3) | uvec3(0, 0, 0) | uvec3(8, 8, 8) | uvec3(20, 20, 20) | uvec3(36, 36, 36) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_uvec4
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | 0.5 | 8.25 | 20.125 | 36.8125 ];
+ output uvec4 out0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(2, 2, 2, 2) | uvec4(3, 3, 3, 3) | uvec4(0, 0, 0, 0) | uvec4(8, 8, 8, 8) | uvec4(20, 20, 20, 20) | uvec4(36, 36, 36, 36) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_uvec2
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | 12 | 66 | 192 | 255 ];
+ output uvec2 out0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(2, 2) | uvec2(5, 5) | uvec2(8, 8) | uvec2(11, 11) | uvec2(12, 12) | uvec2(66, 66) | uvec2(192, 192) | uvec2(255, 255) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_uvec3
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | 12 | 66 | 192 | 255 ];
+ output uvec3 out0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(2, 2, 2) | uvec3(5, 5, 5) | uvec3(8, 8, 8) | uvec3(11, 11, 11) | uvec3(12, 12, 12) | uvec3(66, 66, 66) | uvec3(192, 192, 192) | uvec3(255, 255, 255) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_uvec4
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | 12 | 66 | 192 | 255 ];
+ output uvec4 out0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(2, 2, 2, 2) | uvec4(5, 5, 5, 5) | uvec4(8, 8, 8, 8) | uvec4(11, 11, 11, 11) | uvec4(12, 12, 12, 12) | uvec4(66, 66, 66, 66) | uvec4(192, 192, 192, 192) | uvec4(255, 255, 255, 255) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_uvec2
+ version 310 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output uvec2 out0 = [ uvec2(0, 0) | uvec2(2, 2) | uvec2(3, 3) | uvec2(8, 8) | uvec2(9, 9) | uvec2(12, 12) | uvec2(10, 10) | uvec2(45, 45) | uvec2(193, 193) | uvec2(255, 255) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_uvec3
+ version 310 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output uvec3 out0 = [ uvec3(0, 0, 0) | uvec3(2, 2, 2) | uvec3(3, 3, 3) | uvec3(8, 8, 8) | uvec3(9, 9, 9) | uvec3(12, 12, 12) | uvec3(10, 10, 10) | uvec3(45, 45, 45) | uvec3(193, 193, 193) | uvec3(255, 255, 255) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_uvec4
+ version 310 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output uvec4 out0 = [ uvec4(0, 0, 0, 0) | uvec4(2, 2, 2, 2) | uvec4(3, 3, 3, 3) | uvec4(8, 8, 8, 8) | uvec4(9, 9, 9, 9) | uvec4(12, 12, 12, 12) | uvec4(10, 10, 10, 10) | uvec4(45, 45, 45, 45) | uvec4(193, 193, 193, 193) | uvec4(255, 255, 255, 255) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_uvec2
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output uvec2 out0 = [ uvec2(1, 1) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_uvec3
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output uvec3 out0 = [ uvec3(1, 1, 1) | uvec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_uvec4
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output uvec4 out0 = [ uvec4(1, 1, 1, 1) | uvec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # scalar_to_vector
+group vector_to_scalar "Vector to Scalar Conversions"
+
+ case vec2_to_float
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_int
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_bool
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output bool out0 = [ false | true | true | true | true ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_float
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_int
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_bool
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output bool out0 = [ false | true | true | true | true ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_float
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_int
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_bool
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output bool out0 = [ false | true | true | true | true ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_float
+ version 310 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output float out0 = [ 0.0 | 1.0 | 0.0 | -32.0 | 0.0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_int
+ version 310 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_bool
+ version 310 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output bool out0 = [ false | true | false | true | false ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_float
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output float out0 = [ 0.0 | 1.0 | 0.0 | -32.0 | 0.0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_int
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_bool
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output bool out0 = [ false | true | false | true | false ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_float
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output float out0 = [ 0.0 | 1.0 | 0.0 | -32.0 | 0.0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_int
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_bool
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output bool out0 = [ false | true | false | true | false ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_float
+ version 310 es
+ values
+ {
+ input uvec2 in0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ output float out0 = [ 0.0 | 1.0 | 0.0 | 32.0 | 0.0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_int
+ version 310 es
+ values
+ {
+ input uvec2 in0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | 32 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_bool
+ version 310 es
+ values
+ {
+ input uvec2 in0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ output bool out0 = [ false | true | false | true | false ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_float
+ version 310 es
+ values
+ {
+ input uvec3 in0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ output float out0 = [ 0.0 | 1.0 | 0.0 | 32.0 | 0.0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_int
+ version 310 es
+ values
+ {
+ input uvec3 in0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | 32 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_bool
+ version 310 es
+ values
+ {
+ input uvec3 in0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ output bool out0 = [ false | true | false | true | false ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_float
+ version 310 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output float out0 = [ 0.0 | 1.0 | 0.0 | 32.0 | 0.0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_int
+ version 310 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | 32 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_bool
+ version 310 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output bool out0 = [ false | true | false | true | false ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_float
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output float out0 = [ 1.0 | 0.0 | 0.0 | 1.0 | 0.0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_int
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output int out0 = [ 1 | 0 | 0 | 1 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_bool
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_float
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output float out0 = [ 1.0 | 0.0 | 0.0 | 1.0 | 0.0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_int
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output int out0 = [ 1 | 0 | 0 | 1 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_bool
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_float
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output float out0 = [ 1.0 | 0.0 | 0.0 | 1.0 | 0.0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = float(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_int
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output int out0 = [ 1 | 0 | 0 | 1 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = int(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_bool
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bool(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_uint
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(0.5, 2.25) | vec2(32.0, 64.0) | vec2(0.75, 0.0322580645161) ];
+ output uint out0 = [ 0 | 1 | 0 | 32 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_uint
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(0.5, 2.25, 4.875) | vec3(32.0, 64.0, 51.0) | vec3(0.75, 0.0322580645161, 0.0526315789474) ];
+ output uint out0 = [ 0 | 1 | 0 | 32 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_uint
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.5, 2.25, 4.875, 9.0) | vec4(32.0, 64.0, 51.0, 24.0) | vec4(0.75, 0.0322580645161, 0.0526315789474, 0.25) ];
+ output uint out0 = [ 0 | 1 | 0 | 32 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_uint
+ version 310 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, 2) | ivec2(32, 64) | ivec2(0, 0) ];
+ output uint out0 = [ 0 | 1 | 0 | 32 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_uint
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, 2, 4) | ivec3(32, 64, 51) | ivec3(0, 0, 0) ];
+ output uint out0 = [ 0 | 1 | 0 | 32 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_uint
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 2, 4, 9) | ivec4(32, 64, 51, 24) | ivec4(0, 0, 0, 0) ];
+ output uint out0 = [ 0 | 1 | 0 | 32 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_uint
+ version 310 es
+ values
+ {
+ input uvec2 in0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ output uint out0 = [ 0 | 1 | 0 | 32 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_uint
+ version 310 es
+ values
+ {
+ input uvec3 in0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ output uint out0 = [ 0 | 1 | 0 | 32 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_uint
+ version 310 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output uint out0 = [ 0 | 1 | 0 | 32 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_uint
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output uint out0 = [ 1 | 0 | 0 | 1 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_uint
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output uint out0 = [ 1 | 0 | 0 | 1 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_uint
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output uint out0 = [ 1 | 0 | 0 | 1 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uint(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # vector_to_scalar
+
+group vector_to_vector "Vector to Vector Conversions"
+
+ case vec4_to_vec4
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_vec3
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_vec2
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec2 out0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_ivec4
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_ivec3
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_ivec2
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_bvec4
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output bvec4 out0 = [ bvec4(false, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_bvec3
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output bvec3 out0 = [ bvec3(false, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_bvec2
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output bvec2 out0 = [ bvec2(false, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_vec4
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 0.0, 0.0) | vec4(1.0, 1.0, 1.0, 1.0) | vec4(0.0, -2.0, -4.0, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_vec3
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(0.0, -2.0, -4.0) | vec3(-32.0, 64.0, -51.0) | vec3(0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_vec2
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(0.0, -2.0) | vec2(-32.0, 64.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_ivec4
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_ivec3
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_ivec2
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_bvec4
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_bvec3
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, true, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_bvec2
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_vec4
+ version 310 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 0.0, 0.0) | vec4(1.0, 1.0, 1.0, 1.0) | vec4(0.0, 2.0, 4.0, 9.0) | vec4(32.0, 64.0, 51.0, 24.0) | vec4(0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_vec3
+ version 310 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(0.0, 2.0, 4.0) | vec3(32.0, 64.0, 51.0) | vec3(0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_vec2
+ version 310 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(0.0, 2.0) | vec2(32.0, 64.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_ivec4
+ version 310 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 2, 4, 9) | ivec4(32, 64, 51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_ivec3
+ version 310 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, 2, 4) | ivec3(32, 64, 51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_ivec2
+ version 310 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, 2) | ivec2(32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_bvec4
+ version 310 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_bvec3
+ version 310 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, true, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_bvec2
+ version 310 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_vec4
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output vec4 out0 = [ vec4(1.0, 0.0, 0.0, 1.0) | vec4(0.0, 0.0, 0.0, 1.0) | vec4(0.0, 1.0, 0.0, 0.0) | vec4(1.0, 1.0, 1.0, 1.0) | vec4(0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_vec3
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output vec3 out0 = [ vec3(1.0, 0.0, 0.0) | vec3(0.0, 0.0, 0.0) | vec3(0.0, 1.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_vec2
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output vec2 out0 = [ vec2(1.0, 0.0) | vec2(0.0, 0.0) | vec2(0.0, 1.0) | vec2(1.0, 1.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_ivec4
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output ivec4 out0 = [ ivec4(1, 0, 0, 1) | ivec4(0, 0, 0, 1) | ivec4(0, 1, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_ivec3
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output ivec3 out0 = [ ivec3(1, 0, 0) | ivec3(0, 0, 0) | ivec3(0, 1, 0) | ivec3(1, 1, 1) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_ivec2
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output ivec2 out0 = [ ivec2(1, 0) | ivec2(0, 0) | ivec2(0, 1) | ivec2(1, 1) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_bvec4
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_bvec3
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_bvec2
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_uvec4
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.5, 2.25, 4.875, 9.0) | vec4(32.0, 64.0, 51.0, 24.0) | vec4(0.75, 0.0322580645161, 0.0526315789474, 0.25) ];
+ output uvec4 out0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_uvec3
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.5, 2.25, 4.875, 9.0) | vec4(32.0, 64.0, 51.0, 24.0) | vec4(0.75, 0.0322580645161, 0.0526315789474, 0.25) ];
+ output uvec3 out0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_to_uvec2
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.5, 2.25, 4.875, 9.0) | vec4(32.0, 64.0, 51.0, 24.0) | vec4(0.75, 0.0322580645161, 0.0526315789474, 0.25) ];
+ output uvec2 out0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_uvec4
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 2, 4, 9) | ivec4(32, 64, 51, 24) | ivec4(0, 0, 0, 0) ];
+ output uvec4 out0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_uvec3
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 2, 4, 9) | ivec4(32, 64, 51, 24) | ivec4(0, 0, 0, 0) ];
+ output uvec3 out0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_to_uvec2
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 2, 4, 9) | ivec4(32, 64, 51, 24) | ivec4(0, 0, 0, 0) ];
+ output uvec2 out0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_uvec4
+ version 310 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output uvec4 out0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_uvec3
+ version 310 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output uvec3 out0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4_to_uvec2
+ version 310 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(0, 0, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 2, 4, 9) | uvec4(32, 64, 51, 24) | uvec4(0, 0, 0, 0) ];
+ output uvec2 out0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_uvec4
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output uvec4 out0 = [ uvec4(1, 0, 0, 1) | uvec4(0, 0, 0, 1) | uvec4(0, 1, 0, 0) | uvec4(1, 1, 1, 1) | uvec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_uvec3
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output uvec3 out0 = [ uvec3(1, 0, 0) | uvec3(0, 0, 0) | uvec3(0, 1, 0) | uvec3(1, 1, 1) | uvec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_to_uvec2
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output uvec2 out0 = [ uvec2(1, 0) | uvec2(0, 0) | uvec2(0, 1) | uvec2(1, 1) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_vec3
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_vec2
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec2 out0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_ivec3
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_ivec2
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_bvec3
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output bvec3 out0 = [ bvec3(false, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_bvec2
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output bvec2 out0 = [ bvec2(false, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_vec3
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(0.0, -2.0, -4.0) | vec3(-32.0, 64.0, -51.0) | vec3(0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_vec2
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(0.0, -2.0) | vec2(-32.0, 64.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_ivec3
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_ivec2
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_bvec3
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, true, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_bvec2
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_vec3
+ version 310 es
+ values
+ {
+ input uvec3 in0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(0.0, 2.0, 4.0) | vec3(32.0, 64.0, 51.0) | vec3(0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_vec2
+ version 310 es
+ values
+ {
+ input uvec3 in0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(0.0, 2.0) | vec2(32.0, 64.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_ivec3
+ version 310 es
+ values
+ {
+ input uvec3 in0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, 2, 4) | ivec3(32, 64, 51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_ivec2
+ version 310 es
+ values
+ {
+ input uvec3 in0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, 2) | ivec2(32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_bvec3
+ version 310 es
+ values
+ {
+ input uvec3 in0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, true, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_bvec2
+ version 310 es
+ values
+ {
+ input uvec3 in0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_vec3
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output vec3 out0 = [ vec3(1.0, 0.0, 0.0) | vec3(0.0, 0.0, 0.0) | vec3(0.0, 1.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_vec2
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output vec2 out0 = [ vec2(1.0, 0.0) | vec2(0.0, 0.0) | vec2(0.0, 1.0) | vec2(1.0, 1.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_ivec3
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output ivec3 out0 = [ ivec3(1, 0, 0) | ivec3(0, 0, 0) | ivec3(0, 1, 0) | ivec3(1, 1, 1) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_ivec2
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output ivec2 out0 = [ ivec2(1, 0) | ivec2(0, 0) | ivec2(0, 1) | ivec2(1, 1) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_bvec3
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_bvec2
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_uvec3
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(0.5, 2.25, 4.875) | vec3(32.0, 64.0, 51.0) | vec3(0.75, 0.0322580645161, 0.0526315789474) ];
+ output uvec3 out0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_to_uvec2
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(0.5, 2.25, 4.875) | vec3(32.0, 64.0, 51.0) | vec3(0.75, 0.0322580645161, 0.0526315789474) ];
+ output uvec2 out0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_uvec3
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, 2, 4) | ivec3(32, 64, 51) | ivec3(0, 0, 0) ];
+ output uvec3 out0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_to_uvec2
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, 2, 4) | ivec3(32, 64, 51) | ivec3(0, 0, 0) ];
+ output uvec2 out0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_uvec3
+ version 310 es
+ values
+ {
+ input uvec3 in0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ output uvec3 out0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3_to_uvec2
+ version 310 es
+ values
+ {
+ input uvec3 in0 = [ uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 0, 0) ];
+ output uvec2 out0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_uvec3
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output uvec3 out0 = [ uvec3(1, 0, 0) | uvec3(0, 0, 0) | uvec3(0, 1, 0) | uvec3(1, 1, 1) | uvec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_to_uvec2
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output uvec2 out0 = [ uvec2(1, 0) | uvec2(0, 0) | uvec2(0, 1) | uvec2(1, 1) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_vec2
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_ivec2
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_bvec2
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output bvec2 out0 = [ bvec2(false, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_vec2
+ version 310 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(0.0, -2.0) | vec2(-32.0, 64.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_ivec2
+ version 310 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_bvec2
+ version 310 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_vec2
+ version 310 es
+ values
+ {
+ input uvec2 in0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(0.0, 2.0) | vec2(32.0, 64.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_ivec2
+ version 310 es
+ values
+ {
+ input uvec2 in0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, 2) | ivec2(32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_bvec2
+ version 310 es
+ values
+ {
+ input uvec2 in0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_vec2
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output vec2 out0 = [ vec2(1.0, 0.0) | vec2(0.0, 0.0) | vec2(0.0, 1.0) | vec2(1.0, 1.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_ivec2
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output ivec2 out0 = [ ivec2(1, 0) | ivec2(0, 0) | ivec2(0, 1) | ivec2(1, 1) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_bvec2
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_to_uvec2
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(0.5, 2.25) | vec2(32.0, 64.0) | vec2(0.75, 0.0322580645161) ];
+ output uvec2 out0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2_to_uvec2
+ version 310 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, 2) | ivec2(32, 64) | ivec2(0, 0) ];
+ output uvec2 out0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2_to_uvec2
+ version 310 es
+ values
+ {
+ input uvec2 in0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ output uvec2 out0 = [ uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_to_uvec2
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output uvec2 out0 = [ uvec2(1, 0) | uvec2(0, 0) | uvec2(0, 1) | uvec2(1, 1) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # vector_to_vector
+group scalar_to_matrix "Scalar to Matrix Conversions"
+
+ case float_to_mat4
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output mat4 out0 = [ mat4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0) | mat4(3.5, 0.0, 0.0, 0.0, 0.0, 3.5, 0.0, 0.0, 0.0, 0.0, 3.5, 0.0, 0.0, 0.0, 0.0, 3.5) | mat4(-0.5, 0.0, 0.0, 0.0, 0.0, -0.5, 0.0, 0.0, 0.0, 0.0, -0.5, 0.0, 0.0, 0.0, 0.0, -0.5) | mat4(-8.25, 0.0, 0.0, 0.0, 0.0, -8.25, 0.0, 0.0, 0.0, 0.0, -8.25, 0.0, 0.0, 0.0, 0.0, -8.25) | mat4(-20.125, 0.0, 0.0, 0.0, 0.0, -20.125, 0.0, 0.0, 0.0, 0.0, -20.125, 0.0, 0.0, 0.0, 0.0, -20.125) | mat4(36.8125, 0.0, 0.0, 0.0, 0.0, 36.8125, 0.0, 0.0, 0.0, 0.0, 36.8125, 0.0, 0.0, 0.0, 0.0, 36.8125) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_mat4x3
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output mat4x3 out0 = [ mat4x3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0) | mat4x3(3.5, 0.0, 0.0, 0.0, 3.5, 0.0, 0.0, 0.0, 3.5, 0.0, 0.0, 0.0) | mat4x3(-0.5, 0.0, 0.0, 0.0, -0.5, 0.0, 0.0, 0.0, -0.5, 0.0, 0.0, 0.0) | mat4x3(-8.25, 0.0, 0.0, 0.0, -8.25, 0.0, 0.0, 0.0, -8.25, 0.0, 0.0, 0.0) | mat4x3(-20.125, 0.0, 0.0, 0.0, -20.125, 0.0, 0.0, 0.0, -20.125, 0.0, 0.0, 0.0) | mat4x3(36.8125, 0.0, 0.0, 0.0, 36.8125, 0.0, 0.0, 0.0, 36.8125, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_mat4x2
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output mat4x2 out0 = [ mat4x2(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(2.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(3.5, 0.0, 0.0, 3.5, 0.0, 0.0, 0.0, 0.0) | mat4x2(-0.5, 0.0, 0.0, -0.5, 0.0, 0.0, 0.0, 0.0) | mat4x2(-8.25, 0.0, 0.0, -8.25, 0.0, 0.0, 0.0, 0.0) | mat4x2(-20.125, 0.0, 0.0, -20.125, 0.0, 0.0, 0.0, 0.0) | mat4x2(36.8125, 0.0, 0.0, 36.8125, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_mat3x4
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output mat3x4 out0 = [ mat3x4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0) | mat3x4(3.5, 0.0, 0.0, 0.0, 0.0, 3.5, 0.0, 0.0, 0.0, 0.0, 3.5, 0.0) | mat3x4(-0.5, 0.0, 0.0, 0.0, 0.0, -0.5, 0.0, 0.0, 0.0, 0.0, -0.5, 0.0) | mat3x4(-8.25, 0.0, 0.0, 0.0, 0.0, -8.25, 0.0, 0.0, 0.0, 0.0, -8.25, 0.0) | mat3x4(-20.125, 0.0, 0.0, 0.0, 0.0, -20.125, 0.0, 0.0, 0.0, 0.0, -20.125, 0.0) | mat3x4(36.8125, 0.0, 0.0, 0.0, 0.0, 36.8125, 0.0, 0.0, 0.0, 0.0, 36.8125, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_mat3
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output mat3 out0 = [ mat3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 2.0) | mat3(3.5, 0.0, 0.0, 0.0, 3.5, 0.0, 0.0, 0.0, 3.5) | mat3(-0.5, 0.0, 0.0, 0.0, -0.5, 0.0, 0.0, 0.0, -0.5) | mat3(-8.25, 0.0, 0.0, 0.0, -8.25, 0.0, 0.0, 0.0, -8.25) | mat3(-20.125, 0.0, 0.0, 0.0, -20.125, 0.0, 0.0, 0.0, -20.125) | mat3(36.8125, 0.0, 0.0, 0.0, 36.8125, 0.0, 0.0, 0.0, 36.8125) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_mat3x2
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output mat3x2 out0 = [ mat3x2(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(2.0, 0.0, 0.0, 2.0, 0.0, 0.0) | mat3x2(3.5, 0.0, 0.0, 3.5, 0.0, 0.0) | mat3x2(-0.5, 0.0, 0.0, -0.5, 0.0, 0.0) | mat3x2(-8.25, 0.0, 0.0, -8.25, 0.0, 0.0) | mat3x2(-20.125, 0.0, 0.0, -20.125, 0.0, 0.0) | mat3x2(36.8125, 0.0, 0.0, 36.8125, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_mat2x4
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output mat2x4 out0 = [ mat2x4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0) | mat2x4(3.5, 0.0, 0.0, 0.0, 0.0, 3.5, 0.0, 0.0) | mat2x4(-0.5, 0.0, 0.0, 0.0, 0.0, -0.5, 0.0, 0.0) | mat2x4(-8.25, 0.0, 0.0, 0.0, 0.0, -8.25, 0.0, 0.0) | mat2x4(-20.125, 0.0, 0.0, 0.0, 0.0, -20.125, 0.0, 0.0) | mat2x4(36.8125, 0.0, 0.0, 0.0, 0.0, 36.8125, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_mat2x3
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output mat2x3 out0 = [ mat2x3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(2.0, 0.0, 0.0, 0.0, 2.0, 0.0) | mat2x3(3.5, 0.0, 0.0, 0.0, 3.5, 0.0) | mat2x3(-0.5, 0.0, 0.0, 0.0, -0.5, 0.0) | mat2x3(-8.25, 0.0, 0.0, 0.0, -8.25, 0.0) | mat2x3(-20.125, 0.0, 0.0, 0.0, -20.125, 0.0) | mat2x3(36.8125, 0.0, 0.0, 0.0, 36.8125, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_to_mat2
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -8.25 | -20.125 | 36.8125 ];
+ output mat2 out0 = [ mat2(0.0, 0.0, 0.0, 0.0) | mat2(1.0, 0.0, 0.0, 1.0) | mat2(2.0, 0.0, 0.0, 2.0) | mat2(3.5, 0.0, 0.0, 3.5) | mat2(-0.5, 0.0, 0.0, -0.5) | mat2(-8.25, 0.0, 0.0, -8.25) | mat2(-20.125, 0.0, 0.0, -20.125) | mat2(36.8125, 0.0, 0.0, 36.8125) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_mat4
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output mat4 out0 = [ mat4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0) | mat4(5.0, 0.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 5.0) | mat4(8.0, 0.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 0.0, 8.0) | mat4(11.0, 0.0, 0.0, 0.0, 0.0, 11.0, 0.0, 0.0, 0.0, 0.0, 11.0, 0.0, 0.0, 0.0, 0.0, 11.0) | mat4(-12.0, 0.0, 0.0, 0.0, 0.0, -12.0, 0.0, 0.0, 0.0, 0.0, -12.0, 0.0, 0.0, 0.0, 0.0, -12.0) | mat4(-66.0, 0.0, 0.0, 0.0, 0.0, -66.0, 0.0, 0.0, 0.0, 0.0, -66.0, 0.0, 0.0, 0.0, 0.0, -66.0) | mat4(-192.0, 0.0, 0.0, 0.0, 0.0, -192.0, 0.0, 0.0, 0.0, 0.0, -192.0, 0.0, 0.0, 0.0, 0.0, -192.0) | mat4(255.0, 0.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 0.0, 255.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_mat4x3
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output mat4x3 out0 = [ mat4x3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0) | mat4x3(5.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0, 0.0) | mat4x3(8.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0) | mat4x3(11.0, 0.0, 0.0, 0.0, 11.0, 0.0, 0.0, 0.0, 11.0, 0.0, 0.0, 0.0) | mat4x3(-12.0, 0.0, 0.0, 0.0, -12.0, 0.0, 0.0, 0.0, -12.0, 0.0, 0.0, 0.0) | mat4x3(-66.0, 0.0, 0.0, 0.0, -66.0, 0.0, 0.0, 0.0, -66.0, 0.0, 0.0, 0.0) | mat4x3(-192.0, 0.0, 0.0, 0.0, -192.0, 0.0, 0.0, 0.0, -192.0, 0.0, 0.0, 0.0) | mat4x3(255.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_mat4x2
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output mat4x2 out0 = [ mat4x2(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(2.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(5.0, 0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(8.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(11.0, 0.0, 0.0, 11.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(-12.0, 0.0, 0.0, -12.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(-66.0, 0.0, 0.0, -66.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(-192.0, 0.0, 0.0, -192.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(255.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_mat3x4
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output mat3x4 out0 = [ mat3x4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0) | mat3x4(5.0, 0.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 5.0, 0.0) | mat3x4(8.0, 0.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 0.0, 8.0, 0.0) | mat3x4(11.0, 0.0, 0.0, 0.0, 0.0, 11.0, 0.0, 0.0, 0.0, 0.0, 11.0, 0.0) | mat3x4(-12.0, 0.0, 0.0, 0.0, 0.0, -12.0, 0.0, 0.0, 0.0, 0.0, -12.0, 0.0) | mat3x4(-66.0, 0.0, 0.0, 0.0, 0.0, -66.0, 0.0, 0.0, 0.0, 0.0, -66.0, 0.0) | mat3x4(-192.0, 0.0, 0.0, 0.0, 0.0, -192.0, 0.0, 0.0, 0.0, 0.0, -192.0, 0.0) | mat3x4(255.0, 0.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 0.0, 255.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_mat3
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output mat3 out0 = [ mat3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 2.0) | mat3(5.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 5.0) | mat3(8.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 8.0) | mat3(11.0, 0.0, 0.0, 0.0, 11.0, 0.0, 0.0, 0.0, 11.0) | mat3(-12.0, 0.0, 0.0, 0.0, -12.0, 0.0, 0.0, 0.0, -12.0) | mat3(-66.0, 0.0, 0.0, 0.0, -66.0, 0.0, 0.0, 0.0, -66.0) | mat3(-192.0, 0.0, 0.0, 0.0, -192.0, 0.0, 0.0, 0.0, -192.0) | mat3(255.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 255.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_mat3x2
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output mat3x2 out0 = [ mat3x2(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(2.0, 0.0, 0.0, 2.0, 0.0, 0.0) | mat3x2(5.0, 0.0, 0.0, 5.0, 0.0, 0.0) | mat3x2(8.0, 0.0, 0.0, 8.0, 0.0, 0.0) | mat3x2(11.0, 0.0, 0.0, 11.0, 0.0, 0.0) | mat3x2(-12.0, 0.0, 0.0, -12.0, 0.0, 0.0) | mat3x2(-66.0, 0.0, 0.0, -66.0, 0.0, 0.0) | mat3x2(-192.0, 0.0, 0.0, -192.0, 0.0, 0.0) | mat3x2(255.0, 0.0, 0.0, 255.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_mat2x4
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output mat2x4 out0 = [ mat2x4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0) | mat2x4(5.0, 0.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0) | mat2x4(8.0, 0.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0) | mat2x4(11.0, 0.0, 0.0, 0.0, 0.0, 11.0, 0.0, 0.0) | mat2x4(-12.0, 0.0, 0.0, 0.0, 0.0, -12.0, 0.0, 0.0) | mat2x4(-66.0, 0.0, 0.0, 0.0, 0.0, -66.0, 0.0, 0.0) | mat2x4(-192.0, 0.0, 0.0, 0.0, 0.0, -192.0, 0.0, 0.0) | mat2x4(255.0, 0.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_mat2x3
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output mat2x3 out0 = [ mat2x3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(2.0, 0.0, 0.0, 0.0, 2.0, 0.0) | mat2x3(5.0, 0.0, 0.0, 0.0, 5.0, 0.0) | mat2x3(8.0, 0.0, 0.0, 0.0, 8.0, 0.0) | mat2x3(11.0, 0.0, 0.0, 0.0, 11.0, 0.0) | mat2x3(-12.0, 0.0, 0.0, 0.0, -12.0, 0.0) | mat2x3(-66.0, 0.0, 0.0, 0.0, -66.0, 0.0) | mat2x3(-192.0, 0.0, 0.0, 0.0, -192.0, 0.0) | mat2x3(255.0, 0.0, 0.0, 0.0, 255.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_to_mat2
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 2 | 5 | 8 | 11 | -12 | -66 | -192 | 255 ];
+ output mat2 out0 = [ mat2(0.0, 0.0, 0.0, 0.0) | mat2(1.0, 0.0, 0.0, 1.0) | mat2(2.0, 0.0, 0.0, 2.0) | mat2(5.0, 0.0, 0.0, 5.0) | mat2(8.0, 0.0, 0.0, 8.0) | mat2(11.0, 0.0, 0.0, 11.0) | mat2(-12.0, 0.0, 0.0, -12.0) | mat2(-66.0, 0.0, 0.0, -66.0) | mat2(-192.0, 0.0, 0.0, -192.0) | mat2(255.0, 0.0, 0.0, 255.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_mat4
+ version 310 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output mat4 out0 = [ mat4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat4(2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0) | mat4(3.0, 0.0, 0.0, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 0.0, 3.0) | mat4(8.0, 0.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 0.0, 8.0) | mat4(9.0, 0.0, 0.0, 0.0, 0.0, 9.0, 0.0, 0.0, 0.0, 0.0, 9.0, 0.0, 0.0, 0.0, 0.0, 9.0) | mat4(12.0, 0.0, 0.0, 0.0, 0.0, 12.0, 0.0, 0.0, 0.0, 0.0, 12.0, 0.0, 0.0, 0.0, 0.0, 12.0) | mat4(10.0, 0.0, 0.0, 0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0.0, 10.0) | mat4(45.0, 0.0, 0.0, 0.0, 0.0, 45.0, 0.0, 0.0, 0.0, 0.0, 45.0, 0.0, 0.0, 0.0, 0.0, 45.0) | mat4(193.0, 0.0, 0.0, 0.0, 0.0, 193.0, 0.0, 0.0, 0.0, 0.0, 193.0, 0.0, 0.0, 0.0, 0.0, 193.0) | mat4(255.0, 0.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 0.0, 255.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_mat4x3
+ version 310 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output mat4x3 out0 = [ mat4x3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat4x3(2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0) | mat4x3(3.0, 0.0, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0) | mat4x3(8.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0) | mat4x3(9.0, 0.0, 0.0, 0.0, 9.0, 0.0, 0.0, 0.0, 9.0, 0.0, 0.0, 0.0) | mat4x3(12.0, 0.0, 0.0, 0.0, 12.0, 0.0, 0.0, 0.0, 12.0, 0.0, 0.0, 0.0) | mat4x3(10.0, 0.0, 0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 10.0, 0.0, 0.0, 0.0) | mat4x3(45.0, 0.0, 0.0, 0.0, 45.0, 0.0, 0.0, 0.0, 45.0, 0.0, 0.0, 0.0) | mat4x3(193.0, 0.0, 0.0, 0.0, 193.0, 0.0, 0.0, 0.0, 193.0, 0.0, 0.0, 0.0) | mat4x3(255.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_mat4x2
+ version 310 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output mat4x2 out0 = [ mat4x2(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(2.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(3.0, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(8.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(9.0, 0.0, 0.0, 9.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(12.0, 0.0, 0.0, 12.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(10.0, 0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(45.0, 0.0, 0.0, 45.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(193.0, 0.0, 0.0, 193.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(255.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_mat3x4
+ version 310 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output mat3x4 out0 = [ mat3x4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3x4(2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0) | mat3x4(3.0, 0.0, 0.0, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 0.0, 3.0, 0.0) | mat3x4(8.0, 0.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 0.0, 8.0, 0.0) | mat3x4(9.0, 0.0, 0.0, 0.0, 0.0, 9.0, 0.0, 0.0, 0.0, 0.0, 9.0, 0.0) | mat3x4(12.0, 0.0, 0.0, 0.0, 0.0, 12.0, 0.0, 0.0, 0.0, 0.0, 12.0, 0.0) | mat3x4(10.0, 0.0, 0.0, 0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0.0, 10.0, 0.0) | mat3x4(45.0, 0.0, 0.0, 0.0, 0.0, 45.0, 0.0, 0.0, 0.0, 0.0, 45.0, 0.0) | mat3x4(193.0, 0.0, 0.0, 0.0, 0.0, 193.0, 0.0, 0.0, 0.0, 0.0, 193.0, 0.0) | mat3x4(255.0, 0.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 0.0, 255.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_mat3
+ version 310 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output mat3 out0 = [ mat3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3(2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 2.0) | mat3(3.0, 0.0, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 3.0) | mat3(8.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 8.0) | mat3(9.0, 0.0, 0.0, 0.0, 9.0, 0.0, 0.0, 0.0, 9.0) | mat3(12.0, 0.0, 0.0, 0.0, 12.0, 0.0, 0.0, 0.0, 12.0) | mat3(10.0, 0.0, 0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 10.0) | mat3(45.0, 0.0, 0.0, 0.0, 45.0, 0.0, 0.0, 0.0, 45.0) | mat3(193.0, 0.0, 0.0, 0.0, 193.0, 0.0, 0.0, 0.0, 193.0) | mat3(255.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0, 0.0, 255.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_mat3x2
+ version 310 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output mat3x2 out0 = [ mat3x2(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3x2(2.0, 0.0, 0.0, 2.0, 0.0, 0.0) | mat3x2(3.0, 0.0, 0.0, 3.0, 0.0, 0.0) | mat3x2(8.0, 0.0, 0.0, 8.0, 0.0, 0.0) | mat3x2(9.0, 0.0, 0.0, 9.0, 0.0, 0.0) | mat3x2(12.0, 0.0, 0.0, 12.0, 0.0, 0.0) | mat3x2(10.0, 0.0, 0.0, 10.0, 0.0, 0.0) | mat3x2(45.0, 0.0, 0.0, 45.0, 0.0, 0.0) | mat3x2(193.0, 0.0, 0.0, 193.0, 0.0, 0.0) | mat3x2(255.0, 0.0, 0.0, 255.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_mat2x4
+ version 310 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output mat2x4 out0 = [ mat2x4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat2x4(2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0) | mat2x4(3.0, 0.0, 0.0, 0.0, 0.0, 3.0, 0.0, 0.0) | mat2x4(8.0, 0.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0) | mat2x4(9.0, 0.0, 0.0, 0.0, 0.0, 9.0, 0.0, 0.0) | mat2x4(12.0, 0.0, 0.0, 0.0, 0.0, 12.0, 0.0, 0.0) | mat2x4(10.0, 0.0, 0.0, 0.0, 0.0, 10.0, 0.0, 0.0) | mat2x4(45.0, 0.0, 0.0, 0.0, 0.0, 45.0, 0.0, 0.0) | mat2x4(193.0, 0.0, 0.0, 0.0, 0.0, 193.0, 0.0, 0.0) | mat2x4(255.0, 0.0, 0.0, 0.0, 0.0, 255.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_mat2x3
+ version 310 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output mat2x3 out0 = [ mat2x3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat2x3(2.0, 0.0, 0.0, 0.0, 2.0, 0.0) | mat2x3(3.0, 0.0, 0.0, 0.0, 3.0, 0.0) | mat2x3(8.0, 0.0, 0.0, 0.0, 8.0, 0.0) | mat2x3(9.0, 0.0, 0.0, 0.0, 9.0, 0.0) | mat2x3(12.0, 0.0, 0.0, 0.0, 12.0, 0.0) | mat2x3(10.0, 0.0, 0.0, 0.0, 10.0, 0.0) | mat2x3(45.0, 0.0, 0.0, 0.0, 45.0, 0.0) | mat2x3(193.0, 0.0, 0.0, 0.0, 193.0, 0.0) | mat2x3(255.0, 0.0, 0.0, 0.0, 255.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_to_mat2
+ version 310 es
+ values
+ {
+ input uint in0 = [ 0 | 2 | 3 | 8 | 9 | 12 | 10 | 45 | 193 | 255 ];
+ output mat2 out0 = [ mat2(0.0, 0.0, 0.0, 0.0) | mat2(2.0, 0.0, 0.0, 2.0) | mat2(3.0, 0.0, 0.0, 3.0) | mat2(8.0, 0.0, 0.0, 8.0) | mat2(9.0, 0.0, 0.0, 9.0) | mat2(12.0, 0.0, 0.0, 12.0) | mat2(10.0, 0.0, 0.0, 10.0) | mat2(45.0, 0.0, 0.0, 45.0) | mat2(193.0, 0.0, 0.0, 193.0) | mat2(255.0, 0.0, 0.0, 255.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_mat4
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output mat4 out0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_mat4x3
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output mat4x3 out0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_mat4x2
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output mat4x2 out0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_mat3x4
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output mat3x4 out0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_mat3
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_mat3x2
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output mat3x2 out0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_mat2x4
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output mat2x4 out0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_mat2x3
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output mat2x3 out0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_to_mat2
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # scalar_to_matrix
+group matrix_to_matrix "Matrix to Matrix Conversions"
+
+ case mat4_to_mat4
+ version 310 es
+ values
+ {
+ input mat4 in0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 9.975, -6.542, 0.015625, 9.975) ];
+ output mat4 out0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 9.975, -6.542, 0.015625, 9.975) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4_to_mat4x3
+ version 310 es
+ values
+ {
+ input mat4 in0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 9.975, -6.542, 0.015625, 9.975) ];
+ output mat4x3 out0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125, 9.975, -6.542, 0.015625) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4_to_mat4x2
+ version 310 es
+ values
+ {
+ input mat4 in0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 9.975, -6.542, 0.015625, 9.975) ];
+ output mat4x2 out0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 9.975, -6.542) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4_to_mat3x4
+ version 310 es
+ values
+ {
+ input mat4 in0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 9.975, -6.542, 0.015625, 9.975) ];
+ output mat3x4 out0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4_to_mat3
+ version 310 es
+ values
+ {
+ input mat4 in0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 9.975, -6.542, 0.015625, 9.975) ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4_to_mat3x2
+ version 310 es
+ values
+ {
+ input mat4 in0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 9.975, -6.542, 0.015625, 9.975) ];
+ output mat3x2 out0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4_to_mat2x4
+ version 310 es
+ values
+ {
+ input mat4 in0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 9.975, -6.542, 0.015625, 9.975) ];
+ output mat2x4 out0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4_to_mat2x3
+ version 310 es
+ values
+ {
+ input mat4 in0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 9.975, -6.542, 0.015625, 9.975) ];
+ output mat2x3 out0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4_to_mat2
+ version 310 es
+ values
+ {
+ input mat4 in0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 9.975, -6.542, 0.015625, 9.975) ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, 32.0, 12.5, 0.0208333333333) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x3_to_mat4
+ version 310 es
+ values
+ {
+ input mat4x3 in0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125, 9.975, -6.542, 0.015625) ];
+ output mat4 out0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, 0.0, 12.5, 0.0208333333333, 0.0625, 0.0, -0.75, -8.425, 0.03125, 0.0, 9.975, -6.542, 0.015625, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x3_to_mat4x3
+ version 310 es
+ values
+ {
+ input mat4x3 in0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125, 9.975, -6.542, 0.015625) ];
+ output mat4x3 out0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125, 9.975, -6.542, 0.015625) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x3_to_mat4x2
+ version 310 es
+ values
+ {
+ input mat4x3 in0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125, 9.975, -6.542, 0.015625) ];
+ output mat4x2 out0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 9.975, -6.542) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x3_to_mat3x4
+ version 310 es
+ values
+ {
+ input mat4x3 in0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125, 9.975, -6.542, 0.015625) ];
+ output mat3x4 out0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, 0.0, 12.5, 0.0208333333333, 0.0625, 0.0, -0.75, -8.425, 0.03125, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x3_to_mat3
+ version 310 es
+ values
+ {
+ input mat4x3 in0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125, 9.975, -6.542, 0.015625) ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x3_to_mat3x2
+ version 310 es
+ values
+ {
+ input mat4x3 in0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125, 9.975, -6.542, 0.015625) ];
+ output mat3x2 out0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x3_to_mat2x4
+ version 310 es
+ values
+ {
+ input mat4x3 in0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125, 9.975, -6.542, 0.015625) ];
+ output mat2x4 out0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, 0.0, 12.5, 0.0208333333333, 0.0625, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x3_to_mat2x3
+ version 310 es
+ values
+ {
+ input mat4x3 in0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125, 9.975, -6.542, 0.015625) ];
+ output mat2x3 out0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x3_to_mat2
+ version 310 es
+ values
+ {
+ input mat4x3 in0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125, 9.975, -6.542, 0.015625) ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, 32.0, 12.5, 0.0208333333333) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x2_to_mat4
+ version 310 es
+ values
+ {
+ input mat4x2 in0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 9.975, -6.542) ];
+ output mat4 out0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.0, 0.0, 12.5, 0.0208333333333, 0.0, 0.0, -0.75, -8.425, 1.0, 0.0, 9.975, -6.542, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x2_to_mat4x3
+ version 310 es
+ values
+ {
+ input mat4x2 in0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 9.975, -6.542) ];
+ output mat4x3 out0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.0, 12.5, 0.0208333333333, 0.0, -0.75, -8.425, 1.0, 9.975, -6.542, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x2_to_mat4x2
+ version 310 es
+ values
+ {
+ input mat4x2 in0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 9.975, -6.542) ];
+ output mat4x2 out0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 9.975, -6.542) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x2_to_mat3x4
+ version 310 es
+ values
+ {
+ input mat4x2 in0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 9.975, -6.542) ];
+ output mat3x4 out0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.0, 0.0, 12.5, 0.0208333333333, 0.0, 0.0, -0.75, -8.425, 1.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x2_to_mat3
+ version 310 es
+ values
+ {
+ input mat4x2 in0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 9.975, -6.542) ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.0, 12.5, 0.0208333333333, 0.0, -0.75, -8.425, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x2_to_mat3x2
+ version 310 es
+ values
+ {
+ input mat4x2 in0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 9.975, -6.542) ];
+ output mat3x2 out0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x2_to_mat2x4
+ version 310 es
+ values
+ {
+ input mat4x2 in0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 9.975, -6.542) ];
+ output mat2x4 out0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.0, 0.0, 12.5, 0.0208333333333, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x2_to_mat2x3
+ version 310 es
+ values
+ {
+ input mat4x2 in0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 9.975, -6.542) ];
+ output mat2x3 out0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.0, 12.5, 0.0208333333333, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x2_to_mat2
+ version 310 es
+ values
+ {
+ input mat4x2 in0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 9.975, -6.542) ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, 32.0, 12.5, 0.0208333333333) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x4_to_mat4
+ version 310 es
+ values
+ {
+ input mat3x4 in0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125) ];
+ output mat4 out0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125, 0.0, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x4_to_mat4x3
+ version 310 es
+ values
+ {
+ input mat3x4 in0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125) ];
+ output mat4x3 out0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x4_to_mat4x2
+ version 310 es
+ values
+ {
+ input mat3x4 in0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125) ];
+ output mat4x2 out0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x4_to_mat3x4
+ version 310 es
+ values
+ {
+ input mat3x4 in0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125) ];
+ output mat3x4 out0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x4_to_mat3
+ version 310 es
+ values
+ {
+ input mat3x4 in0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125) ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x4_to_mat3x2
+ version 310 es
+ values
+ {
+ input mat3x4 in0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125) ];
+ output mat3x2 out0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x4_to_mat2x4
+ version 310 es
+ values
+ {
+ input mat3x4 in0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125) ];
+ output mat2x4 out0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x4_to_mat2x3
+ version 310 es
+ values
+ {
+ input mat3x4 in0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125) ];
+ output mat2x3 out0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x4_to_mat2
+ version 310 es
+ values
+ {
+ input mat3x4 in0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, -0.75, -8.425, 0.03125, -0.0125) ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, 32.0, 12.5, 0.0208333333333) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3_to_mat4
+ version 310 es
+ values
+ {
+ input mat3 in0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ output mat4 out0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, 0.0, 12.5, 0.0208333333333, 0.0625, 0.0, -0.75, -8.425, 0.03125, 0.0, 0.0, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3_to_mat4x3
+ version 310 es
+ values
+ {
+ input mat3 in0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ output mat4x3 out0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3_to_mat4x2
+ version 310 es
+ values
+ {
+ input mat3 in0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ output mat4x2 out0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3_to_mat3x4
+ version 310 es
+ values
+ {
+ input mat3 in0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ output mat3x4 out0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, 0.0, 12.5, 0.0208333333333, 0.0625, 0.0, -0.75, -8.425, 0.03125, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3_to_mat3
+ version 310 es
+ values
+ {
+ input mat3 in0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3_to_mat3x2
+ version 310 es
+ values
+ {
+ input mat3 in0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ output mat3x2 out0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3_to_mat2x4
+ version 310 es
+ values
+ {
+ input mat3 in0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ output mat2x4 out0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, 0.0, 12.5, 0.0208333333333, 0.0625, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3_to_mat2x3
+ version 310 es
+ values
+ {
+ input mat3 in0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ output mat2x3 out0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3_to_mat2
+ version 310 es
+ values
+ {
+ input mat3 in0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, -0.75, -8.425, 0.03125) ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, 32.0, 12.5, 0.0208333333333) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x2_to_mat4
+ version 310 es
+ values
+ {
+ input mat3x2 in0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ output mat4 out0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.0, 0.0, 12.5, 0.0208333333333, 0.0, 0.0, -0.75, -8.425, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x2_to_mat4x3
+ version 310 es
+ values
+ {
+ input mat3x2 in0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ output mat4x3 out0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.0, 12.5, 0.0208333333333, 0.0, -0.75, -8.425, 1.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x2_to_mat4x2
+ version 310 es
+ values
+ {
+ input mat3x2 in0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ output mat4x2 out0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x2_to_mat3x4
+ version 310 es
+ values
+ {
+ input mat3x2 in0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ output mat3x4 out0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.0, 0.0, 12.5, 0.0208333333333, 0.0, 0.0, -0.75, -8.425, 1.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x2_to_mat3
+ version 310 es
+ values
+ {
+ input mat3x2 in0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.0, 12.5, 0.0208333333333, 0.0, -0.75, -8.425, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x2_to_mat3x2
+ version 310 es
+ values
+ {
+ input mat3x2 in0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ output mat3x2 out0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x2_to_mat2x4
+ version 310 es
+ values
+ {
+ input mat3x2 in0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ output mat2x4 out0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.0, 0.0, 12.5, 0.0208333333333, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x2_to_mat2x3
+ version 310 es
+ values
+ {
+ input mat3x2 in0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ output mat2x3 out0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.0, 12.5, 0.0208333333333, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x2_to_mat2
+ version 310 es
+ values
+ {
+ input mat3x2 in0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, -0.75, -8.425) ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, 32.0, 12.5, 0.0208333333333) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x4_to_mat4
+ version 310 es
+ values
+ {
+ input mat2x4 in0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5) ];
+ output mat4 out0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x4_to_mat4x3
+ version 310 es
+ values
+ {
+ input mat2x4 in0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5) ];
+ output mat4x3 out0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x4_to_mat4x2
+ version 310 es
+ values
+ {
+ input mat2x4 in0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5) ];
+ output mat4x2 out0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x4_to_mat3x4
+ version 310 es
+ values
+ {
+ input mat2x4 in0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5) ];
+ output mat3x4 out0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5, 0.0, 0.0, 1.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x4_to_mat3
+ version 310 es
+ values
+ {
+ input mat2x4 in0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5) ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x4_to_mat3x2
+ version 310 es
+ values
+ {
+ input mat2x4 in0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5) ];
+ output mat3x2 out0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x4_to_mat2x4
+ version 310 es
+ values
+ {
+ input mat2x4 in0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5) ];
+ output mat2x4 out0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x4_to_mat2x3
+ version 310 es
+ values
+ {
+ input mat2x4 in0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5) ];
+ output mat2x3 out0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x4_to_mat2
+ version 310 es
+ values
+ {
+ input mat2x4 in0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, -6.725, 12.5, 0.0208333333333, 0.0625, -0.5) ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, 32.0, 12.5, 0.0208333333333) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x3_to_mat4
+ version 310 es
+ values
+ {
+ input mat2x3 in0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ output mat4 out0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, 32.0, 0.125, 0.0, 12.5, 0.0208333333333, 0.0625, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x3_to_mat4x3
+ version 310 es
+ values
+ {
+ input mat2x3 in0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ output mat4x3 out0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x3_to_mat4x2
+ version 310 es
+ values
+ {
+ input mat2x3 in0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ output mat4x2 out0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, 32.0, 12.5, 0.0208333333333, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x3_to_mat3x4
+ version 310 es
+ values
+ {
+ input mat2x3 in0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ output mat3x4 out0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, 32.0, 0.125, 0.0, 12.5, 0.0208333333333, 0.0625, 0.0, 0.0, 0.0, 1.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x3_to_mat3
+ version 310 es
+ values
+ {
+ input mat2x3 in0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x3_to_mat3x2
+ version 310 es
+ values
+ {
+ input mat2x3 in0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ output mat3x2 out0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, 32.0, 12.5, 0.0208333333333, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x3_to_mat2x4
+ version 310 es
+ values
+ {
+ input mat2x3 in0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ output mat2x4 out0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, 32.0, 0.125, 0.0, 12.5, 0.0208333333333, 0.0625, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x3_to_mat2x3
+ version 310 es
+ values
+ {
+ input mat2x3 in0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ output mat2x3 out0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x3_to_mat2
+ version 310 es
+ values
+ {
+ input mat2x3 in0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, 32.0, 0.125, 12.5, 0.0208333333333, 0.0625) ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, 32.0, 12.5, 0.0208333333333) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2_to_mat4
+ version 310 es
+ values
+ {
+ input mat2 in0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(8.0, -24.0, 16.0, -16.0) | mat2(0.125, 0.03125, 0.0625, 0.015625) | mat2(-18.725, -0.0125, -0.5, 19.975) ];
+ output mat4 out0 = [ mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, -0.75, 0.0, 0.0, 12.5, 9.975, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(6.5, -0.75, 0.0, 0.0, 12.5, 9.975, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(8.0, -24.0, 0.0, 0.0, 16.0, -16.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(0.125, 0.03125, 0.0, 0.0, 0.0625, 0.015625, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(-18.725, -0.0125, 0.0, 0.0, -0.5, 19.975, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2_to_mat4x3
+ version 310 es
+ values
+ {
+ input mat2 in0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(8.0, -24.0, 16.0, -16.0) | mat2(0.125, 0.03125, 0.0625, 0.015625) | mat2(-18.725, -0.0125, -0.5, 19.975) ];
+ output mat4x3 out0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, -0.75, 0.0, 12.5, 9.975, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(6.5, -0.75, 0.0, 12.5, 9.975, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(8.0, -24.0, 0.0, 16.0, -16.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(0.125, 0.03125, 0.0, 0.0625, 0.015625, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat4x3(-18.725, -0.0125, 0.0, -0.5, 19.975, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2_to_mat4x2
+ version 310 es
+ values
+ {
+ input mat2 in0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(8.0, -24.0, 16.0, -16.0) | mat2(0.125, 0.03125, 0.0625, 0.015625) | mat2(-18.725, -0.0125, -0.5, 19.975) ];
+ output mat4x2 out0 = [ mat4x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, -0.75, 12.5, 9.975, 0.0, 0.0, 0.0, 0.0) | mat4x2(6.5, -0.75, 12.5, 9.975, 0.0, 0.0, 0.0, 0.0) | mat4x2(8.0, -24.0, 16.0, -16.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(0.125, 0.03125, 0.0625, 0.015625, 0.0, 0.0, 0.0, 0.0) | mat4x2(-18.725, -0.0125, -0.5, 19.975, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2_to_mat3x4
+ version 310 es
+ values
+ {
+ input mat2 in0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(8.0, -24.0, 16.0, -16.0) | mat2(0.125, 0.03125, 0.0625, 0.015625) | mat2(-18.725, -0.0125, -0.5, 19.975) ];
+ output mat3x4 out0 = [ mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, -0.75, 0.0, 0.0, 12.5, 9.975, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(6.5, -0.75, 0.0, 0.0, 12.5, 9.975, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(8.0, -24.0, 0.0, 0.0, 16.0, -16.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(0.125, 0.03125, 0.0, 0.0, 0.0625, 0.015625, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(-18.725, -0.0125, 0.0, 0.0, -0.5, 19.975, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2_to_mat3
+ version 310 es
+ values
+ {
+ input mat2 in0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(8.0, -24.0, 16.0, -16.0) | mat2(0.125, 0.03125, 0.0625, 0.015625) | mat2(-18.725, -0.0125, -0.5, 19.975) ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, -0.75, 0.0, 12.5, 9.975, 0.0, 0.0, 0.0, 1.0) | mat3(6.5, -0.75, 0.0, 12.5, 9.975, 0.0, 0.0, 0.0, 1.0) | mat3(8.0, -24.0, 0.0, 16.0, -16.0, 0.0, 0.0, 0.0, 1.0) | mat3(0.125, 0.03125, 0.0, 0.0625, 0.015625, 0.0, 0.0, 0.0, 1.0) | mat3(-18.725, -0.0125, 0.0, -0.5, 19.975, 0.0, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2_to_mat3x2
+ version 310 es
+ values
+ {
+ input mat2 in0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(8.0, -24.0, 16.0, -16.0) | mat2(0.125, 0.03125, 0.0625, 0.015625) | mat2(-18.725, -0.0125, -0.5, 19.975) ];
+ output mat3x2 out0 = [ mat3x2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat3x2(6.5, -0.75, 12.5, 9.975, 0.0, 0.0) | mat3x2(6.5, -0.75, 12.5, 9.975, 0.0, 0.0) | mat3x2(8.0, -24.0, 16.0, -16.0, 0.0, 0.0) | mat3x2(0.125, 0.03125, 0.0625, 0.015625, 0.0, 0.0) | mat3x2(-18.725, -0.0125, -0.5, 19.975, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2_to_mat2x4
+ version 310 es
+ values
+ {
+ input mat2 in0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(8.0, -24.0, 16.0, -16.0) | mat2(0.125, 0.03125, 0.0625, 0.015625) | mat2(-18.725, -0.0125, -0.5, 19.975) ];
+ output mat2x4 out0 = [ mat2x4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0) | mat2x4(6.5, -0.75, 0.0, 0.0, 12.5, 9.975, 0.0, 0.0) | mat2x4(6.5, -0.75, 0.0, 0.0, 12.5, 9.975, 0.0, 0.0) | mat2x4(8.0, -24.0, 0.0, 0.0, 16.0, -16.0, 0.0, 0.0) | mat2x4(0.125, 0.03125, 0.0, 0.0, 0.0625, 0.015625, 0.0, 0.0) | mat2x4(-18.725, -0.0125, 0.0, 0.0, -0.5, 19.975, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2_to_mat2x3
+ version 310 es
+ values
+ {
+ input mat2 in0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(8.0, -24.0, 16.0, -16.0) | mat2(0.125, 0.03125, 0.0625, 0.015625) | mat2(-18.725, -0.0125, -0.5, 19.975) ];
+ output mat2x3 out0 = [ mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat2x3(6.5, -0.75, 0.0, 12.5, 9.975, 0.0) | mat2x3(6.5, -0.75, 0.0, 12.5, 9.975, 0.0) | mat2x3(8.0, -24.0, 0.0, 16.0, -16.0, 0.0) | mat2x3(0.125, 0.03125, 0.0, 0.0625, 0.015625, 0.0) | mat2x3(-18.725, -0.0125, 0.0, -0.5, 19.975, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2_to_mat2
+ version 310 es
+ values
+ {
+ input mat2 in0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(8.0, -24.0, 16.0, -16.0) | mat2(0.125, 0.03125, 0.0625, 0.015625) | mat2(-18.725, -0.0125, -0.5, 19.975) ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 1.0) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(6.5, -0.75, 12.5, 9.975) | mat2(8.0, -24.0, 16.0, -16.0) | mat2(0.125, 0.03125, 0.0625, 0.015625) | mat2(-18.725, -0.0125, -0.5, 19.975) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # matrix_to_matrix
+group vector_combine "Vector Combine Constructors"
+
+ case vec2_vec2_to_vec4
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.75, -0.0322580645161) ];
+ input vec2 in1 = [ vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.5, -2.25) | vec2(-0.75, -0.0322580645161) ];
+ output vec4 out0 = [ vec4(-0.5, -2.25, -32.0, 64.0) | vec4(-32.0, 64.0, 1.0, 1.25) | vec4(1.0, 1.25, 0.0, 0.5) | vec4(0.0, 0.5, -0.5, -2.25) | vec4(-0.75, -0.0322580645161, -0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_vec2_to_ivec4
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.75, -0.0322580645161) ];
+ input vec2 in1 = [ vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.5, -2.25) | vec2(-0.75, -0.0322580645161) ];
+ output ivec4 out0 = [ ivec4(0, -2, -32, 64) | ivec4(-32, 64, 1, 1) | ivec4(1, 1, 0, 0) | ivec4(0, 0, 0, -2) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_vec2_to_bvec4
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.75, -0.0322580645161) ];
+ input vec2 in1 = [ vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.5, -2.25) | vec2(-0.75, -0.0322580645161) ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, false, true) | bvec4(false, true, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_bvec2_to_vec4
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(false, false) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) ];
+ input bvec2 in1 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 1.0, 0.0) | vec4(1.0, 0.0, 0.0, 0.0) | vec4(0.0, 1.0, 0.0, 1.0) | vec4(0.0, 0.0, 1.0, 1.0) | vec4(1.0, 1.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_bvec2_to_ivec4
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(false, false) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) ];
+ input bvec2 in1 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output ivec4 out0 = [ ivec4(0, 0, 1, 0) | ivec4(1, 0, 0, 0) | ivec4(0, 1, 0, 1) | ivec4(0, 0, 1, 1) | ivec4(1, 1, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_bvec2_to_bvec4
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(false, false) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) ];
+ input bvec2 in1 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, true, false) | bvec4(true, false, false, false) | bvec4(false, true, false, true) | bvec4(false, false, true, true) | bvec4(true, true, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_float_to_vec4
+ version 310 es
+ values
+ {
+ input float in0 = [ 1.0 | 0.0 | -0.5 | -8.25 | 3.5 | -20.125 | 36.8125 | 2.0 ];
+ input float in1 = [ 0.0 | 36.8125 | -8.25 | 2.0 | 3.5 | 1.0 | -20.125 | -0.5 ];
+ input float in2 = [ 3.5 | 36.8125 | -8.25 | 1.0 | 2.0 | 0.0 | -20.125 | -0.5 ];
+ input float in3 = [ 3.5 | 36.8125 | 1.0 | -8.25 | 2.0 | 0.0 | -0.5 | -20.125 ];
+ output vec4 out0 = [ vec4(1.0, 0.0, 3.5, 3.5) | vec4(0.0, 36.8125, 36.8125, 36.8125) | vec4(-0.5, -8.25, -8.25, 1.0) | vec4(-8.25, 2.0, 1.0, -8.25) | vec4(3.5, 3.5, 2.0, 2.0) | vec4(-20.125, 1.0, 0.0, 0.0) | vec4(36.8125, -20.125, -20.125, -0.5) | vec4(2.0, -0.5, -0.5, -20.125) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_float_to_ivec4
+ version 310 es
+ values
+ {
+ input float in0 = [ 1.0 | 0.0 | -0.5 | -8.25 | 3.5 | -20.125 | 36.8125 | 2.0 ];
+ input float in1 = [ 0.0 | 36.8125 | -8.25 | 2.0 | 3.5 | 1.0 | -20.125 | -0.5 ];
+ input float in2 = [ 3.5 | 36.8125 | -8.25 | 1.0 | 2.0 | 0.0 | -20.125 | -0.5 ];
+ input float in3 = [ 3.5 | 36.8125 | 1.0 | -8.25 | 2.0 | 0.0 | -0.5 | -20.125 ];
+ output ivec4 out0 = [ ivec4(1, 0, 3, 3) | ivec4(0, 36, 36, 36) | ivec4(0, -8, -8, 1) | ivec4(-8, 2, 1, -8) | ivec4(3, 3, 2, 2) | ivec4(-20, 1, 0, 0) | ivec4(36, -20, -20, 0) | ivec4(2, 0, 0, -20) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_float_to_bvec4
+ version 310 es
+ values
+ {
+ input float in0 = [ 1.0 | 0.0 | -0.5 | -8.25 | 3.5 | -20.125 | 36.8125 | 2.0 ];
+ input float in1 = [ 0.0 | 36.8125 | -8.25 | 2.0 | 3.5 | 1.0 | -20.125 | -0.5 ];
+ input float in2 = [ 3.5 | 36.8125 | -8.25 | 1.0 | 2.0 | 0.0 | -20.125 | -0.5 ];
+ input float in3 = [ 3.5 | 36.8125 | 1.0 | -8.25 | 2.0 | 0.0 | -0.5 | -20.125 ];
+ output bvec4 out0 = [ bvec4(true, false, true, true) | bvec4(false, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_int_to_vec4
+ version 310 es
+ values
+ {
+ input int in0 = [ -12 | -66 | 2 | 5 | 8 | -192 | 255 | 1 | 0 | 11 ];
+ input int in1 = [ 2 | 5 | -66 | 11 | -192 | 8 | -12 | 1 | 255 | 0 ];
+ input int in2 = [ 11 | 255 | 5 | 8 | 2 | -192 | -12 | -66 | 1 | 0 ];
+ input int in3 = [ -192 | -66 | 8 | -12 | 1 | 2 | 0 | 255 | 5 | 11 ];
+ output vec4 out0 = [ vec4(-12.0, 2.0, 11.0, -192.0) | vec4(-66.0, 5.0, 255.0, -66.0) | vec4(2.0, -66.0, 5.0, 8.0) | vec4(5.0, 11.0, 8.0, -12.0) | vec4(8.0, -192.0, 2.0, 1.0) | vec4(-192.0, 8.0, -192.0, 2.0) | vec4(255.0, -12.0, -12.0, 0.0) | vec4(1.0, 1.0, -66.0, 255.0) | vec4(0.0, 255.0, 1.0, 5.0) | vec4(11.0, 0.0, 0.0, 11.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_int_to_ivec4
+ version 310 es
+ values
+ {
+ input int in0 = [ -12 | -66 | 2 | 5 | 8 | -192 | 255 | 1 | 0 | 11 ];
+ input int in1 = [ 2 | 5 | -66 | 11 | -192 | 8 | -12 | 1 | 255 | 0 ];
+ input int in2 = [ 11 | 255 | 5 | 8 | 2 | -192 | -12 | -66 | 1 | 0 ];
+ input int in3 = [ -192 | -66 | 8 | -12 | 1 | 2 | 0 | 255 | 5 | 11 ];
+ output ivec4 out0 = [ ivec4(-12, 2, 11, -192) | ivec4(-66, 5, 255, -66) | ivec4(2, -66, 5, 8) | ivec4(5, 11, 8, -12) | ivec4(8, -192, 2, 1) | ivec4(-192, 8, -192, 2) | ivec4(255, -12, -12, 0) | ivec4(1, 1, -66, 255) | ivec4(0, 255, 1, 5) | ivec4(11, 0, 0, 11) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_int_to_bvec4
+ version 310 es
+ values
+ {
+ input int in0 = [ -12 | -66 | 2 | 5 | 8 | -192 | 255 | 1 | 0 | 11 ];
+ input int in1 = [ 2 | 5 | -66 | 11 | -192 | 8 | -12 | 1 | 255 | 0 ];
+ input int in2 = [ 11 | 255 | 5 | 8 | 2 | -192 | -12 | -66 | 1 | 0 ];
+ input int in3 = [ -192 | -66 | 8 | -12 | 1 | 2 | 0 | 255 | 5 | 11 ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, false) | bvec4(true, true, true, true) | bvec4(false, true, true, true) | bvec4(true, false, false, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint_uint_uint_to_vec4
+ version 310 es
+ values
+ {
+ input uint in0 = [ 193 | 3 | 255 | 8 | 10 | 9 | 2 | 12 | 0 | 45 ];
+ input uint in1 = [ 12 | 45 | 193 | 2 | 8 | 255 | 0 | 3 | 9 | 10 ];
+ input uint in2 = [ 9 | 8 | 12 | 2 | 255 | 45 | 3 | 0 | 193 | 10 ];
+ input uint in3 = [ 3 | 9 | 12 | 2 | 255 | 193 | 0 | 10 | 45 | 8 ];
+ output vec4 out0 = [ vec4(193.0, 12.0, 9.0, 3.0) | vec4(3.0, 45.0, 8.0, 9.0) | vec4(255.0, 193.0, 12.0, 12.0) | vec4(8.0, 2.0, 2.0, 2.0) | vec4(10.0, 8.0, 255.0, 255.0) | vec4(9.0, 255.0, 45.0, 193.0) | vec4(2.0, 0.0, 3.0, 0.0) | vec4(12.0, 3.0, 0.0, 10.0) | vec4(0.0, 9.0, 193.0, 45.0) | vec4(45.0, 10.0, 10.0, 8.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint_uint_uint_to_ivec4
+ version 310 es
+ values
+ {
+ input uint in0 = [ 193 | 3 | 255 | 8 | 10 | 9 | 2 | 12 | 0 | 45 ];
+ input uint in1 = [ 12 | 45 | 193 | 2 | 8 | 255 | 0 | 3 | 9 | 10 ];
+ input uint in2 = [ 9 | 8 | 12 | 2 | 255 | 45 | 3 | 0 | 193 | 10 ];
+ input uint in3 = [ 3 | 9 | 12 | 2 | 255 | 193 | 0 | 10 | 45 | 8 ];
+ output ivec4 out0 = [ ivec4(193, 12, 9, 3) | ivec4(3, 45, 8, 9) | ivec4(255, 193, 12, 12) | ivec4(8, 2, 2, 2) | ivec4(10, 8, 255, 255) | ivec4(9, 255, 45, 193) | ivec4(2, 0, 3, 0) | ivec4(12, 3, 0, 10) | ivec4(0, 9, 193, 45) | ivec4(45, 10, 10, 8) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint_uint_uint_to_bvec4
+ version 310 es
+ values
+ {
+ input uint in0 = [ 193 | 3 | 255 | 8 | 10 | 9 | 2 | 12 | 0 | 45 ];
+ input uint in1 = [ 12 | 45 | 193 | 2 | 8 | 255 | 0 | 3 | 9 | 10 ];
+ input uint in2 = [ 9 | 8 | 12 | 2 | 255 | 45 | 3 | 0 | 193 | 10 ];
+ input uint in3 = [ 3 | 9 | 12 | 2 | 255 | 193 | 0 | 10 | 45 | 8 ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, false, true, false) | bvec4(true, true, false, true) | bvec4(false, true, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_bool_to_vec4
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ true | false ];
+ input bool in2 = [ false | true ];
+ input bool in3 = [ false | true ];
+ output vec4 out0 = [ vec4(1.0, 1.0, 0.0, 0.0) | vec4(0.0, 0.0, 1.0, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_bool_to_ivec4
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ true | false ];
+ input bool in2 = [ false | true ];
+ input bool in3 = [ false | true ];
+ output ivec4 out0 = [ ivec4(1, 1, 0, 0) | ivec4(0, 0, 1, 1) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_bool_to_bvec4
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ true | false ];
+ input bool in2 = [ false | true ];
+ input bool in3 = [ false | true ];
+ output bvec4 out0 = [ bvec4(true, true, false, false) | bvec4(false, false, true, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_bool_to_vec4
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | true | false | false | false | true | false | false | true | true ];
+ input float in1 = [ 36.8125 | 0.0 | -8.25 | 1.0 | -0.5 | 0.0 | 2.0 | -20.125 | 3.5 | 1.0 ];
+ input int in2 = [ -66 | 2 | 255 | 11 | 1 | 8 | -192 | -12 | 0 | 5 ];
+ input bool in3 = [ true | true | false | false | true | true | false | true | false | false ];
+ output vec4 out0 = [ vec4(1.0, 36.8125, -66.0, 1.0) | vec4(1.0, 0.0, 2.0, 1.0) | vec4(0.0, -8.25, 255.0, 0.0) | vec4(0.0, 1.0, 11.0, 0.0) | vec4(0.0, -0.5, 1.0, 1.0) | vec4(1.0, 0.0, 8.0, 1.0) | vec4(0.0, 2.0, -192.0, 0.0) | vec4(0.0, -20.125, -12.0, 1.0) | vec4(1.0, 3.5, 0.0, 0.0) | vec4(1.0, 1.0, 5.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_bool_to_ivec4
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | true | false | false | false | true | false | false | true | true ];
+ input float in1 = [ 36.8125 | 0.0 | -8.25 | 1.0 | -0.5 | 0.0 | 2.0 | -20.125 | 3.5 | 1.0 ];
+ input int in2 = [ -66 | 2 | 255 | 11 | 1 | 8 | -192 | -12 | 0 | 5 ];
+ input bool in3 = [ true | true | false | false | true | true | false | true | false | false ];
+ output ivec4 out0 = [ ivec4(1, 36, -66, 1) | ivec4(1, 0, 2, 1) | ivec4(0, -8, 255, 0) | ivec4(0, 1, 11, 0) | ivec4(0, 0, 1, 1) | ivec4(1, 0, 8, 1) | ivec4(0, 2, -192, 0) | ivec4(0, -20, -12, 1) | ivec4(1, 3, 0, 0) | ivec4(1, 1, 5, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_bool_to_bvec4
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | true | false | false | false | true | false | false | true | true ];
+ input float in1 = [ 36.8125 | 0.0 | -8.25 | 1.0 | -0.5 | 0.0 | 2.0 | -20.125 | 3.5 | 1.0 ];
+ input int in2 = [ -66 | 2 | 255 | 11 | 1 | 8 | -192 | -12 | 0 | 5 ];
+ input bool in3 = [ true | true | false | false | true | true | false | true | false | false ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(true, false, true, true) | bvec4(false, true, true, false) | bvec4(false, true, true, false) | bvec4(false, true, true, true) | bvec4(true, false, true, true) | bvec4(false, true, true, false) | bvec4(false, true, true, true) | bvec4(true, true, false, false) | bvec4(true, true, true, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_to_vec4
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(-0.75, -0.0322580645161) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) ];
+ input ivec2 in1 = [ ivec2(0, 0) | ivec2(0, -2) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.0, 0.0) | vec4(-0.75, -0.0322580645161, 0.0, -2.0) | vec4(-0.5, -2.25, 0.0, 0.0) | vec4(-32.0, 64.0, -32.0, 64.0) | vec4(1.0, 1.25, 1.0, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_to_ivec4
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(-0.75, -0.0322580645161) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) ];
+ input ivec2 in1 = [ ivec2(0, 0) | ivec2(0, -2) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(0, 0, 0, -2) | ivec4(0, -2, 0, 0) | ivec4(-32, 64, -32, 64) | ivec4(1, 1, 1, 1) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_to_bvec4
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(-0.75, -0.0322580645161) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) ];
+ input ivec2 in1 = [ ivec2(0, 0) | ivec2(0, -2) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) ];
+ output bvec4 out0 = [ bvec4(false, true, false, false) | bvec4(true, true, false, true) | bvec4(true, true, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bvec2_to_vec4
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.5, -2.25) ];
+ input bvec2 in1 = [ bvec2(false, true) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(true, false) ];
+ output vec4 out0 = [ vec4(-0.75, -0.0322580645161, 0.0, 1.0) | vec4(-32.0, 64.0, 0.0, 0.0) | vec4(1.0, 1.25, 0.0, 0.0) | vec4(0.0, 0.5, 1.0, 1.0) | vec4(-0.5, -2.25, 1.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bvec2_to_ivec4
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.5, -2.25) ];
+ input bvec2 in1 = [ bvec2(false, true) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(true, false) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 1) | ivec4(-32, 64, 0, 0) | ivec4(1, 1, 0, 0) | ivec4(0, 0, 1, 1) | ivec4(0, -2, 1, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bvec2_to_bvec4
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.5, -2.25) ];
+ input bvec2 in1 = [ bvec2(false, true) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(true, false) ];
+ output bvec4 out0 = [ bvec4(true, true, false, true) | bvec4(true, true, false, false) | bvec4(true, true, false, false) | bvec4(false, true, true, true) | bvec4(true, true, true, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_float_to_vec4
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, false, false) | bvec3(false, true, false) ];
+ input float in1 = [ -0.5 | 3.5 | 2.0 | 0.0 | -8.25 | 1.0 | 36.8125 | -20.125 ];
+ output vec4 out0 = [ vec4(1.0, 0.0, 0.0, -0.5) | vec4(0.0, 0.0, 0.0, 3.5) | vec4(0.0, 1.0, 0.0, 2.0) | vec4(1.0, 1.0, 1.0, 0.0) | vec4(0.0, 0.0, 0.0, -8.25) | vec4(0.0, 0.0, 0.0, 1.0) | vec4(1.0, 0.0, 0.0, 36.8125) | vec4(0.0, 1.0, 0.0, -20.125) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_float_to_ivec4
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, false, false) | bvec3(false, true, false) ];
+ input float in1 = [ -0.5 | 3.5 | 2.0 | 0.0 | -8.25 | 1.0 | 36.8125 | -20.125 ];
+ output ivec4 out0 = [ ivec4(1, 0, 0, 0) | ivec4(0, 0, 0, 3) | ivec4(0, 1, 0, 2) | ivec4(1, 1, 1, 0) | ivec4(0, 0, 0, -8) | ivec4(0, 0, 0, 1) | ivec4(1, 0, 0, 36) | ivec4(0, 1, 0, -20) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_float_to_bvec4
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, false, false) | bvec3(false, true, false) ];
+ input float in1 = [ -0.5 | 3.5 | 2.0 | 0.0 | -8.25 | 1.0 | 36.8125 | -20.125 ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, true) | bvec4(true, true, true, false) | bvec4(false, false, false, true) | bvec4(false, false, false, true) | bvec4(true, false, false, true) | bvec4(false, true, false, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_float_to_vec4
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) ];
+ input float in1 = [ -0.5 | 0.0 | 3.5 | -20.125 | 2.0 | -8.25 | 1.0 | 36.8125 ];
+ output vec4 out0 = [ vec4(-32.0, 64.0, -51.0, -0.5) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.0) | vec4(1.0, 1.25, 1.125, 3.5) | vec4(-0.5, -2.25, -4.875, -20.125) | vec4(0.0, 0.5, 0.75, 2.0) | vec4(-0.5, -2.25, -4.875, -8.25) | vec4(0.0, 0.5, 0.75, 1.0) | vec4(1.0, 1.25, 1.125, 36.8125) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_float_to_ivec4
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) ];
+ input float in1 = [ -0.5 | 0.0 | 3.5 | -20.125 | 2.0 | -8.25 | 1.0 | 36.8125 ];
+ output ivec4 out0 = [ ivec4(-32, 64, -51, 0) | ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 3) | ivec4(0, -2, -4, -20) | ivec4(0, 0, 0, 2) | ivec4(0, -2, -4, -8) | ivec4(0, 0, 0, 1) | ivec4(1, 1, 1, 36) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_float_to_bvec4
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) ];
+ input float in1 = [ -0.5 | 0.0 | 3.5 | -20.125 | 2.0 | -8.25 | 1.0 | 36.8125 ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(true, true, true, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, true, true, true) | bvec4(true, true, true, true) | bvec4(false, true, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_ivec2_int_to_vec4
+ version 310 es
+ values
+ {
+ input int in0 = [ -12 | 11 | 8 | 255 | 0 | 1 | -66 | 2 | -192 | 5 ];
+ input ivec2 in1 = [ ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, -2) | ivec2(1, 1) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) | ivec2(0, 0) | ivec2(0, 0) ];
+ input int in2 = [ 1 | 11 | 2 | -66 | -192 | 0 | -12 | 255 | 5 | 8 ];
+ output vec4 out0 = [ vec4(-12.0, 0.0, -2.0, 1.0) | vec4(11.0, -32.0, 64.0, 11.0) | vec4(8.0, 0.0, 0.0, 2.0) | vec4(255.0, 0.0, -2.0, -66.0) | vec4(0.0, 1.0, 1.0, -192.0) | vec4(1.0, 0.0, 0.0, 0.0) | vec4(-66.0, -32.0, 64.0, -12.0) | vec4(2.0, 1.0, 1.0, 255.0) | vec4(-192.0, 0.0, 0.0, 5.0) | vec4(5.0, 0.0, 0.0, 8.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_ivec2_int_to_ivec4
+ version 310 es
+ values
+ {
+ input int in0 = [ -12 | 11 | 8 | 255 | 0 | 1 | -66 | 2 | -192 | 5 ];
+ input ivec2 in1 = [ ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, -2) | ivec2(1, 1) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) | ivec2(0, 0) | ivec2(0, 0) ];
+ input int in2 = [ 1 | 11 | 2 | -66 | -192 | 0 | -12 | 255 | 5 | 8 ];
+ output ivec4 out0 = [ ivec4(-12, 0, -2, 1) | ivec4(11, -32, 64, 11) | ivec4(8, 0, 0, 2) | ivec4(255, 0, -2, -66) | ivec4(0, 1, 1, -192) | ivec4(1, 0, 0, 0) | ivec4(-66, -32, 64, -12) | ivec4(2, 1, 1, 255) | ivec4(-192, 0, 0, 5) | ivec4(5, 0, 0, 8) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_ivec2_int_to_bvec4
+ version 310 es
+ values
+ {
+ input int in0 = [ -12 | 11 | 8 | 255 | 0 | 1 | -66 | 2 | -192 | 5 ];
+ input ivec2 in1 = [ ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, -2) | ivec2(1, 1) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) | ivec2(0, 0) | ivec2(0, 0) ];
+ input int in2 = [ 1 | 11 | 2 | -66 | -192 | 0 | -12 | 255 | 5 | 8 ];
+ output bvec4 out0 = [ bvec4(true, false, true, true) | bvec4(true, true, true, true) | bvec4(true, false, false, true) | bvec4(true, false, true, true) | bvec4(false, true, true, true) | bvec4(true, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, false, false, true) | bvec4(true, false, false, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_ivec2_to_vec4
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false | false | false | true | true | true | false ];
+ input float in1 = [ 1.0 | 0.0 | 2.0 | 3.5 | -20.125 | -0.5 | 36.8125 | -8.25 ];
+ input ivec2 in2 = [ ivec2(1, 1) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, 0) | ivec2(0, -2) | ivec2(0, -2) | ivec2(0, 0) | ivec2(1, 1) ];
+ output vec4 out0 = [ vec4(1.0, 1.0, 1.0, 1.0) | vec4(0.0, 0.0, -32.0, 64.0) | vec4(0.0, 2.0, 0.0, 0.0) | vec4(0.0, 3.5, 0.0, 0.0) | vec4(1.0, -20.125, 0.0, -2.0) | vec4(1.0, -0.5, 0.0, -2.0) | vec4(1.0, 36.8125, 0.0, 0.0) | vec4(0.0, -8.25, 1.0, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_ivec2_to_ivec4
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false | false | false | true | true | true | false ];
+ input float in1 = [ 1.0 | 0.0 | 2.0 | 3.5 | -20.125 | -0.5 | 36.8125 | -8.25 ];
+ input ivec2 in2 = [ ivec2(1, 1) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, 0) | ivec2(0, -2) | ivec2(0, -2) | ivec2(0, 0) | ivec2(1, 1) ];
+ output ivec4 out0 = [ ivec4(1, 1, 1, 1) | ivec4(0, 0, -32, 64) | ivec4(0, 2, 0, 0) | ivec4(0, 3, 0, 0) | ivec4(1, -20, 0, -2) | ivec4(1, 0, 0, -2) | ivec4(1, 36, 0, 0) | ivec4(0, -8, 1, 1) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_ivec2_to_bvec4
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false | false | false | true | true | true | false ];
+ input float in1 = [ 1.0 | 0.0 | 2.0 | 3.5 | -20.125 | -0.5 | 36.8125 | -8.25 ];
+ input ivec2 in2 = [ ivec2(1, 1) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, 0) | ivec2(0, -2) | ivec2(0, -2) | ivec2(0, 0) | ivec2(1, 1) ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(false, false, true, true) | bvec4(false, true, false, false) | bvec4(false, true, false, false) | bvec4(true, true, false, true) | bvec4(true, true, false, true) | bvec4(true, true, false, false) | bvec4(false, true, true, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_uvec3_to_vec4
+ version 310 es
+ values
+ {
+ input float in0 = [ 1.0 | -20.125 | -8.25 | -0.5 | 0.0 | 2.0 | 3.5 | 36.8125 ];
+ input uvec3 in1 = [ uvec3(0, 0, 0) | uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) ];
+ output vec4 out0 = [ vec4(1.0, 0.0, 0.0, 0.0) | vec4(-20.125, 0.0, 0.0, 0.0) | vec4(-8.25, 1.0, 1.0, 1.0) | vec4(-0.5, 0.0, 2.0, 4.0) | vec4(0.0, 0.0, 0.0, 0.0) | vec4(2.0, 1.0, 1.0, 1.0) | vec4(3.5, 0.0, 2.0, 4.0) | vec4(36.8125, 32.0, 64.0, 51.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_uvec3_to_ivec4
+ version 310 es
+ values
+ {
+ input float in0 = [ 1.0 | -20.125 | -8.25 | -0.5 | 0.0 | 2.0 | 3.5 | 36.8125 ];
+ input uvec3 in1 = [ uvec3(0, 0, 0) | uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) ];
+ output ivec4 out0 = [ ivec4(1, 0, 0, 0) | ivec4(-20, 0, 0, 0) | ivec4(-8, 1, 1, 1) | ivec4(0, 0, 2, 4) | ivec4(0, 0, 0, 0) | ivec4(2, 1, 1, 1) | ivec4(3, 0, 2, 4) | ivec4(36, 32, 64, 51) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_uvec3_to_bvec4
+ version 310 es
+ values
+ {
+ input float in0 = [ 1.0 | -20.125 | -8.25 | -0.5 | 0.0 | 2.0 | 3.5 | 36.8125 ];
+ input uvec3 in1 = [ uvec3(0, 0, 0) | uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(0, 0, 0) | uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(32, 64, 51) ];
+ output bvec4 out0 = [ bvec4(true, false, false, false) | bvec4(true, false, false, false) | bvec4(true, true, true, true) | bvec4(true, false, true, true) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, false, true, true) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_uvec2_bool_to_vec4
+ version 310 es
+ values
+ {
+ input int in0 = [ 1 | -192 | -66 | -12 | 0 | 2 | 11 | 8 | 255 | 5 ];
+ input uvec2 in1 = [ uvec2(0, 2) | uvec2(1, 1) | uvec2(0, 0) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) | uvec2(32, 64) | uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 0) ];
+ input bool in2 = [ false | false | true | true | true | true | true | false | false | false ];
+ output vec4 out0 = [ vec4(1.0, 0.0, 2.0, 0.0) | vec4(-192.0, 1.0, 1.0, 0.0) | vec4(-66.0, 0.0, 0.0, 1.0) | vec4(-12.0, 0.0, 2.0, 1.0) | vec4(0.0, 32.0, 64.0, 1.0) | vec4(2.0, 0.0, 0.0, 1.0) | vec4(11.0, 32.0, 64.0, 1.0) | vec4(8.0, 0.0, 0.0, 0.0) | vec4(255.0, 1.0, 1.0, 0.0) | vec4(5.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_uvec2_bool_to_ivec4
+ version 310 es
+ values
+ {
+ input int in0 = [ 1 | -192 | -66 | -12 | 0 | 2 | 11 | 8 | 255 | 5 ];
+ input uvec2 in1 = [ uvec2(0, 2) | uvec2(1, 1) | uvec2(0, 0) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) | uvec2(32, 64) | uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 0) ];
+ input bool in2 = [ false | false | true | true | true | true | true | false | false | false ];
+ output ivec4 out0 = [ ivec4(1, 0, 2, 0) | ivec4(-192, 1, 1, 0) | ivec4(-66, 0, 0, 1) | ivec4(-12, 0, 2, 1) | ivec4(0, 32, 64, 1) | ivec4(2, 0, 0, 1) | ivec4(11, 32, 64, 1) | ivec4(8, 0, 0, 0) | ivec4(255, 1, 1, 0) | ivec4(5, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_uvec2_bool_to_bvec4
+ version 310 es
+ values
+ {
+ input int in0 = [ 1 | -192 | -66 | -12 | 0 | 2 | 11 | 8 | 255 | 5 ];
+ input uvec2 in1 = [ uvec2(0, 2) | uvec2(1, 1) | uvec2(0, 0) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) | uvec2(32, 64) | uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 0) ];
+ input bool in2 = [ false | false | true | true | true | true | true | false | false | false ];
+ output bvec4 out0 = [ bvec4(true, false, true, false) | bvec4(true, true, true, false) | bvec4(true, false, false, true) | bvec4(true, false, true, true) | bvec4(false, true, true, true) | bvec4(true, false, false, true) | bvec4(true, true, true, true) | bvec4(true, false, false, false) | bvec4(true, true, true, false) | bvec4(true, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_vec2_to_uvec4
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(32.0, 64.0) | vec2(0.75, 0.0322580645161) | vec2(0.0, 0.5) | vec2(0.5, 2.25) | vec2(1.0, 1.25) ];
+ input vec2 in1 = [ vec2(0.5, 2.25) | vec2(1.0, 1.25) | vec2(32.0, 64.0) | vec2(0.0, 0.5) | vec2(0.75, 0.0322580645161) ];
+ output uvec4 out0 = [ uvec4(32, 64, 0, 2) | uvec4(0, 0, 1, 1) | uvec4(0, 0, 32, 64) | uvec4(0, 2, 0, 0) | uvec4(1, 1, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_bvec2_to_uvec4
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) | bvec2(false, false) ];
+ input bvec2 in1 = [ bvec2(true, true) | bvec2(false, false) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) ];
+ output uvec4 out0 = [ uvec4(1, 0, 1, 1) | uvec4(0, 1, 0, 0) | uvec4(1, 1, 1, 0) | uvec4(0, 0, 0, 1) | uvec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_float_to_uvec4
+ version 310 es
+ values
+ {
+ input float in0 = [ 2.0 | 36.8125 | 0.0 | 20.125 | 1.0 | 0.5 | 8.25 | 3.5 ];
+ input float in1 = [ 1.0 | 8.25 | 2.0 | 20.125 | 36.8125 | 0.0 | 0.5 | 3.5 ];
+ input float in2 = [ 0.0 | 8.25 | 2.0 | 1.0 | 36.8125 | 20.125 | 0.5 | 3.5 ];
+ input float in3 = [ 1.0 | 8.25 | 0.0 | 2.0 | 20.125 | 3.5 | 0.5 | 36.8125 ];
+ output uvec4 out0 = [ uvec4(2, 1, 0, 1) | uvec4(36, 8, 8, 8) | uvec4(0, 2, 2, 0) | uvec4(20, 20, 1, 2) | uvec4(1, 36, 36, 20) | uvec4(0, 0, 20, 3) | uvec4(8, 0, 0, 0) | uvec4(3, 3, 3, 36) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_int_to_uvec4
+ version 310 es
+ values
+ {
+ input int in0 = [ 192 | 2 | 12 | 11 | 0 | 8 | 5 | 66 | 1 | 255 ];
+ input int in1 = [ 66 | 12 | 5 | 1 | 0 | 192 | 8 | 255 | 11 | 2 ];
+ input int in2 = [ 192 | 5 | 1 | 66 | 255 | 11 | 8 | 12 | 2 | 0 ];
+ input int in3 = [ 255 | 5 | 11 | 12 | 2 | 1 | 66 | 0 | 8 | 192 ];
+ output uvec4 out0 = [ uvec4(192, 66, 192, 255) | uvec4(2, 12, 5, 5) | uvec4(12, 5, 1, 11) | uvec4(11, 1, 66, 12) | uvec4(0, 0, 255, 2) | uvec4(8, 192, 11, 1) | uvec4(5, 8, 8, 66) | uvec4(66, 255, 12, 0) | uvec4(1, 11, 2, 8) | uvec4(255, 2, 0, 192) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint_uint_uint_to_uvec4
+ version 310 es
+ values
+ {
+ input uint in0 = [ 255 | 8 | 3 | 193 | 45 | 2 | 0 | 12 | 9 | 10 ];
+ input uint in1 = [ 255 | 45 | 0 | 12 | 2 | 10 | 8 | 9 | 193 | 3 ];
+ input uint in2 = [ 3 | 0 | 2 | 9 | 12 | 10 | 255 | 45 | 193 | 8 ];
+ input uint in3 = [ 2 | 255 | 10 | 193 | 8 | 12 | 3 | 9 | 0 | 45 ];
+ output uvec4 out0 = [ uvec4(255, 255, 3, 2) | uvec4(8, 45, 0, 255) | uvec4(3, 0, 2, 10) | uvec4(193, 12, 9, 193) | uvec4(45, 2, 12, 8) | uvec4(2, 10, 10, 12) | uvec4(0, 8, 255, 3) | uvec4(12, 9, 45, 9) | uvec4(9, 193, 193, 0) | uvec4(10, 3, 8, 45) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_bool_to_uvec4
+ version 310 es
+ values
+ {
+ input bool in0 = [ false | true ];
+ input bool in1 = [ false | true ];
+ input bool in2 = [ true | false ];
+ input bool in3 = [ true | false ];
+ output uvec4 out0 = [ uvec4(0, 0, 1, 1) | uvec4(1, 1, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_bool_to_uvec4
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false | false | true | false | true | true | true | false | false ];
+ input float in1 = [ 20.125 | 0.0 | 1.0 | 3.5 | 1.0 | 0.0 | 0.5 | 8.25 | 2.0 | 36.8125 ];
+ input int in2 = [ 66 | 192 | 1 | 2 | 5 | 11 | 8 | 12 | 255 | 0 ];
+ input bool in3 = [ true | true | true | true | false | true | false | false | false | false ];
+ output uvec4 out0 = [ uvec4(1, 20, 66, 1) | uvec4(0, 0, 192, 1) | uvec4(0, 1, 1, 1) | uvec4(1, 3, 2, 1) | uvec4(0, 1, 5, 0) | uvec4(1, 0, 11, 1) | uvec4(1, 0, 8, 0) | uvec4(1, 8, 12, 0) | uvec4(0, 2, 255, 0) | uvec4(0, 36, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_to_uvec4
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.5, 2.25) | vec2(1.0, 1.25) | vec2(32.0, 64.0) | vec2(0.75, 0.0322580645161) | vec2(0.0, 0.5) ];
+ input ivec2 in1 = [ ivec2(1, 1) | ivec2(0, 2) | ivec2(32, 64) | ivec2(0, 0) | ivec2(0, 0) ];
+ output uvec4 out0 = [ uvec4(0, 2, 1, 1) | uvec4(1, 1, 0, 2) | uvec4(32, 64, 32, 64) | uvec4(0, 0, 0, 0) | uvec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bvec2_to_uvec4
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(32.0, 64.0) | vec2(0.75, 0.0322580645161) | vec2(0.5, 2.25) | vec2(0.0, 0.5) | vec2(1.0, 1.25) ];
+ input bvec2 in1 = [ bvec2(false, false) | bvec2(false, false) | bvec2(true, false) | bvec2(false, true) | bvec2(true, true) ];
+ output uvec4 out0 = [ uvec4(32, 64, 0, 0) | uvec4(0, 0, 0, 0) | uvec4(0, 2, 1, 0) | uvec4(0, 0, 0, 1) | uvec4(1, 1, 1, 1) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_float_to_uvec4
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(true, true, true) | bvec3(false, true, false) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, false, false) | bvec3(false, false, false) ];
+ input float in1 = [ 2.0 | 0.0 | 36.8125 | 0.5 | 1.0 | 8.25 | 3.5 | 20.125 ];
+ output uvec4 out0 = [ uvec4(1, 0, 0, 2) | uvec4(1, 1, 1, 0) | uvec4(0, 1, 0, 36) | uvec4(0, 0, 0, 0) | uvec4(0, 0, 0, 1) | uvec4(0, 1, 0, 8) | uvec4(1, 0, 0, 3) | uvec4(0, 0, 0, 20) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_float_to_uvec4
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.5, 2.25, 4.875) | vec3(1.0, 1.25, 1.125) | vec3(0.0, 0.5, 0.75) | vec3(0.5, 2.25, 4.875) | vec3(32.0, 64.0, 51.0) | vec3(1.0, 1.25, 1.125) | vec3(0.75, 0.0322580645161, 0.0526315789474) | vec3(0.0, 0.5, 0.75) ];
+ input float in1 = [ 8.25 | 1.0 | 0.0 | 36.8125 | 2.0 | 0.5 | 20.125 | 3.5 ];
+ output uvec4 out0 = [ uvec4(0, 2, 4, 8) | uvec4(1, 1, 1, 1) | uvec4(0, 0, 0, 0) | uvec4(0, 2, 4, 36) | uvec4(32, 64, 51, 2) | uvec4(1, 1, 1, 0) | uvec4(0, 0, 0, 20) | uvec4(0, 0, 0, 3) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_ivec2_int_to_uvec4
+ version 310 es
+ values
+ {
+ input int in0 = [ 8 | 1 | 11 | 192 | 255 | 12 | 66 | 2 | 0 | 5 ];
+ input ivec2 in1 = [ ivec2(1, 1) | ivec2(0, 0) | ivec2(1, 1) | ivec2(32, 64) | ivec2(0, 2) | ivec2(0, 2) | ivec2(0, 0) | ivec2(0, 0) | ivec2(32, 64) | ivec2(0, 0) ];
+ input int in2 = [ 2 | 192 | 12 | 0 | 8 | 1 | 66 | 255 | 11 | 5 ];
+ output uvec4 out0 = [ uvec4(8, 1, 1, 2) | uvec4(1, 0, 0, 192) | uvec4(11, 1, 1, 12) | uvec4(192, 32, 64, 0) | uvec4(255, 0, 2, 8) | uvec4(12, 0, 2, 1) | uvec4(66, 0, 0, 66) | uvec4(2, 0, 0, 255) | uvec4(0, 32, 64, 11) | uvec4(5, 0, 0, 5) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_ivec2_to_uvec4
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | true | false | false | true | false | false | true ];
+ input float in1 = [ 8.25 | 0.5 | 2.0 | 20.125 | 0.0 | 36.8125 | 3.5 | 1.0 ];
+ input ivec2 in2 = [ ivec2(32, 64) | ivec2(1, 1) | ivec2(0, 2) | ivec2(0, 0) | ivec2(0, 0) | ivec2(0, 2) | ivec2(1, 1) | ivec2(0, 0) ];
+ output uvec4 out0 = [ uvec4(1, 8, 32, 64) | uvec4(1, 0, 1, 1) | uvec4(0, 2, 0, 2) | uvec4(0, 20, 0, 0) | uvec4(1, 0, 0, 0) | uvec4(0, 36, 0, 2) | uvec4(0, 3, 1, 1) | uvec4(1, 1, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_uvec3_to_uvec4
+ version 310 es
+ values
+ {
+ input float in0 = [ 8.25 | 20.125 | 1.0 | 0.5 | 3.5 | 2.0 | 36.8125 | 0.0 ];
+ input uvec3 in1 = [ uvec3(0, 0, 0) | uvec3(0, 0, 0) | uvec3(0, 2, 4) | uvec3(32, 64, 51) | uvec3(0, 2, 4) | uvec3(1, 1, 1) | uvec3(1, 1, 1) | uvec3(0, 0, 0) ];
+ output uvec4 out0 = [ uvec4(8, 0, 0, 0) | uvec4(20, 0, 0, 0) | uvec4(1, 0, 2, 4) | uvec4(0, 32, 64, 51) | uvec4(3, 0, 2, 4) | uvec4(2, 1, 1, 1) | uvec4(36, 1, 1, 1) | uvec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_uvec2_bool_to_uvec4
+ version 310 es
+ values
+ {
+ input int in0 = [ 2 | 1 | 11 | 66 | 192 | 12 | 8 | 255 | 0 | 5 ];
+ input uvec2 in1 = [ uvec2(1, 1) | uvec2(0, 0) | uvec2(0, 0) | uvec2(0, 2) | uvec2(0, 0) | uvec2(0, 2) | uvec2(32, 64) | uvec2(1, 1) | uvec2(32, 64) | uvec2(0, 0) ];
+ input bool in2 = [ true | false | false | false | false | true | true | true | false | true ];
+ output uvec4 out0 = [ uvec4(2, 1, 1, 1) | uvec4(1, 0, 0, 0) | uvec4(11, 0, 0, 0) | uvec4(66, 0, 2, 0) | uvec4(192, 0, 0, 0) | uvec4(12, 0, 2, 1) | uvec4(8, 32, 64, 1) | uvec4(255, 1, 1, 1) | uvec4(0, 32, 64, 0) | uvec4(5, 0, 0, 1) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_to_vec3
+ version 310 es
+ values
+ {
+ input float in0 = [ -0.5 | 1.0 | 3.5 | -8.25 | 36.8125 | 0.0 | 2.0 | -20.125 ];
+ input float in1 = [ 2.0 | -20.125 | 3.5 | 36.8125 | -8.25 | 1.0 | -0.5 | 0.0 ];
+ input float in2 = [ 1.0 | 3.5 | 2.0 | -8.25 | -20.125 | -0.5 | 36.8125 | 0.0 ];
+ output vec3 out0 = [ vec3(-0.5, 2.0, 1.0) | vec3(1.0, -20.125, 3.5) | vec3(3.5, 3.5, 2.0) | vec3(-8.25, 36.8125, -8.25) | vec3(36.8125, -8.25, -20.125) | vec3(0.0, 1.0, -0.5) | vec3(2.0, -0.5, 36.8125) | vec3(-20.125, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_to_ivec3
+ version 310 es
+ values
+ {
+ input float in0 = [ -0.5 | 1.0 | 3.5 | -8.25 | 36.8125 | 0.0 | 2.0 | -20.125 ];
+ input float in1 = [ 2.0 | -20.125 | 3.5 | 36.8125 | -8.25 | 1.0 | -0.5 | 0.0 ];
+ input float in2 = [ 1.0 | 3.5 | 2.0 | -8.25 | -20.125 | -0.5 | 36.8125 | 0.0 ];
+ output ivec3 out0 = [ ivec3(0, 2, 1) | ivec3(1, -20, 3) | ivec3(3, 3, 2) | ivec3(-8, 36, -8) | ivec3(36, -8, -20) | ivec3(0, 1, 0) | ivec3(2, 0, 36) | ivec3(-20, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_to_bvec3
+ version 310 es
+ values
+ {
+ input float in0 = [ -0.5 | 1.0 | 3.5 | -8.25 | 36.8125 | 0.0 | 2.0 | -20.125 ];
+ input float in1 = [ 2.0 | -20.125 | 3.5 | 36.8125 | -8.25 | 1.0 | -0.5 | 0.0 ];
+ input float in2 = [ 1.0 | 3.5 | 2.0 | -8.25 | -20.125 | -0.5 | 36.8125 | 0.0 ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(false, true, true) | bvec3(true, true, true) | bvec3(true, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_to_vec3
+ version 310 es
+ values
+ {
+ input int in0 = [ -192 | 5 | -12 | 0 | 11 | 8 | 1 | -66 | 255 | 2 ];
+ input int in1 = [ 5 | 1 | 8 | 0 | 2 | -192 | -12 | 255 | -66 | 11 ];
+ input int in2 = [ -192 | 1 | 2 | 5 | -12 | 8 | 11 | 0 | 255 | -66 ];
+ output vec3 out0 = [ vec3(-192.0, 5.0, -192.0) | vec3(5.0, 1.0, 1.0) | vec3(-12.0, 8.0, 2.0) | vec3(0.0, 0.0, 5.0) | vec3(11.0, 2.0, -12.0) | vec3(8.0, -192.0, 8.0) | vec3(1.0, -12.0, 11.0) | vec3(-66.0, 255.0, 0.0) | vec3(255.0, -66.0, 255.0) | vec3(2.0, 11.0, -66.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_to_ivec3
+ version 310 es
+ values
+ {
+ input int in0 = [ -192 | 5 | -12 | 0 | 11 | 8 | 1 | -66 | 255 | 2 ];
+ input int in1 = [ 5 | 1 | 8 | 0 | 2 | -192 | -12 | 255 | -66 | 11 ];
+ input int in2 = [ -192 | 1 | 2 | 5 | -12 | 8 | 11 | 0 | 255 | -66 ];
+ output ivec3 out0 = [ ivec3(-192, 5, -192) | ivec3(5, 1, 1) | ivec3(-12, 8, 2) | ivec3(0, 0, 5) | ivec3(11, 2, -12) | ivec3(8, -192, 8) | ivec3(1, -12, 11) | ivec3(-66, 255, 0) | ivec3(255, -66, 255) | ivec3(2, 11, -66) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_to_bvec3
+ version 310 es
+ values
+ {
+ input int in0 = [ -192 | 5 | -12 | 0 | 11 | 8 | 1 | -66 | 255 | 2 ];
+ input int in1 = [ 5 | 1 | 8 | 0 | 2 | -192 | -12 | 255 | -66 | 11 ];
+ input int in2 = [ -192 | 1 | 2 | 5 | -12 | 8 | 11 | 0 | 255 | -66 ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(false, false, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, false) | bvec3(true, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint_uint_to_vec3
+ version 310 es
+ values
+ {
+ input uint in0 = [ 8 | 45 | 2 | 3 | 255 | 193 | 12 | 0 | 9 | 10 ];
+ input uint in1 = [ 193 | 2 | 9 | 8 | 0 | 255 | 45 | 3 | 10 | 12 ];
+ input uint in2 = [ 12 | 2 | 193 | 255 | 8 | 10 | 45 | 0 | 3 | 9 ];
+ output vec3 out0 = [ vec3(8.0, 193.0, 12.0) | vec3(45.0, 2.0, 2.0) | vec3(2.0, 9.0, 193.0) | vec3(3.0, 8.0, 255.0) | vec3(255.0, 0.0, 8.0) | vec3(193.0, 255.0, 10.0) | vec3(12.0, 45.0, 45.0) | vec3(0.0, 3.0, 0.0) | vec3(9.0, 10.0, 3.0) | vec3(10.0, 12.0, 9.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint_uint_to_ivec3
+ version 310 es
+ values
+ {
+ input uint in0 = [ 8 | 45 | 2 | 3 | 255 | 193 | 12 | 0 | 9 | 10 ];
+ input uint in1 = [ 193 | 2 | 9 | 8 | 0 | 255 | 45 | 3 | 10 | 12 ];
+ input uint in2 = [ 12 | 2 | 193 | 255 | 8 | 10 | 45 | 0 | 3 | 9 ];
+ output ivec3 out0 = [ ivec3(8, 193, 12) | ivec3(45, 2, 2) | ivec3(2, 9, 193) | ivec3(3, 8, 255) | ivec3(255, 0, 8) | ivec3(193, 255, 10) | ivec3(12, 45, 45) | ivec3(0, 3, 0) | ivec3(9, 10, 3) | ivec3(10, 12, 9) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint_uint_to_bvec3
+ version 310 es
+ values
+ {
+ input uint in0 = [ 8 | 45 | 2 | 3 | 255 | 193 | 12 | 0 | 9 | 10 ];
+ input uint in1 = [ 193 | 2 | 9 | 8 | 0 | 255 | 45 | 3 | 10 | 12 ];
+ input uint in2 = [ 12 | 2 | 193 | 255 | 8 | 10 | 45 | 0 | 3 | 9 ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, false, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_to_vec3
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ true | false ];
+ input bool in2 = [ true | false ];
+ output vec3 out0 = [ vec3(1.0, 1.0, 1.0) | vec3(0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_to_ivec3
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ true | false ];
+ input bool in2 = [ true | false ];
+ output ivec3 out0 = [ ivec3(1, 1, 1) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_to_bvec3
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ true | false ];
+ input bool in2 = [ true | false ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_to_vec3
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | true | false | false | true | false | true | false | false | true ];
+ input float in1 = [ 0.0 | 36.8125 | 0.0 | -8.25 | 1.0 | 3.5 | 1.0 | -0.5 | -20.125 | 2.0 ];
+ input int in2 = [ 8 | -192 | -66 | 2 | 1 | -12 | 11 | 255 | 5 | 0 ];
+ output vec3 out0 = [ vec3(1.0, 0.0, 8.0) | vec3(1.0, 36.8125, -192.0) | vec3(0.0, 0.0, -66.0) | vec3(0.0, -8.25, 2.0) | vec3(1.0, 1.0, 1.0) | vec3(0.0, 3.5, -12.0) | vec3(1.0, 1.0, 11.0) | vec3(0.0, -0.5, 255.0) | vec3(0.0, -20.125, 5.0) | vec3(1.0, 2.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_to_ivec3
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | true | false | false | true | false | true | false | false | true ];
+ input float in1 = [ 0.0 | 36.8125 | 0.0 | -8.25 | 1.0 | 3.5 | 1.0 | -0.5 | -20.125 | 2.0 ];
+ input int in2 = [ 8 | -192 | -66 | 2 | 1 | -12 | 11 | 255 | 5 | 0 ];
+ output ivec3 out0 = [ ivec3(1, 0, 8) | ivec3(1, 36, -192) | ivec3(0, 0, -66) | ivec3(0, -8, 2) | ivec3(1, 1, 1) | ivec3(0, 3, -12) | ivec3(1, 1, 11) | ivec3(0, 0, 255) | ivec3(0, -20, 5) | ivec3(1, 2, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_to_bvec3
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | true | false | false | true | false | true | false | false | true ];
+ input float in1 = [ 0.0 | 36.8125 | 0.0 | -8.25 | 1.0 | 3.5 | 1.0 | -0.5 | -20.125 | 2.0 ];
+ input int in2 = [ 8 | -192 | -66 | 2 | 1 | -12 | 11 | 255 | 5 | 0 ];
+ output bvec3 out0 = [ bvec3(true, false, true) | bvec3(true, true, true) | bvec3(false, false, true) | bvec3(false, true, true) | bvec3(true, true, true) | bvec3(false, true, true) | bvec3(true, true, true) | bvec3(false, true, true) | bvec3(false, true, true) | bvec3(true, true, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bool_to_vec3
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(0.0, 0.5) ];
+ input bool in1 = [ false | true | true | true | false ];
+ output vec3 out0 = [ vec3(1.0, 1.25, 0.0) | vec3(-0.75, -0.0322580645161, 1.0) | vec3(-32.0, 64.0, 1.0) | vec3(-0.5, -2.25, 1.0) | vec3(0.0, 0.5, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bool_to_ivec3
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(0.0, 0.5) ];
+ input bool in1 = [ false | true | true | true | false ];
+ output ivec3 out0 = [ ivec3(1, 1, 0) | ivec3(0, 0, 1) | ivec3(-32, 64, 1) | ivec3(0, -2, 1) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bool_to_bvec3
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(0.0, 0.5) ];
+ input bool in1 = [ false | true | true | true | false ];
+ output bvec3 out0 = [ bvec3(true, true, false) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(false, true, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_float_to_vec3
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, true) | bvec2(false, true) | bvec2(true, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ input float in1 = [ -20.125 | 2.0 | 36.8125 | 1.0 | 3.5 | 0.0 | -8.25 | -0.5 ];
+ output vec3 out0 = [ vec3(1.0, 0.0, -20.125) | vec3(0.0, 1.0, 2.0) | vec3(0.0, 1.0, 36.8125) | vec3(1.0, 0.0, 1.0) | vec3(0.0, 0.0, 3.5) | vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, -8.25) | vec3(0.0, 0.0, -0.5) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_float_to_ivec3
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, true) | bvec2(false, true) | bvec2(true, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ input float in1 = [ -20.125 | 2.0 | 36.8125 | 1.0 | 3.5 | 0.0 | -8.25 | -0.5 ];
+ output ivec3 out0 = [ ivec3(1, 0, -20) | ivec3(0, 1, 2) | ivec3(0, 1, 36) | ivec3(1, 0, 1) | ivec3(0, 0, 3) | ivec3(0, 0, 0) | ivec3(1, 1, -8) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_float_to_bvec3
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, true) | bvec2(false, true) | bvec2(true, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ input float in1 = [ -20.125 | 2.0 | 36.8125 | 1.0 | 3.5 | 0.0 | -8.25 | -0.5 ];
+ output bvec3 out0 = [ bvec3(true, false, true) | bvec3(false, true, true) | bvec3(false, true, true) | bvec3(true, false, true) | bvec3(false, false, true) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_int_to_vec3
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, true) | bvec2(false, false) | bvec2(false, false) | bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) ];
+ input int in1 = [ 1 | -66 | 255 | 8 | -192 | 2 | 5 | 11 | -12 | 0 ];
+ output vec3 out0 = [ vec3(1.0, 1.0, 1.0) | vec3(0.0, 0.0, -66.0) | vec3(0.0, 0.0, 255.0) | vec3(1.0, 0.0, 8.0) | vec3(0.0, 0.0, -192.0) | vec3(0.0, 1.0, 2.0) | vec3(1.0, 0.0, 5.0) | vec3(0.0, 1.0, 11.0) | vec3(0.0, 0.0, -12.0) | vec3(1.0, 1.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_int_to_ivec3
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, true) | bvec2(false, false) | bvec2(false, false) | bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) ];
+ input int in1 = [ 1 | -66 | 255 | 8 | -192 | 2 | 5 | 11 | -12 | 0 ];
+ output ivec3 out0 = [ ivec3(1, 1, 1) | ivec3(0, 0, -66) | ivec3(0, 0, 255) | ivec3(1, 0, 8) | ivec3(0, 0, -192) | ivec3(0, 1, 2) | ivec3(1, 0, 5) | ivec3(0, 1, 11) | ivec3(0, 0, -12) | ivec3(1, 1, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_int_to_bvec3
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, true) | bvec2(false, false) | bvec2(false, false) | bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) ];
+ input int in1 = [ 1 | -66 | 255 | 8 | -192 | 2 | 5 | 11 | -12 | 0 ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(false, false, true) | bvec3(false, false, true) | bvec3(true, false, true) | bvec3(false, false, true) | bvec3(false, true, true) | bvec3(true, false, true) | bvec3(false, true, true) | bvec3(false, false, true) | bvec3(true, true, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_ivec2_to_vec3
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | true | false | false | true ];
+ input ivec2 in1 = [ ivec2(0, -2) | ivec2(0, 0) | ivec2(0, 0) | ivec2(1, 1) | ivec2(-32, 64) ];
+ output vec3 out0 = [ vec3(1.0, 0.0, -2.0) | vec3(1.0, 0.0, 0.0) | vec3(0.0, 0.0, 0.0) | vec3(0.0, 1.0, 1.0) | vec3(1.0, -32.0, 64.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_ivec2_to_ivec3
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | true | false | false | true ];
+ input ivec2 in1 = [ ivec2(0, -2) | ivec2(0, 0) | ivec2(0, 0) | ivec2(1, 1) | ivec2(-32, 64) ];
+ output ivec3 out0 = [ ivec3(1, 0, -2) | ivec3(1, 0, 0) | ivec3(0, 0, 0) | ivec3(0, 1, 1) | ivec3(1, -32, 64) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_ivec2_to_bvec3
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | true | false | false | true ];
+ input ivec2 in1 = [ ivec2(0, -2) | ivec2(0, 0) | ivec2(0, 0) | ivec2(1, 1) | ivec2(-32, 64) ];
+ output bvec3 out0 = [ bvec3(true, false, true) | bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_uvec2_to_vec3
+ version 310 es
+ values
+ {
+ input float in0 = [ -20.125 | 36.8125 | -8.25 | 2.0 | -0.5 | 0.0 | 3.5 | 1.0 ];
+ input uvec2 in1 = [ uvec2(0, 0) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) | uvec2(0, 2) | uvec2(0, 0) | uvec2(1, 1) | uvec2(1, 1) ];
+ output vec3 out0 = [ vec3(-20.125, 0.0, 0.0) | vec3(36.8125, 0.0, 2.0) | vec3(-8.25, 32.0, 64.0) | vec3(2.0, 0.0, 0.0) | vec3(-0.5, 0.0, 2.0) | vec3(0.0, 0.0, 0.0) | vec3(3.5, 1.0, 1.0) | vec3(1.0, 1.0, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_uvec2_to_ivec3
+ version 310 es
+ values
+ {
+ input float in0 = [ -20.125 | 36.8125 | -8.25 | 2.0 | -0.5 | 0.0 | 3.5 | 1.0 ];
+ input uvec2 in1 = [ uvec2(0, 0) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) | uvec2(0, 2) | uvec2(0, 0) | uvec2(1, 1) | uvec2(1, 1) ];
+ output ivec3 out0 = [ ivec3(-20, 0, 0) | ivec3(36, 0, 2) | ivec3(-8, 32, 64) | ivec3(2, 0, 0) | ivec3(0, 0, 2) | ivec3(0, 0, 0) | ivec3(3, 1, 1) | ivec3(1, 1, 1) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_uvec2_to_bvec3
+ version 310 es
+ values
+ {
+ input float in0 = [ -20.125 | 36.8125 | -8.25 | 2.0 | -0.5 | 0.0 | 3.5 | 1.0 ];
+ input uvec2 in1 = [ uvec2(0, 0) | uvec2(0, 2) | uvec2(32, 64) | uvec2(0, 0) | uvec2(0, 2) | uvec2(0, 0) | uvec2(1, 1) | uvec2(1, 1) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(true, false, true) | bvec3(true, true, true) | bvec3(true, false, false) | bvec3(true, false, true) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(true, true, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_to_uvec3
+ version 310 es
+ values
+ {
+ input float in0 = [ 8.25 | 20.125 | 2.0 | 3.5 | 0.5 | 36.8125 | 1.0 | 0.0 ];
+ input float in1 = [ 1.0 | 0.0 | 3.5 | 36.8125 | 8.25 | 2.0 | 0.5 | 20.125 ];
+ input float in2 = [ 20.125 | 0.5 | 8.25 | 36.8125 | 1.0 | 0.0 | 3.5 | 2.0 ];
+ output uvec3 out0 = [ uvec3(8, 1, 20) | uvec3(20, 0, 0) | uvec3(2, 3, 8) | uvec3(3, 36, 36) | uvec3(0, 8, 1) | uvec3(36, 2, 0) | uvec3(1, 0, 3) | uvec3(0, 20, 2) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_to_uvec3
+ version 310 es
+ values
+ {
+ input int in0 = [ 1 | 255 | 192 | 2 | 5 | 12 | 0 | 11 | 8 | 66 ];
+ input int in1 = [ 192 | 66 | 5 | 8 | 11 | 1 | 0 | 255 | 12 | 2 ];
+ input int in2 = [ 192 | 5 | 1 | 11 | 66 | 8 | 12 | 0 | 2 | 255 ];
+ output uvec3 out0 = [ uvec3(1, 192, 192) | uvec3(255, 66, 5) | uvec3(192, 5, 1) | uvec3(2, 8, 11) | uvec3(5, 11, 66) | uvec3(12, 1, 8) | uvec3(0, 0, 12) | uvec3(11, 255, 0) | uvec3(8, 12, 2) | uvec3(66, 2, 255) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint_uint_to_uvec3
+ version 310 es
+ values
+ {
+ input uint in0 = [ 193 | 9 | 45 | 255 | 2 | 0 | 10 | 8 | 12 | 3 ];
+ input uint in1 = [ 3 | 45 | 2 | 9 | 10 | 0 | 8 | 12 | 255 | 193 ];
+ input uint in2 = [ 2 | 3 | 9 | 10 | 255 | 8 | 12 | 0 | 193 | 45 ];
+ output uvec3 out0 = [ uvec3(193, 3, 2) | uvec3(9, 45, 3) | uvec3(45, 2, 9) | uvec3(255, 9, 10) | uvec3(2, 10, 255) | uvec3(0, 0, 8) | uvec3(10, 8, 12) | uvec3(8, 12, 0) | uvec3(12, 255, 193) | uvec3(3, 193, 45) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_to_uvec3
+ version 310 es
+ values
+ {
+ input bool in0 = [ false | true ];
+ input bool in1 = [ false | true ];
+ input bool in2 = [ true | false ];
+ output uvec3 out0 = [ uvec3(0, 0, 1) | uvec3(1, 1, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_to_uvec3
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false | true | false | false | true | false | true | true | false ];
+ input float in1 = [ 36.8125 | 20.125 | 1.0 | 0.0 | 3.5 | 1.0 | 2.0 | 0.5 | 0.0 | 8.25 ];
+ input int in2 = [ 1 | 0 | 8 | 66 | 2 | 11 | 192 | 5 | 12 | 255 ];
+ output uvec3 out0 = [ uvec3(1, 36, 1) | uvec3(0, 20, 0) | uvec3(1, 1, 8) | uvec3(0, 0, 66) | uvec3(0, 3, 2) | uvec3(1, 1, 11) | uvec3(0, 2, 192) | uvec3(1, 0, 5) | uvec3(1, 0, 12) | uvec3(0, 8, 255) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bool_to_uvec3
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(32.0, 64.0) | vec2(0.5, 2.25) | vec2(1.0, 1.25) | vec2(0.75, 0.0322580645161) ];
+ input bool in1 = [ false | false | true | true | true ];
+ output uvec3 out0 = [ uvec3(0, 0, 0) | uvec3(32, 64, 0) | uvec3(0, 2, 1) | uvec3(1, 1, 1) | uvec3(0, 0, 1) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_float_to_uvec3
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, true) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(false, false) ];
+ input float in1 = [ 8.25 | 36.8125 | 20.125 | 2.0 | 0.0 | 1.0 | 0.5 | 3.5 ];
+ output uvec3 out0 = [ uvec3(1, 1, 8) | uvec3(1, 0, 36) | uvec3(0, 1, 20) | uvec3(0, 0, 2) | uvec3(1, 0, 0) | uvec3(0, 1, 1) | uvec3(0, 0, 0) | uvec3(0, 0, 3) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_int_to_uvec3
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, true) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) | bvec2(true, false) | bvec2(false, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, false) ];
+ input int in1 = [ 255 | 1 | 2 | 5 | 0 | 11 | 192 | 12 | 8 | 66 ];
+ output uvec3 out0 = [ uvec3(1, 1, 255) | uvec3(0, 1, 1) | uvec3(0, 0, 2) | uvec3(1, 1, 5) | uvec3(0, 0, 0) | uvec3(1, 0, 11) | uvec3(0, 0, 192) | uvec3(0, 0, 12) | uvec3(0, 1, 8) | uvec3(1, 0, 66) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_ivec2_to_uvec3
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false | true | true | false ];
+ input ivec2 in1 = [ ivec2(0, 0) | ivec2(0, 2) | ivec2(1, 1) | ivec2(0, 0) | ivec2(32, 64) ];
+ output uvec3 out0 = [ uvec3(1, 0, 0) | uvec3(0, 0, 2) | uvec3(1, 1, 1) | uvec3(1, 0, 0) | uvec3(0, 32, 64) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_uvec2_to_uvec3
+ version 310 es
+ values
+ {
+ input float in0 = [ 2.0 | 8.25 | 20.125 | 3.5 | 0.0 | 0.5 | 36.8125 | 1.0 ];
+ input uvec2 in1 = [ uvec2(0, 2) | uvec2(1, 1) | uvec2(32, 64) | uvec2(0, 0) | uvec2(0, 2) | uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 0) ];
+ output uvec3 out0 = [ uvec3(2, 0, 2) | uvec3(8, 1, 1) | uvec3(20, 32, 64) | uvec3(3, 0, 0) | uvec3(0, 0, 2) | uvec3(0, 0, 0) | uvec3(36, 1, 1) | uvec3(1, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_to_vec2
+ version 310 es
+ values
+ {
+ input float in0 = [ -0.5 | -20.125 | 1.0 | 2.0 | 3.5 | 36.8125 | -8.25 | 0.0 ];
+ input float in1 = [ 1.0 | -20.125 | 0.0 | 3.5 | -8.25 | 36.8125 | -0.5 | 2.0 ];
+ output vec2 out0 = [ vec2(-0.5, 1.0) | vec2(-20.125, -20.125) | vec2(1.0, 0.0) | vec2(2.0, 3.5) | vec2(3.5, -8.25) | vec2(36.8125, 36.8125) | vec2(-8.25, -0.5) | vec2(0.0, 2.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_to_ivec2
+ version 310 es
+ values
+ {
+ input float in0 = [ -0.5 | -20.125 | 1.0 | 2.0 | 3.5 | 36.8125 | -8.25 | 0.0 ];
+ input float in1 = [ 1.0 | -20.125 | 0.0 | 3.5 | -8.25 | 36.8125 | -0.5 | 2.0 ];
+ output ivec2 out0 = [ ivec2(0, 1) | ivec2(-20, -20) | ivec2(1, 0) | ivec2(2, 3) | ivec2(3, -8) | ivec2(36, 36) | ivec2(-8, 0) | ivec2(0, 2) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_to_bvec2
+ version 310 es
+ values
+ {
+ input float in0 = [ -0.5 | -20.125 | 1.0 | 2.0 | 3.5 | 36.8125 | -8.25 | 0.0 ];
+ input float in1 = [ 1.0 | -20.125 | 0.0 | 3.5 | -8.25 | 36.8125 | -0.5 | 2.0 ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, true) | bvec2(true, false) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(false, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_to_vec2
+ version 310 es
+ values
+ {
+ input int in0 = [ 2 | -66 | 0 | 5 | -12 | 8 | -192 | 1 | 11 | 255 ];
+ input int in1 = [ -192 | 8 | 1 | 0 | 5 | -66 | 2 | 255 | 11 | -12 ];
+ output vec2 out0 = [ vec2(2.0, -192.0) | vec2(-66.0, 8.0) | vec2(0.0, 1.0) | vec2(5.0, 0.0) | vec2(-12.0, 5.0) | vec2(8.0, -66.0) | vec2(-192.0, 2.0) | vec2(1.0, 255.0) | vec2(11.0, 11.0) | vec2(255.0, -12.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_to_ivec2
+ version 310 es
+ values
+ {
+ input int in0 = [ 2 | -66 | 0 | 5 | -12 | 8 | -192 | 1 | 11 | 255 ];
+ input int in1 = [ -192 | 8 | 1 | 0 | 5 | -66 | 2 | 255 | 11 | -12 ];
+ output ivec2 out0 = [ ivec2(2, -192) | ivec2(-66, 8) | ivec2(0, 1) | ivec2(5, 0) | ivec2(-12, 5) | ivec2(8, -66) | ivec2(-192, 2) | ivec2(1, 255) | ivec2(11, 11) | ivec2(255, -12) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_to_bvec2
+ version 310 es
+ values
+ {
+ input int in0 = [ 2 | -66 | 0 | 5 | -12 | 8 | -192 | 1 | 11 | 255 ];
+ input int in1 = [ -192 | 8 | 1 | 0 | 5 | -66 | 2 | 255 | 11 | -12 ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, true) | bvec2(false, true) | bvec2(true, false) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint_to_vec2
+ version 310 es
+ values
+ {
+ input uint in0 = [ 9 | 12 | 0 | 255 | 8 | 45 | 3 | 2 | 10 | 193 ];
+ input uint in1 = [ 8 | 9 | 45 | 2 | 12 | 193 | 255 | 0 | 3 | 10 ];
+ output vec2 out0 = [ vec2(9.0, 8.0) | vec2(12.0, 9.0) | vec2(0.0, 45.0) | vec2(255.0, 2.0) | vec2(8.0, 12.0) | vec2(45.0, 193.0) | vec2(3.0, 255.0) | vec2(2.0, 0.0) | vec2(10.0, 3.0) | vec2(193.0, 10.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint_to_ivec2
+ version 310 es
+ values
+ {
+ input uint in0 = [ 9 | 12 | 0 | 255 | 8 | 45 | 3 | 2 | 10 | 193 ];
+ input uint in1 = [ 8 | 9 | 45 | 2 | 12 | 193 | 255 | 0 | 3 | 10 ];
+ output ivec2 out0 = [ ivec2(9, 8) | ivec2(12, 9) | ivec2(0, 45) | ivec2(255, 2) | ivec2(8, 12) | ivec2(45, 193) | ivec2(3, 255) | ivec2(2, 0) | ivec2(10, 3) | ivec2(193, 10) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint_to_bvec2
+ version 310 es
+ values
+ {
+ input uint in0 = [ 9 | 12 | 0 | 255 | 8 | 45 | 3 | 2 | 10 | 193 ];
+ input uint in1 = [ 8 | 9 | 45 | 2 | 12 | 193 | 255 | 0 | 3 | 10 ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, false) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_to_vec2
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ true | false ];
+ output vec2 out0 = [ vec2(1.0, 1.0) | vec2(0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_to_ivec2
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ true | false ];
+ output ivec2 out0 = [ ivec2(1, 1) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_to_bvec2
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ true | false ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_int_to_vec2
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 3.5 | 0.0 | 2.0 | -8.25 | 36.8125 | -20.125 | 1.0 | 1.0 | -0.5 ];
+ input int in1 = [ -66 | 1 | 255 | -192 | 8 | 2 | 0 | 5 | -12 | 11 ];
+ output vec2 out0 = [ vec2(0.0, -66.0) | vec2(3.5, 1.0) | vec2(0.0, 255.0) | vec2(2.0, -192.0) | vec2(-8.25, 8.0) | vec2(36.8125, 2.0) | vec2(-20.125, 0.0) | vec2(1.0, 5.0) | vec2(1.0, -12.0) | vec2(-0.5, 11.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_int_to_ivec2
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 3.5 | 0.0 | 2.0 | -8.25 | 36.8125 | -20.125 | 1.0 | 1.0 | -0.5 ];
+ input int in1 = [ -66 | 1 | 255 | -192 | 8 | 2 | 0 | 5 | -12 | 11 ];
+ output ivec2 out0 = [ ivec2(0, -66) | ivec2(3, 1) | ivec2(0, 255) | ivec2(2, -192) | ivec2(-8, 8) | ivec2(36, 2) | ivec2(-20, 0) | ivec2(1, 5) | ivec2(1, -12) | ivec2(0, 11) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_int_to_bvec2
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 3.5 | 0.0 | 2.0 | -8.25 | 36.8125 | -20.125 | 1.0 | 1.0 | -0.5 ];
+ input int in1 = [ -66 | 1 | 255 | -192 | 8 | 2 | 0 | 5 | -12 | 11 ];
+ output bvec2 out0 = [ bvec2(false, true) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, false) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_bool_to_vec2
+ version 310 es
+ values
+ {
+ input float in0 = [ 2.0 | 3.5 | 1.0 | -20.125 | -8.25 | 0.0 | -0.5 | 36.8125 ];
+ input bool in1 = [ false | true | true | false | false | true | false | true ];
+ output vec2 out0 = [ vec2(2.0, 0.0) | vec2(3.5, 1.0) | vec2(1.0, 1.0) | vec2(-20.125, 0.0) | vec2(-8.25, 0.0) | vec2(0.0, 1.0) | vec2(-0.5, 0.0) | vec2(36.8125, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_bool_to_ivec2
+ version 310 es
+ values
+ {
+ input float in0 = [ 2.0 | 3.5 | 1.0 | -20.125 | -8.25 | 0.0 | -0.5 | 36.8125 ];
+ input bool in1 = [ false | true | true | false | false | true | false | true ];
+ output ivec2 out0 = [ ivec2(2, 0) | ivec2(3, 1) | ivec2(1, 1) | ivec2(-20, 0) | ivec2(-8, 0) | ivec2(0, 1) | ivec2(0, 0) | ivec2(36, 1) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_bool_to_bvec2
+ version 310 es
+ values
+ {
+ input float in0 = [ 2.0 | 3.5 | 1.0 | -20.125 | -8.25 | 0.0 | -0.5 | 36.8125 ];
+ input bool in1 = [ false | true | true | false | false | true | false | true ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(true, true) | bvec2(true, true) | bvec2(true, false) | bvec2(true, false) | bvec2(false, true) | bvec2(true, false) | bvec2(true, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_bool_to_vec2
+ version 310 es
+ values
+ {
+ input int in0 = [ 255 | 2 | -12 | 1 | -192 | 5 | 8 | 0 | -66 | 11 ];
+ input bool in1 = [ true | false | false | false | true | false | true | false | true | true ];
+ output vec2 out0 = [ vec2(255.0, 1.0) | vec2(2.0, 0.0) | vec2(-12.0, 0.0) | vec2(1.0, 0.0) | vec2(-192.0, 1.0) | vec2(5.0, 0.0) | vec2(8.0, 1.0) | vec2(0.0, 0.0) | vec2(-66.0, 1.0) | vec2(11.0, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_bool_to_ivec2
+ version 310 es
+ values
+ {
+ input int in0 = [ 255 | 2 | -12 | 1 | -192 | 5 | 8 | 0 | -66 | 11 ];
+ input bool in1 = [ true | false | false | false | true | false | true | false | true | true ];
+ output ivec2 out0 = [ ivec2(255, 1) | ivec2(2, 0) | ivec2(-12, 0) | ivec2(1, 0) | ivec2(-192, 1) | ivec2(5, 0) | ivec2(8, 1) | ivec2(0, 0) | ivec2(-66, 1) | ivec2(11, 1) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_bool_to_bvec2
+ version 310 es
+ values
+ {
+ input int in0 = [ 255 | 2 | -12 | 1 | -192 | 5 | 8 | 0 | -66 | 11 ];
+ input bool in1 = [ true | false | false | false | true | false | true | false | true | true ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, false) | bvec2(true, false) | bvec2(true, false) | bvec2(true, true) | bvec2(true, false) | bvec2(true, true) | bvec2(false, false) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_uint_to_vec2
+ version 310 es
+ values
+ {
+ input int in0 = [ -66 | 1 | -192 | -12 | 5 | 255 | 11 | 0 | 2 | 8 ];
+ input uint in1 = [ 193 | 0 | 2 | 10 | 255 | 12 | 45 | 8 | 9 | 3 ];
+ output vec2 out0 = [ vec2(-66.0, 193.0) | vec2(1.0, 0.0) | vec2(-192.0, 2.0) | vec2(-12.0, 10.0) | vec2(5.0, 255.0) | vec2(255.0, 12.0) | vec2(11.0, 45.0) | vec2(0.0, 8.0) | vec2(2.0, 9.0) | vec2(8.0, 3.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_uint_to_ivec2
+ version 310 es
+ values
+ {
+ input int in0 = [ -66 | 1 | -192 | -12 | 5 | 255 | 11 | 0 | 2 | 8 ];
+ input uint in1 = [ 193 | 0 | 2 | 10 | 255 | 12 | 45 | 8 | 9 | 3 ];
+ output ivec2 out0 = [ ivec2(-66, 193) | ivec2(1, 0) | ivec2(-192, 2) | ivec2(-12, 10) | ivec2(5, 255) | ivec2(255, 12) | ivec2(11, 45) | ivec2(0, 8) | ivec2(2, 9) | ivec2(8, 3) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_uint_to_bvec2
+ version 310 es
+ values
+ {
+ input int in0 = [ -66 | 1 | -192 | -12 | 5 | 255 | 11 | 0 | 2 | 8 ];
+ input uint in1 = [ 193 | 0 | 2 | 10 | 255 | 12 | 45 | 8 | 9 | 3 ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, false) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_float_to_vec2
+ version 310 es
+ values
+ {
+ input uint in0 = [ 12 | 0 | 8 | 193 | 3 | 10 | 9 | 2 | 45 | 255 ];
+ input float in1 = [ -20.125 | 0.0 | 3.5 | -8.25 | 0.0 | 1.0 | 2.0 | 36.8125 | -0.5 | 1.0 ];
+ output vec2 out0 = [ vec2(12.0, -20.125) | vec2(0.0, 0.0) | vec2(8.0, 3.5) | vec2(193.0, -8.25) | vec2(3.0, 0.0) | vec2(10.0, 1.0) | vec2(9.0, 2.0) | vec2(2.0, 36.8125) | vec2(45.0, -0.5) | vec2(255.0, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = vec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_float_to_ivec2
+ version 310 es
+ values
+ {
+ input uint in0 = [ 12 | 0 | 8 | 193 | 3 | 10 | 9 | 2 | 45 | 255 ];
+ input float in1 = [ -20.125 | 0.0 | 3.5 | -8.25 | 0.0 | 1.0 | 2.0 | 36.8125 | -0.5 | 1.0 ];
+ output ivec2 out0 = [ ivec2(12, -20) | ivec2(0, 0) | ivec2(8, 3) | ivec2(193, -8) | ivec2(3, 0) | ivec2(10, 1) | ivec2(9, 2) | ivec2(2, 36) | ivec2(45, 0) | ivec2(255, 1) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = ivec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_float_to_bvec2
+ version 310 es
+ values
+ {
+ input uint in0 = [ 12 | 0 | 8 | 193 | 3 | 10 | 9 | 2 | 45 | 255 ];
+ input float in1 = [ -20.125 | 0.0 | 3.5 | -8.25 | 0.0 | 1.0 | 2.0 | 36.8125 | -0.5 | 1.0 ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(false, false) | bvec2(true, true) | bvec2(true, true) | bvec2(true, false) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) | bvec2(true, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = bvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_to_uvec2
+ version 310 es
+ values
+ {
+ input float in0 = [ 8.25 | 36.8125 | 1.0 | 0.5 | 20.125 | 0.0 | 2.0 | 3.5 ];
+ input float in1 = [ 0.5 | 36.8125 | 0.0 | 2.0 | 8.25 | 20.125 | 1.0 | 3.5 ];
+ output uvec2 out0 = [ uvec2(8, 0) | uvec2(36, 36) | uvec2(1, 0) | uvec2(0, 2) | uvec2(20, 8) | uvec2(0, 20) | uvec2(2, 1) | uvec2(3, 3) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_to_uvec2
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | 12 | 8 | 11 | 255 | 66 | 192 | 2 | 5 | 1 ];
+ input int in1 = [ 11 | 12 | 2 | 5 | 66 | 192 | 255 | 0 | 1 | 8 ];
+ output uvec2 out0 = [ uvec2(0, 11) | uvec2(12, 12) | uvec2(8, 2) | uvec2(11, 5) | uvec2(255, 66) | uvec2(66, 192) | uvec2(192, 255) | uvec2(2, 0) | uvec2(5, 1) | uvec2(1, 8) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint_to_uvec2
+ version 310 es
+ values
+ {
+ input uint in0 = [ 3 | 9 | 10 | 193 | 8 | 0 | 255 | 45 | 2 | 12 ];
+ input uint in1 = [ 0 | 2 | 12 | 3 | 10 | 9 | 45 | 193 | 255 | 8 ];
+ output uvec2 out0 = [ uvec2(3, 0) | uvec2(9, 2) | uvec2(10, 12) | uvec2(193, 3) | uvec2(8, 10) | uvec2(0, 9) | uvec2(255, 45) | uvec2(45, 193) | uvec2(2, 255) | uvec2(12, 8) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_to_uvec2
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ true | false ];
+ output uvec2 out0 = [ uvec2(1, 1) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_int_to_uvec2
+ version 310 es
+ values
+ {
+ input float in0 = [ 8.25 | 1.0 | 0.5 | 3.5 | 2.0 | 0.0 | 36.8125 | 1.0 | 0.0 | 20.125 ];
+ input int in1 = [ 0 | 255 | 12 | 5 | 192 | 2 | 66 | 11 | 1 | 8 ];
+ output uvec2 out0 = [ uvec2(8, 0) | uvec2(1, 255) | uvec2(0, 12) | uvec2(3, 5) | uvec2(2, 192) | uvec2(0, 2) | uvec2(36, 66) | uvec2(1, 11) | uvec2(0, 1) | uvec2(20, 8) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_bool_to_uvec2
+ version 310 es
+ values
+ {
+ input float in0 = [ 3.5 | 1.0 | 8.25 | 0.5 | 2.0 | 36.8125 | 0.0 | 20.125 ];
+ input bool in1 = [ true | false | true | false | true | false | false | true ];
+ output uvec2 out0 = [ uvec2(3, 1) | uvec2(1, 0) | uvec2(8, 1) | uvec2(0, 0) | uvec2(2, 1) | uvec2(36, 0) | uvec2(0, 0) | uvec2(20, 1) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_bool_to_uvec2
+ version 310 es
+ values
+ {
+ input int in0 = [ 12 | 11 | 0 | 5 | 8 | 255 | 2 | 1 | 66 | 192 ];
+ input bool in1 = [ true | true | false | false | false | true | false | false | true | true ];
+ output uvec2 out0 = [ uvec2(12, 1) | uvec2(11, 1) | uvec2(0, 0) | uvec2(5, 0) | uvec2(8, 0) | uvec2(255, 1) | uvec2(2, 0) | uvec2(1, 0) | uvec2(66, 1) | uvec2(192, 1) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_uint_to_uvec2
+ version 310 es
+ values
+ {
+ input int in0 = [ 8 | 5 | 1 | 0 | 11 | 12 | 192 | 66 | 255 | 2 ];
+ input uint in1 = [ 8 | 10 | 45 | 255 | 9 | 193 | 2 | 3 | 0 | 12 ];
+ output uvec2 out0 = [ uvec2(8, 8) | uvec2(5, 10) | uvec2(1, 45) | uvec2(0, 255) | uvec2(11, 9) | uvec2(12, 193) | uvec2(192, 2) | uvec2(66, 3) | uvec2(255, 0) | uvec2(2, 12) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_float_to_uvec2
+ version 310 es
+ values
+ {
+ input uint in0 = [ 9 | 45 | 8 | 3 | 10 | 2 | 193 | 12 | 255 | 0 ];
+ input float in1 = [ 3.5 | 20.125 | 2.0 | 0.0 | 1.0 | 36.8125 | 8.25 | 1.0 | 0.0 | 0.5 ];
+ output uvec2 out0 = [ uvec2(9, 3) | uvec2(45, 20) | uvec2(8, 2) | uvec2(3, 0) | uvec2(10, 1) | uvec2(2, 36) | uvec2(193, 8) | uvec2(12, 1) | uvec2(255, 0) | uvec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = uvec2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # vector_combine
+group matrix_combine "Matrix Combine Constructors"
+
+ case vec2_vec2_to_mat2
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(1.0, 1.25) | vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(-0.75, -0.0322580645161) | vec2(0.0, 0.5) ];
+ input vec2 in1 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(-0.5, -2.25) ];
+ output mat2 out0 = [ mat2(1.0, 1.25, 0.0, 0.5) | mat2(-32.0, 64.0, 1.0, 1.25) | mat2(-0.5, -2.25, -0.75, -0.0322580645161) | mat2(-0.75, -0.0322580645161, -32.0, 64.0) | mat2(0.0, 0.5, -0.5, -2.25) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec2_bvec2_to_mat2
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(false, true) | bvec2(true, true) | bvec2(true, false) | bvec2(false, false) | bvec2(false, false) ];
+ input bvec2 in1 = [ bvec2(false, false) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, true) ];
+ output mat2 out0 = [ mat2(0.0, 1.0, 0.0, 0.0) | mat2(1.0, 1.0, 1.0, 0.0) | mat2(1.0, 0.0, 0.0, 0.0) | mat2(0.0, 0.0, 1.0, 1.0) | mat2(0.0, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_float_to_mat2
+ version 310 es
+ values
+ {
+ input float in0 = [ -8.25 | 3.5 | 36.8125 | 2.0 | -20.125 | 1.0 | -0.5 | 0.0 ];
+ input float in1 = [ 3.5 | -20.125 | 1.0 | 0.0 | -8.25 | 2.0 | 36.8125 | -0.5 ];
+ input float in2 = [ 36.8125 | 3.5 | 0.0 | -20.125 | -0.5 | -8.25 | 1.0 | 2.0 ];
+ input float in3 = [ -0.5 | 0.0 | -8.25 | -20.125 | 2.0 | 3.5 | 1.0 | 36.8125 ];
+ output mat2 out0 = [ mat2(-8.25, 3.5, 36.8125, -0.5) | mat2(3.5, -20.125, 3.5, 0.0) | mat2(36.8125, 1.0, 0.0, -8.25) | mat2(2.0, 0.0, -20.125, -20.125) | mat2(-20.125, -8.25, -0.5, 2.0) | mat2(1.0, 2.0, -8.25, 3.5) | mat2(-0.5, 36.8125, 1.0, 1.0) | mat2(0.0, -0.5, 2.0, 36.8125) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_int_to_mat2
+ version 310 es
+ values
+ {
+ input int in0 = [ 2 | 1 | -192 | 11 | -66 | 255 | 0 | 8 | -12 | 5 ];
+ input int in1 = [ 11 | 255 | 5 | -66 | 8 | 2 | 0 | -12 | 1 | -192 ];
+ input int in2 = [ 11 | 1 | -12 | 255 | 5 | 0 | 8 | -192 | 2 | -66 ];
+ input int in3 = [ 2 | 1 | 0 | 8 | 255 | -66 | -192 | 11 | 5 | -12 ];
+ output mat2 out0 = [ mat2(2.0, 11.0, 11.0, 2.0) | mat2(1.0, 255.0, 1.0, 1.0) | mat2(-192.0, 5.0, -12.0, 0.0) | mat2(11.0, -66.0, 255.0, 8.0) | mat2(-66.0, 8.0, 5.0, 255.0) | mat2(255.0, 2.0, 0.0, -66.0) | mat2(0.0, 0.0, 8.0, -192.0) | mat2(8.0, -12.0, -192.0, 11.0) | mat2(-12.0, 1.0, 2.0, 5.0) | mat2(5.0, -192.0, -66.0, -12.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint_uint_uint_to_mat2
+ version 310 es
+ values
+ {
+ input uint in0 = [ 193 | 9 | 12 | 45 | 10 | 2 | 8 | 3 | 255 | 0 ];
+ input uint in1 = [ 0 | 255 | 12 | 193 | 3 | 2 | 45 | 9 | 8 | 10 ];
+ input uint in2 = [ 3 | 9 | 10 | 2 | 12 | 193 | 255 | 0 | 8 | 45 ];
+ input uint in3 = [ 45 | 12 | 9 | 3 | 2 | 255 | 10 | 8 | 193 | 0 ];
+ output mat2 out0 = [ mat2(193.0, 0.0, 3.0, 45.0) | mat2(9.0, 255.0, 9.0, 12.0) | mat2(12.0, 12.0, 10.0, 9.0) | mat2(45.0, 193.0, 2.0, 3.0) | mat2(10.0, 3.0, 12.0, 2.0) | mat2(2.0, 2.0, 193.0, 255.0) | mat2(8.0, 45.0, 255.0, 10.0) | mat2(3.0, 9.0, 0.0, 8.0) | mat2(255.0, 8.0, 8.0, 193.0) | mat2(0.0, 10.0, 45.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_bool_to_mat2
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ true | false ];
+ input bool in2 = [ true | false ];
+ input bool in3 = [ false | true ];
+ output mat2 out0 = [ mat2(1.0, 1.0, 1.0, 0.0) | mat2(0.0, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_bool_to_mat2
+ version 310 es
+ values
+ {
+ input bool in0 = [ false | true | false | true | true | false | true | true | false | false ];
+ input float in1 = [ 2.0 | -0.5 | 0.0 | 1.0 | 1.0 | 36.8125 | 3.5 | 0.0 | -8.25 | -20.125 ];
+ input int in2 = [ 0 | -12 | 8 | -192 | 1 | -66 | 5 | 11 | 2 | 255 ];
+ input bool in3 = [ true | false | true | false | true | false | false | true | true | false ];
+ output mat2 out0 = [ mat2(0.0, 2.0, 0.0, 1.0) | mat2(1.0, -0.5, -12.0, 0.0) | mat2(0.0, 0.0, 8.0, 1.0) | mat2(1.0, 1.0, -192.0, 0.0) | mat2(1.0, 1.0, 1.0, 1.0) | mat2(0.0, 36.8125, -66.0, 0.0) | mat2(1.0, 3.5, 5.0, 0.0) | mat2(1.0, 0.0, 11.0, 1.0) | mat2(0.0, -8.25, 2.0, 1.0) | mat2(0.0, -20.125, 255.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_to_mat2
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(1.0, 1.25) | vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(-0.75, -0.0322580645161) | vec2(0.0, 0.5) ];
+ input ivec2 in1 = [ ivec2(0, -2) | ivec2(0, 0) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) ];
+ output mat2 out0 = [ mat2(1.0, 1.25, 0.0, -2.0) | mat2(-32.0, 64.0, 0.0, 0.0) | mat2(-0.5, -2.25, 0.0, 0.0) | mat2(-0.75, -0.0322580645161, -32.0, 64.0) | mat2(0.0, 0.5, 1.0, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bvec2_to_mat2
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) | vec2(0.0, 0.5) ];
+ input bvec2 in1 = [ bvec2(false, false) | bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) ];
+ output mat2 out0 = [ mat2(-0.5, -2.25, 0.0, 0.0) | mat2(-32.0, 64.0, 1.0, 0.0) | mat2(1.0, 1.25, 0.0, 0.0) | mat2(-0.75, -0.0322580645161, 0.0, 1.0) | mat2(0.0, 0.5, 1.0, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_float_to_mat2
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, true, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(true, false, false) | bvec3(false, true, false) | bvec3(false, false, false) | bvec3(false, false, false) ];
+ input float in1 = [ 36.8125 | -8.25 | 1.0 | -0.5 | 2.0 | -20.125 | 0.0 | 3.5 ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 0.0, 36.8125) | mat2(0.0, 1.0, 0.0, -8.25) | mat2(0.0, 0.0, 0.0, 1.0) | mat2(1.0, 1.0, 1.0, -0.5) | mat2(1.0, 0.0, 0.0, 2.0) | mat2(0.0, 1.0, 0.0, -20.125) | mat2(0.0, 0.0, 0.0, 0.0) | mat2(0.0, 0.0, 0.0, 3.5) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_float_to_mat2
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-0.5, -2.25, -4.875) | vec3(1.0, 1.25, 1.125) | vec3(0.0, 0.5, 0.75) | vec3(-32.0, 64.0, -51.0) | vec3(0.0, 0.5, 0.75) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ input float in1 = [ -0.5 | -20.125 | 0.0 | 36.8125 | 3.5 | -8.25 | 2.0 | 1.0 ];
+ output mat2 out0 = [ mat2(1.0, 1.25, 1.125, -0.5) | mat2(-0.5, -2.25, -4.875, -20.125) | mat2(-0.5, -2.25, -4.875, 0.0) | mat2(1.0, 1.25, 1.125, 36.8125) | mat2(0.0, 0.5, 0.75, 3.5) | mat2(-32.0, 64.0, -51.0, -8.25) | mat2(0.0, 0.5, 0.75, 2.0) | mat2(-0.75, -0.0322580645161, 0.0526315789474, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_ivec2_int_to_mat2
+ version 310 es
+ values
+ {
+ input int in0 = [ 8 | -192 | 2 | 0 | -66 | 255 | 5 | 1 | -12 | 11 ];
+ input ivec2 in1 = [ ivec2(0, -2) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, -2) | ivec2(1, 1) | ivec2(1, 1) ];
+ input int in2 = [ 2 | 1 | -12 | 0 | 11 | 8 | 255 | -192 | 5 | -66 ];
+ output mat2 out0 = [ mat2(8.0, 0.0, -2.0, 2.0) | mat2(-192.0, 0.0, 0.0, 1.0) | mat2(2.0, -32.0, 64.0, -12.0) | mat2(0.0, 0.0, 0.0, 0.0) | mat2(-66.0, 0.0, 0.0, 11.0) | mat2(255.0, -32.0, 64.0, 8.0) | mat2(5.0, 0.0, 0.0, 255.0) | mat2(1.0, 0.0, -2.0, -192.0) | mat2(-12.0, 1.0, 1.0, 5.0) | mat2(11.0, 1.0, 1.0, -66.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_ivec2_to_mat2
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | true | true | false | false | true | false | false ];
+ input float in1 = [ 1.0 | -0.5 | -20.125 | 36.8125 | 2.0 | 0.0 | -8.25 | 3.5 ];
+ input ivec2 in2 = [ ivec2(0, 0) | ivec2(0, 0) | ivec2(1, 1) | ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, -2) ];
+ output mat2 out0 = [ mat2(1.0, 1.0, 0.0, 0.0) | mat2(1.0, -0.5, 0.0, 0.0) | mat2(1.0, -20.125, 1.0, 1.0) | mat2(0.0, 36.8125, 0.0, 0.0) | mat2(0.0, 2.0, 1.0, 1.0) | mat2(1.0, 0.0, 0.0, -2.0) | mat2(0.0, -8.25, -32.0, 64.0) | mat2(0.0, 3.5, 0.0, -2.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_uvec3_to_mat2
+ version 310 es
+ values
+ {
+ input float in0 = [ 36.8125 | 2.0 | -0.5 | 0.0 | -20.125 | 1.0 | 3.5 | -8.25 ];
+ input uvec3 in1 = [ uvec3(1, 1, 1) | uvec3(0, 2, 4) | uvec3(0, 2, 4) | uvec3(0, 0, 0) | uvec3(32, 64, 51) | uvec3(0, 0, 0) | uvec3(0, 0, 0) | uvec3(1, 1, 1) ];
+ output mat2 out0 = [ mat2(36.8125, 1.0, 1.0, 1.0) | mat2(2.0, 0.0, 2.0, 4.0) | mat2(-0.5, 0.0, 2.0, 4.0) | mat2(0.0, 0.0, 0.0, 0.0) | mat2(-20.125, 32.0, 64.0, 51.0) | mat2(1.0, 0.0, 0.0, 0.0) | mat2(3.5, 0.0, 0.0, 0.0) | mat2(-8.25, 1.0, 1.0, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_uvec2_bool_to_mat2
+ version 310 es
+ values
+ {
+ input int in0 = [ 1 | -66 | 5 | -192 | 11 | 0 | 8 | 2 | -12 | 255 ];
+ input uvec2 in1 = [ uvec2(0, 2) | uvec2(32, 64) | uvec2(1, 1) | uvec2(0, 0) | uvec2(0, 0) | uvec2(1, 1) | uvec2(0, 2) | uvec2(0, 0) | uvec2(0, 0) | uvec2(32, 64) ];
+ input bool in2 = [ true | false | true | false | false | false | true | true | true | false ];
+ output mat2 out0 = [ mat2(1.0, 0.0, 2.0, 1.0) | mat2(-66.0, 32.0, 64.0, 0.0) | mat2(5.0, 1.0, 1.0, 1.0) | mat2(-192.0, 0.0, 0.0, 0.0) | mat2(11.0, 0.0, 0.0, 0.0) | mat2(0.0, 1.0, 1.0, 0.0) | mat2(8.0, 0.0, 2.0, 1.0) | mat2(2.0, 0.0, 0.0, 1.0) | mat2(-12.0, 0.0, 0.0, 1.0) | mat2(255.0, 32.0, 64.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_vec3_to_mat2x3
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(1.0, 1.25, 1.125) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(0.0, 0.5, 0.75) ];
+ input vec3 in1 = [ vec3(-32.0, 64.0, -51.0) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output mat2x3 out0 = [ mat2x3(1.0, 1.25, 1.125, -32.0, 64.0, -51.0) | mat2x3(-0.75, -0.0322580645161, 0.0526315789474, -0.5, -2.25, -4.875) | mat2x3(-0.5, -2.25, -4.875, 0.0, 0.5, 0.75) | mat2x3(-32.0, 64.0, -51.0, 1.0, 1.25, 1.125) | mat2x3(0.0, 0.5, 0.75, -0.75, -0.0322580645161, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_bvec3_to_mat2x3
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, true, false) | bvec3(true, false, false) ];
+ input bvec3 in1 = [ bvec3(false, false, false) | bvec3(true, true, true) | bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) ];
+ output mat2x3 out0 = [ mat2x3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat2x3(0.0, 0.0, 0.0, 1.0, 1.0, 1.0) | mat2x3(1.0, 1.0, 1.0, 1.0, 0.0, 0.0) | mat2x3(0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat2x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_float_float_float_to_mat2x3
+ version 310 es
+ values
+ {
+ input float in0 = [ 1.0 | -8.25 | -20.125 | 36.8125 | -0.5 | 2.0 | 3.5 | 0.0 ];
+ input float in1 = [ -0.5 | -20.125 | 36.8125 | -8.25 | 2.0 | 1.0 | 3.5 | 0.0 ];
+ input float in2 = [ 3.5 | 1.0 | 36.8125 | -20.125 | -8.25 | -0.5 | 2.0 | 0.0 ];
+ input float in3 = [ 1.0 | -8.25 | 0.0 | -20.125 | 2.0 | 3.5 | -0.5 | 36.8125 ];
+ input float in4 = [ 1.0 | 0.0 | 3.5 | 2.0 | -8.25 | -20.125 | -0.5 | 36.8125 ];
+ input float in5 = [ 2.0 | -20.125 | -8.25 | -0.5 | 3.5 | 1.0 | 36.8125 | 0.0 ];
+ output mat2x3 out0 = [ mat2x3(1.0, -0.5, 3.5, 1.0, 1.0, 2.0) | mat2x3(-8.25, -20.125, 1.0, -8.25, 0.0, -20.125) | mat2x3(-20.125, 36.8125, 36.8125, 0.0, 3.5, -8.25) | mat2x3(36.8125, -8.25, -20.125, -20.125, 2.0, -0.5) | mat2x3(-0.5, 2.0, -8.25, 2.0, -8.25, 3.5) | mat2x3(2.0, 1.0, -0.5, 3.5, -20.125, 1.0) | mat2x3(3.5, 3.5, 2.0, -0.5, -0.5, 36.8125) | mat2x3(0.0, 0.0, 0.0, 36.8125, 36.8125, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_int_int_int_to_mat2x3
+ version 310 es
+ values
+ {
+ input int in0 = [ 2 | 8 | -192 | 0 | 5 | -12 | 1 | 255 | -66 | 11 ];
+ input int in1 = [ 1 | -192 | 8 | 0 | -12 | 2 | 11 | 255 | -66 | 5 ];
+ input int in2 = [ -192 | 2 | -66 | 8 | 11 | 255 | 0 | 5 | -12 | 1 ];
+ input int in3 = [ 2 | 11 | 255 | 0 | -66 | -12 | 5 | -192 | 8 | 1 ];
+ input int in4 = [ 8 | 0 | -12 | -192 | 2 | -66 | 1 | 255 | 5 | 11 ];
+ input int in5 = [ 0 | 11 | 5 | 8 | -12 | 255 | -192 | 2 | 1 | -66 ];
+ output mat2x3 out0 = [ mat2x3(2.0, 1.0, -192.0, 2.0, 8.0, 0.0) | mat2x3(8.0, -192.0, 2.0, 11.0, 0.0, 11.0) | mat2x3(-192.0, 8.0, -66.0, 255.0, -12.0, 5.0) | mat2x3(0.0, 0.0, 8.0, 0.0, -192.0, 8.0) | mat2x3(5.0, -12.0, 11.0, -66.0, 2.0, -12.0) | mat2x3(-12.0, 2.0, 255.0, -12.0, -66.0, 255.0) | mat2x3(1.0, 11.0, 0.0, 5.0, 1.0, -192.0) | mat2x3(255.0, 255.0, 5.0, -192.0, 255.0, 2.0) | mat2x3(-66.0, -66.0, -12.0, 8.0, 5.0, 1.0) | mat2x3(11.0, 5.0, 1.0, 1.0, 11.0, -66.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_bool_bool_bool_to_mat2x3
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ false | true ];
+ input bool in2 = [ false | true ];
+ input bool in3 = [ true | false ];
+ input bool in4 = [ true | false ];
+ input bool in5 = [ true | false ];
+ output mat2x3 out0 = [ mat2x3(1.0, 0.0, 0.0, 1.0, 1.0, 1.0) | mat2x3(0.0, 1.0, 1.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_bool_float_int_to_mat2x3
+ version 310 es
+ values
+ {
+ input bool in0 = [ false | true | false | true | false | true | false | true | true | false ];
+ input float in1 = [ 0.0 | -8.25 | 2.0 | -20.125 | 3.5 | 0.0 | -0.5 | 36.8125 | 1.0 | 1.0 ];
+ input int in2 = [ -66 | -12 | 2 | 8 | 255 | 11 | -192 | 1 | 5 | 0 ];
+ input bool in3 = [ true | false | true | false | false | true | true | false | true | false ];
+ input float in4 = [ 1.0 | 0.0 | -8.25 | 1.0 | 3.5 | -20.125 | -0.5 | 0.0 | 2.0 | 36.8125 ];
+ input int in5 = [ 255 | -192 | 1 | 2 | -12 | -66 | 8 | 0 | 11 | 5 ];
+ output mat2x3 out0 = [ mat2x3(0.0, 0.0, -66.0, 1.0, 1.0, 255.0) | mat2x3(1.0, -8.25, -12.0, 0.0, 0.0, -192.0) | mat2x3(0.0, 2.0, 2.0, 1.0, -8.25, 1.0) | mat2x3(1.0, -20.125, 8.0, 0.0, 1.0, 2.0) | mat2x3(0.0, 3.5, 255.0, 0.0, 3.5, -12.0) | mat2x3(1.0, 0.0, 11.0, 1.0, -20.125, -66.0) | mat2x3(0.0, -0.5, -192.0, 1.0, -0.5, 8.0) | mat2x3(1.0, 36.8125, 1.0, 0.0, 0.0, 0.0) | mat2x3(1.0, 1.0, 5.0, 1.0, 2.0, 11.0) | mat2x3(0.0, 1.0, 0.0, 0.0, 36.8125, 5.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_ivec3_to_mat2x3
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(0.0, 0.5, 0.75) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ input ivec3 in1 = [ ivec3(1, 1, 1) | ivec3(-32, 64, -51) | ivec3(0, -2, -4) | ivec3(0, 0, 0) | ivec3(0, 0, 0) ];
+ output mat2x3 out0 = [ mat2x3(1.0, 1.25, 1.125, 1.0, 1.0, 1.0) | mat2x3(-0.5, -2.25, -4.875, -32.0, 64.0, -51.0) | mat2x3(-32.0, 64.0, -51.0, 0.0, -2.0, -4.0) | mat2x3(0.0, 0.5, 0.75, 0.0, 0.0, 0.0) | mat2x3(-0.75, -0.0322580645161, 0.0526315789474, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bvec4_to_mat2x3
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(-32.0, 64.0) | vec2(0.0, 0.5) | vec2(-0.5, -2.25) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) ];
+ input bvec4 in1 = [ bvec4(true, false, false, true) | bvec4(false, true, false, false) | bvec4(false, false, false, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output mat2x3 out0 = [ mat2x3(-32.0, 64.0, 1.0, 0.0, 0.0, 1.0) | mat2x3(0.0, 0.5, 0.0, 1.0, 0.0, 0.0) | mat2x3(-0.5, -2.25, 0.0, 0.0, 0.0, 1.0) | mat2x3(1.0, 1.25, 1.0, 1.0, 1.0, 1.0) | mat2x3(-0.75, -0.0322580645161, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_float_ivec2_to_mat2x3
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, false, false) | bvec3(false, true, false) ];
+ input float in1 = [ 1.0 | -8.25 | 36.8125 | 2.0 | 3.5 | -0.5 | -20.125 | 0.0 ];
+ input ivec2 in2 = [ ivec2(1, 1) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(0, -2) | ivec2(1, 1) | ivec2(0, -2) | ivec2(0, 0) | ivec2(0, 0) ];
+ output mat2x3 out0 = [ mat2x3(0.0, 0.0, 0.0, 1.0, 1.0, 1.0) | mat2x3(0.0, 0.0, 0.0, -8.25, 0.0, 0.0) | mat2x3(1.0, 1.0, 1.0, 36.8125, -32.0, 64.0) | mat2x3(1.0, 0.0, 0.0, 2.0, 0.0, -2.0) | mat2x3(0.0, 0.0, 0.0, 3.5, 1.0, 1.0) | mat2x3(0.0, 1.0, 0.0, -0.5, 0.0, -2.0) | mat2x3(1.0, 0.0, 0.0, -20.125, 0.0, 0.0) | mat2x3(0.0, 1.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_float_bvec2_to_mat2x3
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(-32.0, 64.0, -51.0) | vec3(1.0, 1.25, 1.125) ];
+ input float in1 = [ 0.0 | 36.8125 | 3.5 | -0.5 | -8.25 | 2.0 | 1.0 | -20.125 ];
+ input bvec2 in2 = [ bvec2(false, false) | bvec2(false, true) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, false) | bvec2(true, true) | bvec2(false, false) ];
+ output mat2x3 out0 = [ mat2x3(0.0, 0.5, 0.75, 0.0, 0.0, 0.0) | mat2x3(-0.5, -2.25, -4.875, 36.8125, 0.0, 1.0) | mat2x3(0.0, 0.5, 0.75, 3.5, 1.0, 0.0) | mat2x3(1.0, 1.25, 1.125, -0.5, 0.0, 1.0) | mat2x3(-0.5, -2.25, -4.875, -8.25, 0.0, 0.0) | mat2x3(-0.75, -0.0322580645161, 0.0526315789474, 2.0, 1.0, 0.0) | mat2x3(-32.0, 64.0, -51.0, 1.0, 1.0, 1.0) | mat2x3(1.0, 1.25, 1.125, -20.125, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_vec3_vec2_to_mat2x4
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(-0.5, -2.25, -4.875) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-32.0, 64.0, -51.0) ];
+ input vec3 in1 = [ vec3(0.0, 0.5, 0.75) | vec3(-0.5, -2.25, -4.875) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(-32.0, 64.0, -51.0) | vec3(1.0, 1.25, 1.125) ];
+ input vec2 in2 = [ vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-0.5, -2.25) ];
+ output mat2x4 out0 = [ mat2x4(-0.5, -2.25, -4.875, 0.0, 0.5, 0.75, -0.75, -0.0322580645161) | mat2x4(-0.75, -0.0322580645161, 0.0526315789474, -0.5, -2.25, -4.875, -32.0, 64.0) | mat2x4(0.0, 0.5, 0.75, -0.75, -0.0322580645161, 0.0526315789474, 1.0, 1.25) | mat2x4(1.0, 1.25, 1.125, -32.0, 64.0, -51.0, 0.0, 0.5) | mat2x4(-32.0, 64.0, -51.0, 1.0, 1.25, 1.125, -0.5, -2.25) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_ivec3_ivec2_to_mat2x4
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, -2, -4) | ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, 0, 0) | ivec3(-32, 64, -51) ];
+ input ivec3 in1 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ input ivec2 in2 = [ ivec2(0, 0) | ivec2(0, -2) | ivec2(1, 1) | ivec2(0, 0) | ivec2(-32, 64) ];
+ output mat2x4 out0 = [ mat2x4(0.0, -2.0, -4.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat2x4(0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, -2.0) | mat2x4(1.0, 1.0, 1.0, 0.0, -2.0, -4.0, 1.0, 1.0) | mat2x4(0.0, 0.0, 0.0, -32.0, 64.0, -51.0, 0.0, 0.0) | mat2x4(-32.0, 64.0, -51.0, 0.0, 0.0, 0.0, -32.0, 64.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_float_float_int_bool_to_mat2x4
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(0.0, 0.5) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-0.75, -0.0322580645161) ];
+ input ivec2 in1 = [ ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, -2) | ivec2(0, 0) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, 0) | ivec2(1, 1) ];
+ input float in2 = [ -8.25 | -0.5 | 3.5 | 36.8125 | 0.0 | 0.0 | 2.0 | -20.125 | 1.0 | 1.0 ];
+ input float in3 = [ 1.0 | 2.0 | -0.5 | 3.5 | 36.8125 | -8.25 | 1.0 | 0.0 | 0.0 | -20.125 ];
+ input int in4 = [ 255 | 8 | 11 | -12 | -192 | 0 | 2 | 1 | -66 | 5 ];
+ input bool in5 = [ true | false | false | true | false | true | true | false | true | false ];
+ output mat2x4 out0 = [ mat2x4(0.0, 0.5, 1.0, 1.0, -8.25, 1.0, 255.0, 1.0) | mat2x4(-32.0, 64.0, 0.0, -2.0, -0.5, 2.0, 8.0, 0.0) | mat2x4(-0.5, -2.25, -32.0, 64.0, 3.5, -0.5, 11.0, 0.0) | mat2x4(0.0, 0.5, 0.0, -2.0, 36.8125, 3.5, -12.0, 1.0) | mat2x4(-32.0, 64.0, 0.0, 0.0, 0.0, 36.8125, -192.0, 0.0) | mat2x4(1.0, 1.25, 0.0, 0.0, 0.0, -8.25, 0.0, 1.0) | mat2x4(-0.75, -0.0322580645161, -32.0, 64.0, 2.0, 1.0, 2.0, 1.0) | mat2x4(1.0, 1.25, 0.0, 0.0, -20.125, 0.0, 1.0, 0.0) | mat2x4(-0.5, -2.25, 0.0, 0.0, 1.0, 0.0, -66.0, 1.0) | mat2x4(-0.75, -0.0322580645161, 1.0, 1.0, 1.0, -20.125, 5.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_vec2_bool_bvec2_to_mat2x4
+ version 310 es
+ values
+ {
+ input bool in0 = [ false | true | false | true | true | true | false | false | false | true ];
+ input float in1 = [ 0.0 | -0.5 | -20.125 | -8.25 | 0.0 | 2.0 | 3.5 | 1.0 | 1.0 | 36.8125 ];
+ input int in2 = [ 2 | 1 | 255 | 8 | -66 | 0 | -12 | 5 | -192 | 11 ];
+ input vec2 in3 = [ vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) | vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(0.0, 0.5) | vec2(-0.75, -0.0322580645161) ];
+ input bool in4 = [ true | false | false | true | false | false | true | true | true | false ];
+ input bvec2 in5 = [ bvec2(true, false) | bvec2(true, true) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) | bvec2(false, true) | bvec2(false, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, false) ];
+ output mat2x4 out0 = [ mat2x4(0.0, 0.0, 2.0, -32.0, 64.0, 1.0, 1.0, 0.0) | mat2x4(1.0, -0.5, 1.0, -0.5, -2.25, 0.0, 1.0, 1.0) | mat2x4(0.0, -20.125, 255.0, 1.0, 1.25, 0.0, 0.0, 1.0) | mat2x4(1.0, -8.25, 8.0, -0.75, -0.0322580645161, 1.0, 1.0, 1.0) | mat2x4(1.0, 0.0, -66.0, 0.0, 0.5, 0.0, 0.0, 0.0) | mat2x4(1.0, 2.0, 0.0, 1.0, 1.25, 0.0, 0.0, 1.0) | mat2x4(0.0, 3.5, -12.0, -32.0, 64.0, 1.0, 0.0, 0.0) | mat2x4(0.0, 1.0, 5.0, -0.5, -2.25, 1.0, 0.0, 0.0) | mat2x4(0.0, 1.0, -192.0, 0.0, 0.5, 1.0, 0.0, 0.0) | mat2x4(1.0, 36.8125, 11.0, -0.75, -0.0322580645161, 0.0, 1.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bvec2_int_vec4_to_mat2x4
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | true | true | false | false | false | false | false | true | true ];
+ input bvec2 in1 = [ bvec2(true, true) | bvec2(false, false) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(false, true) | bvec2(false, false) ];
+ input int in2 = [ 8 | 1 | 5 | -66 | -192 | 11 | 255 | 0 | -12 | 2 ];
+ input vec4 in3 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) ];
+ output mat2x4 out0 = [ mat2x4(1.0, 1.0, 1.0, 8.0, 0.0, 0.5, 0.75, 0.825) | mat2x4(1.0, 0.0, 0.0, 1.0, 0.0, 0.5, 0.75, 0.825) | mat2x4(1.0, 1.0, 0.0, 5.0, -32.0, 64.0, -51.0, 24.0) | mat2x4(0.0, 0.0, 0.0, -66.0, 1.0, 1.25, 1.125, 1.75) | mat2x4(0.0, 1.0, 1.0, -192.0, -0.5, -2.25, -4.875, 9.0) | mat2x4(0.0, 1.0, 0.0, 11.0, 1.0, 1.25, 1.125, 1.75) | mat2x4(0.0, 0.0, 1.0, 255.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25) | mat2x4(0.0, 0.0, 0.0, 0.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25) | mat2x4(1.0, 0.0, 1.0, -12.0, -0.5, -2.25, -4.875, 9.0) | mat2x4(1.0, 0.0, 0.0, 2.0, -32.0, 64.0, -51.0, 24.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_bvec4_ivec2_bool_to_mat2x4
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 3.5 | 2.0 | -8.25 | -20.125 | 36.8125 | 1.0 | -0.5 ];
+ input bvec4 in1 = [ bvec4(true, false, false, true) | bvec4(true, true, true, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(false, true, false, false) | bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, false, false, false) ];
+ input ivec2 in2 = [ ivec2(0, -2) | ivec2(-32, 64) | ivec2(1, 1) | ivec2(1, 1) | ivec2(0, 0) | ivec2(0, 0) | ivec2(0, 0) | ivec2(0, -2) ];
+ input bool in3 = [ true | true | false | true | false | false | false | true ];
+ output mat2x4 out0 = [ mat2x4(0.0, 1.0, 0.0, 0.0, 1.0, 0.0, -2.0, 1.0) | mat2x4(3.5, 1.0, 1.0, 1.0, 1.0, -32.0, 64.0, 1.0) | mat2x4(2.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0) | mat2x4(-8.25, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0) | mat2x4(-20.125, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat2x4(36.8125, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat2x4(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) | mat2x4(-0.5, 0.0, 0.0, 0.0, 0.0, 0.0, -2.0, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat2x4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_vec3_to_mat3x2
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(-32.0, 64.0, -51.0) | vec3(1.0, 1.25, 1.125) ];
+ input vec3 in1 = [ vec3(1.0, 1.25, 1.125) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(-32.0, 64.0, -51.0) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) ];
+ output mat3x2 out0 = [ mat3x2(-0.75, -0.0322580645161, 0.0526315789474, 1.0, 1.25, 1.125) | mat3x2(-0.5, -2.25, -4.875, -0.75, -0.0322580645161, 0.0526315789474) | mat3x2(0.0, 0.5, 0.75, -32.0, 64.0, -51.0) | mat3x2(-32.0, 64.0, -51.0, -0.5, -2.25, -4.875) | mat3x2(1.0, 1.25, 1.125, 0.0, 0.5, 0.75) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_bvec3_to_mat3x2
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, true, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ input bvec3 in1 = [ bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, true, false) | bvec3(true, false, false) ];
+ output mat3x2 out0 = [ mat3x2(1.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3x2(0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat3x2(0.0, 0.0, 0.0, 1.0, 1.0, 1.0) | mat3x2(1.0, 1.0, 1.0, 0.0, 1.0, 0.0) | mat3x2(0.0, 0.0, 0.0, 1.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_float_float_float_float_float_to_mat3x2
+ version 310 es
+ values
+ {
+ input float in0 = [ -8.25 | 36.8125 | -20.125 | -0.5 | 3.5 | 1.0 | 2.0 | 0.0 ];
+ input float in1 = [ 2.0 | 3.5 | -20.125 | 36.8125 | 1.0 | 0.0 | -8.25 | -0.5 ];
+ input float in2 = [ -0.5 | 2.0 | 1.0 | 0.0 | -8.25 | 36.8125 | -20.125 | 3.5 ];
+ input float in3 = [ 36.8125 | 0.0 | 1.0 | -0.5 | 2.0 | 3.5 | -20.125 | -8.25 ];
+ input float in4 = [ 36.8125 | 2.0 | 0.0 | -0.5 | 3.5 | -20.125 | -8.25 | 1.0 ];
+ input float in5 = [ 0.0 | 36.8125 | -20.125 | -0.5 | 3.5 | 2.0 | 1.0 | -8.25 ];
+ output mat3x2 out0 = [ mat3x2(-8.25, 2.0, -0.5, 36.8125, 36.8125, 0.0) | mat3x2(36.8125, 3.5, 2.0, 0.0, 2.0, 36.8125) | mat3x2(-20.125, -20.125, 1.0, 1.0, 0.0, -20.125) | mat3x2(-0.5, 36.8125, 0.0, -0.5, -0.5, -0.5) | mat3x2(3.5, 1.0, -8.25, 2.0, 3.5, 3.5) | mat3x2(1.0, 0.0, 36.8125, 3.5, -20.125, 2.0) | mat3x2(2.0, -8.25, -20.125, -20.125, -8.25, 1.0) | mat3x2(0.0, -0.5, 3.5, -8.25, 1.0, -8.25) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int_int_int_int_int_to_mat3x2
+ version 310 es
+ values
+ {
+ input int in0 = [ 8 | -192 | 2 | 11 | 255 | -66 | 5 | -12 | 1 | 0 ];
+ input int in1 = [ 1 | 2 | -12 | 5 | 0 | 255 | 8 | 11 | -192 | -66 ];
+ input int in2 = [ -12 | 11 | 2 | 1 | 8 | -66 | -192 | 5 | 255 | 0 ];
+ input int in3 = [ -192 | 0 | -12 | 11 | 1 | -66 | 8 | 255 | 2 | 5 ];
+ input int in4 = [ -12 | 5 | 0 | -66 | 255 | 8 | -192 | 11 | 2 | 1 ];
+ input int in5 = [ -66 | -12 | 8 | 2 | 255 | 0 | -192 | 11 | 1 | 5 ];
+ output mat3x2 out0 = [ mat3x2(8.0, 1.0, -12.0, -192.0, -12.0, -66.0) | mat3x2(-192.0, 2.0, 11.0, 0.0, 5.0, -12.0) | mat3x2(2.0, -12.0, 2.0, -12.0, 0.0, 8.0) | mat3x2(11.0, 5.0, 1.0, 11.0, -66.0, 2.0) | mat3x2(255.0, 0.0, 8.0, 1.0, 255.0, 255.0) | mat3x2(-66.0, 255.0, -66.0, -66.0, 8.0, 0.0) | mat3x2(5.0, 8.0, -192.0, 8.0, -192.0, -192.0) | mat3x2(-12.0, 11.0, 5.0, 255.0, 11.0, 11.0) | mat3x2(1.0, -192.0, 255.0, 2.0, 2.0, 1.0) | mat3x2(0.0, -66.0, 0.0, 5.0, 1.0, 5.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool_bool_bool_bool_bool_to_mat3x2
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ input bool in1 = [ false | true ];
+ input bool in2 = [ false | true ];
+ input bool in3 = [ false | true ];
+ input bool in4 = [ false | true ];
+ input bool in5 = [ false | true ];
+ output mat3x2 out0 = [ mat3x2(1.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3x2(0.0, 1.0, 1.0, 1.0, 1.0, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_bool_float_int_to_mat3x2
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false | true | true | false | true | false | true | false | false ];
+ input float in1 = [ -20.125 | 0.0 | 3.5 | 0.0 | 1.0 | -8.25 | 1.0 | 2.0 | 36.8125 | -0.5 ];
+ input int in2 = [ 255 | -66 | 8 | -192 | 5 | 11 | 1 | 2 | 0 | -12 ];
+ input bool in3 = [ true | false | false | true | false | true | true | false | false | true ];
+ input float in4 = [ 0.0 | -20.125 | 1.0 | -8.25 | 0.0 | -0.5 | 2.0 | 3.5 | 1.0 | 36.8125 ];
+ input int in5 = [ -192 | 8 | 2 | 255 | -66 | -12 | 11 | 0 | 5 | 1 ];
+ output mat3x2 out0 = [ mat3x2(1.0, -20.125, 255.0, 1.0, 0.0, -192.0) | mat3x2(0.0, 0.0, -66.0, 0.0, -20.125, 8.0) | mat3x2(1.0, 3.5, 8.0, 0.0, 1.0, 2.0) | mat3x2(1.0, 0.0, -192.0, 1.0, -8.25, 255.0) | mat3x2(0.0, 1.0, 5.0, 0.0, 0.0, -66.0) | mat3x2(1.0, -8.25, 11.0, 1.0, -0.5, -12.0) | mat3x2(0.0, 1.0, 1.0, 1.0, 2.0, 11.0) | mat3x2(1.0, 2.0, 2.0, 0.0, 3.5, 0.0) | mat3x2(0.0, 36.8125, 0.0, 0.0, 1.0, 5.0) | mat3x2(0.0, -0.5, -12.0, 1.0, 36.8125, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_ivec3_to_mat3x2
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(-32.0, 64.0, -51.0) | vec3(-0.5, -2.25, -4.875) ];
+ input ivec3 in1 = [ ivec3(1, 1, 1) | ivec3(0, 0, 0) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output mat3x2 out0 = [ mat3x2(0.0, 0.5, 0.75, 1.0, 1.0, 1.0) | mat3x2(1.0, 1.25, 1.125, 0.0, 0.0, 0.0) | mat3x2(-0.75, -0.0322580645161, 0.0526315789474, 0.0, -2.0, -4.0) | mat3x2(-32.0, 64.0, -51.0, -32.0, 64.0, -51.0) | mat3x2(-0.5, -2.25, -4.875, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_bvec4_to_mat3x2
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(1.0, 1.25) ];
+ input bvec4 in1 = [ bvec4(true, true, true, true) | bvec4(false, false, false, true) | bvec4(false, false, false, false) | bvec4(true, false, false, true) | bvec4(false, true, false, false) ];
+ output mat3x2 out0 = [ mat3x2(0.0, 0.5, 1.0, 1.0, 1.0, 1.0) | mat3x2(-0.75, -0.0322580645161, 0.0, 0.0, 0.0, 1.0) | mat3x2(-32.0, 64.0, 0.0, 0.0, 0.0, 0.0) | mat3x2(-0.5, -2.25, 1.0, 0.0, 0.0, 1.0) | mat3x2(1.0, 1.25, 0.0, 1.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0, in1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec3_float_ivec2_to_mat3x2
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, false, false) | bvec3(false, true, false) | bvec3(true, false, false) ];
+ input float in1 = [ -8.25 | 1.0 | 2.0 | -0.5 | -20.125 | 0.0 | 36.8125 | 3.5 ];
+ input ivec2 in2 = [ ivec2(1, 1) | ivec2(1, 1) | ivec2(0, 0) | ivec2(0, -2) | ivec2(0, 0) | ivec2(0, 0) | ivec2(0, -2) | ivec2(-32, 64) ];
+ output mat3x2 out0 = [ mat3x2(0.0, 0.0, 0.0, -8.25, 1.0, 1.0) | mat3x2(1.0, 1.0, 1.0, 1.0, 1.0, 1.0) | mat3x2(0.0, 0.0, 0.0, 2.0, 0.0, 0.0) | mat3x2(0.0, 0.0, 0.0, -0.5, 0.0, -2.0) | mat3x2(0.0, 1.0, 0.0, -20.125, 0.0, 0.0) | mat3x2(1.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3x2(0.0, 1.0, 0.0, 36.8125, 0.0, -2.0) | mat3x2(1.0, 0.0, 0.0, 3.5, -32.0, 64.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_float_bvec2_to_mat3x2
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(1.0, 1.25, 1.125) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(0.0, 0.5, 0.75) | vec3(0.0, 0.5, 0.75) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ input float in1 = [ -8.25 | 36.8125 | -0.5 | 3.5 | 2.0 | -20.125 | 0.0 | 1.0 ];
+ input bvec2 in2 = [ bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) | bvec2(false, true) | bvec2(false, true) | bvec2(true, false) | bvec2(false, false) ];
+ output mat3x2 out0 = [ mat3x2(1.0, 1.25, 1.125, -8.25, 1.0, 0.0) | mat3x2(1.0, 1.25, 1.125, 36.8125, 0.0, 0.0) | mat3x2(-0.5, -2.25, -4.875, -0.5, 1.0, 1.0) | mat3x2(-0.5, -2.25, -4.875, 3.5, 0.0, 0.0) | mat3x2(-32.0, 64.0, -51.0, 2.0, 0.0, 1.0) | mat3x2(0.0, 0.5, 0.75, -20.125, 0.0, 1.0) | mat3x2(0.0, 0.5, 0.75, 0.0, 1.0, 0.0) | mat3x2(-0.75, -0.0322580645161, 0.0526315789474, 1.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x2(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_vec3_vec3_to_mat3
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(0.0, 0.5, 0.75) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ input vec3 in1 = [ vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(1.0, 1.25, 1.125) | vec3(-32.0, 64.0, -51.0) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) ];
+ input vec3 in2 = [ vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(-32.0, 64.0, -51.0) | vec3(-0.5, -2.25, -4.875) | vec3(1.0, 1.25, 1.125) | vec3(0.0, 0.5, 0.75) ];
+ output mat3 out0 = [ mat3(1.0, 1.25, 1.125, -0.75, -0.0322580645161, 0.0526315789474, -0.75, -0.0322580645161, 0.0526315789474) | mat3(-0.5, -2.25, -4.875, 1.0, 1.25, 1.125, -32.0, 64.0, -51.0) | mat3(-32.0, 64.0, -51.0, -32.0, 64.0, -51.0, -0.5, -2.25, -4.875) | mat3(0.0, 0.5, 0.75, -0.5, -2.25, -4.875, 1.0, 1.25, 1.125) | mat3(-0.75, -0.0322580645161, 0.0526315789474, 0.0, 0.5, 0.75, 0.0, 0.5, 0.75) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_ivec3_ivec3_to_mat3
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(0, 0, 0) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ input ivec3 in1 = [ ivec3(0, 0, 0) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) | ivec3(1, 1, 1) ];
+ input ivec3 in2 = [ ivec3(1, 1, 1) | ivec3(0, 0, 0) | ivec3(-32, 64, -51) | ivec3(0, -2, -4) | ivec3(0, 0, 0) ];
+ output mat3 out0 = [ mat3(1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0) | mat3(0.0, -2.0, -4.0, 0.0, -2.0, -4.0, 0.0, 0.0, 0.0) | mat3(0.0, 0.0, 0.0, -32.0, 64.0, -51.0, -32.0, 64.0, -51.0) | mat3(-32.0, 64.0, -51.0, 0.0, 0.0, 0.0, 0.0, -2.0, -4.0) | mat3(0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_float_float_int_bool_bool_to_mat3
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(0.0, 0.5) | vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) | vec2(-0.5, -2.25) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-32.0, 64.0) ];
+ input ivec2 in1 = [ ivec2(0, 0) | ivec2(0, -2) | ivec2(1, 1) | ivec2(0, -2) | ivec2(0, 0) | ivec2(0, 0) | ivec2(1, 1) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(-32, 64) ];
+ input float in2 = [ -0.5 | 3.5 | 0.0 | -20.125 | 1.0 | -8.25 | 0.0 | 1.0 | 2.0 | 36.8125 ];
+ input float in3 = [ 3.5 | 0.0 | -20.125 | 36.8125 | 2.0 | -8.25 | -0.5 | 1.0 | 0.0 | 1.0 ];
+ input int in4 = [ 0 | 11 | 5 | -192 | 8 | -66 | 1 | 2 | 255 | -12 ];
+ input bool in5 = [ true | true | true | false | true | false | false | false | true | false ];
+ input bool in6 = [ false | false | true | false | false | false | true | true | true | true ];
+ output mat3 out0 = [ mat3(1.0, 1.25, 0.0, 0.0, -0.5, 3.5, 0.0, 1.0, 0.0) | mat3(-0.5, -2.25, 0.0, -2.0, 3.5, 0.0, 11.0, 1.0, 0.0) | mat3(0.0, 0.5, 1.0, 1.0, 0.0, -20.125, 5.0, 1.0, 1.0) | mat3(-0.75, -0.0322580645161, 0.0, -2.0, -20.125, 36.8125, -192.0, 0.0, 0.0) | mat3(-32.0, 64.0, 0.0, 0.0, 1.0, 2.0, 8.0, 1.0, 0.0) | mat3(-0.75, -0.0322580645161, 0.0, 0.0, -8.25, -8.25, -66.0, 0.0, 0.0) | mat3(-0.5, -2.25, 1.0, 1.0, 0.0, -0.5, 1.0, 0.0, 1.0) | mat3(1.0, 1.25, -32.0, 64.0, 1.0, 1.0, 2.0, 0.0, 1.0) | mat3(0.0, 0.5, 0.0, 0.0, 2.0, 0.0, 255.0, 1.0, 1.0) | mat3(-32.0, 64.0, -32.0, 64.0, 36.8125, 1.0, -12.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0, in1, in2, in3, in4, in5, in6);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_vec2_bool_bvec2_float_to_mat3
+ version 310 es
+ values
+ {
+ input bool in0 = [ false | true | true | true | true | true | false | false | false | false ];
+ input float in1 = [ -8.25 | 1.0 | -0.5 | 36.8125 | 0.0 | 3.5 | -20.125 | 1.0 | 0.0 | 2.0 ];
+ input int in2 = [ 8 | -66 | 5 | 1 | 0 | 2 | -12 | -192 | 11 | 255 ];
+ input vec2 in3 = [ vec2(0.0, 0.5) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(-0.75, -0.0322580645161) | vec2(-0.5, -2.25) | vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) ];
+ input bool in4 = [ true | false | true | false | false | true | true | false | true | false ];
+ input bvec2 in5 = [ bvec2(false, true) | bvec2(false, false) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) | bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) ];
+ input float in6 = [ -0.5 | 1.0 | 1.0 | 0.0 | 36.8125 | 2.0 | 0.0 | 3.5 | -20.125 | -8.25 ];
+ output mat3 out0 = [ mat3(0.0, -8.25, 8.0, 0.0, 0.5, 1.0, 0.0, 1.0, -0.5) | mat3(1.0, 1.0, -66.0, -32.0, 64.0, 0.0, 0.0, 0.0, 1.0) | mat3(1.0, -0.5, 5.0, 1.0, 1.25, 1.0, 1.0, 0.0, 1.0) | mat3(1.0, 36.8125, 1.0, -32.0, 64.0, 0.0, 0.0, 0.0, 0.0) | mat3(1.0, 0.0, 0.0, -0.5, -2.25, 0.0, 1.0, 1.0, 36.8125) | mat3(1.0, 3.5, 2.0, -0.75, -0.0322580645161, 1.0, 0.0, 0.0, 2.0) | mat3(0.0, -20.125, -12.0, -0.5, -2.25, 1.0, 1.0, 0.0, 0.0) | mat3(0.0, 1.0, -192.0, 0.0, 0.5, 0.0, 0.0, 0.0, 3.5) | mat3(0.0, 0.0, 11.0, 1.0, 1.25, 1.0, 0.0, 1.0, -20.125) | mat3(0.0, 2.0, 255.0, -0.75, -0.0322580645161, 0.0, 1.0, 1.0, -8.25) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0, in1, in2, in3, in4, in5, in6);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bvec2_int_vec4_bool_to_mat3
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false | true | true | false | false | true | false | false | true ];
+ input bvec2 in1 = [ bvec2(false, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) | bvec2(true, true) | bvec2(false, false) | bvec2(false, true) | bvec2(true, false) | bvec2(true, false) | bvec2(false, false) ];
+ input int in2 = [ -192 | 2 | 0 | 5 | 1 | -66 | 11 | -12 | 8 | 255 ];
+ input vec4 in3 = [ vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ input bool in4 = [ false | true | false | true | false | false | false | true | true | true ];
+ output mat3 out0 = [ mat3(1.0, 0.0, 0.0, -192.0, -32.0, 64.0, -51.0, 24.0, 0.0) | mat3(0.0, 0.0, 1.0, 2.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25, 1.0) | mat3(1.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.75, 0.825, 0.0) | mat3(1.0, 1.0, 1.0, 5.0, -32.0, 64.0, -51.0, 24.0, 1.0) | mat3(0.0, 1.0, 1.0, 1.0, 1.0, 1.25, 1.125, 1.75, 0.0) | mat3(0.0, 0.0, 0.0, -66.0, 0.0, 0.5, 0.75, 0.825, 0.0) | mat3(1.0, 0.0, 1.0, 11.0, 1.0, 1.25, 1.125, 1.75, 0.0) | mat3(0.0, 1.0, 0.0, -12.0, -0.5, -2.25, -4.875, 9.0, 1.0) | mat3(0.0, 1.0, 0.0, 8.0, -0.5, -2.25, -4.875, 9.0, 1.0) | mat3(1.0, 0.0, 0.0, 255.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0, in1, in2, in3, in4);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_bvec4_ivec2_bool_bool_to_mat3
+ version 310 es
+ values
+ {
+ input float in0 = [ -8.25 | 2.0 | 36.8125 | 3.5 | 1.0 | -0.5 | -20.125 | 0.0 ];
+ input bvec4 in1 = [ bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, false, false, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, false, false, true) | bvec4(false, false, false, true) ];
+ input ivec2 in2 = [ ivec2(1, 1) | ivec2(0, -2) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, 0) | ivec2(0, -2) | ivec2(1, 1) ];
+ input bool in3 = [ false | true | false | true | true | false | true | false ];
+ input bool in4 = [ true | false | false | false | true | true | false | true ];
+ output mat3 out0 = [ mat3(-8.25, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0) | mat3(2.0, 0.0, 1.0, 0.0, 0.0, 0.0, -2.0, 1.0, 0.0) | mat3(36.8125, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat3(3.5, 1.0, 1.0, 1.0, 1.0, -32.0, 64.0, 1.0, 0.0) | mat3(1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0) | mat3(-0.5, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat3(-20.125, 1.0, 0.0, 0.0, 1.0, 0.0, -2.0, 1.0, 0.0) | mat3(0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3(in0, in1, in2, in3, in4);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_vec4_vec4_to_mat3x4
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(0.0, 0.5, 0.75, 0.825) ];
+ input vec4 in1 = [ vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(1.0, 1.25, 1.125, 1.75) ];
+ input vec4 in2 = [ vec4(-32.0, 64.0, -51.0, 24.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(0.0, 0.5, 0.75, 0.825) ];
+ output mat3x4 out0 = [ mat3x4(-0.75, -0.0322580645161, 0.0526315789474, 0.25, -0.75, -0.0322580645161, 0.0526315789474, 0.25, -32.0, 64.0, -51.0, 24.0) | mat3x4(1.0, 1.25, 1.125, 1.75, -0.5, -2.25, -4.875, 9.0, 1.0, 1.25, 1.125, 1.75) | mat3x4(-32.0, 64.0, -51.0, 24.0, 0.0, 0.5, 0.75, 0.825, -0.75, -0.0322580645161, 0.0526315789474, 0.25) | mat3x4(-0.5, -2.25, -4.875, 9.0, -32.0, 64.0, -51.0, 24.0, -0.5, -2.25, -4.875, 9.0) | mat3x4(0.0, 0.5, 0.75, 0.825, 1.0, 1.25, 1.125, 1.75, 0.0, 0.5, 0.75, 0.825) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_ivec4_ivec4_to_mat3x4
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, -2, -4, 9) | ivec4(0, 0, 0, 0) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) ];
+ input ivec4 in1 = [ ivec4(0, -2, -4, 9) | ivec4(0, 0, 0, 0) | ivec4(-32, 64, -51, 24) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) ];
+ input ivec4 in2 = [ ivec4(0, -2, -4, 9) | ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) | ivec4(-32, 64, -51, 24) ];
+ output mat3x4 out0 = [ mat3x4(0.0, -2.0, -4.0, 9.0, 0.0, -2.0, -4.0, 9.0, 0.0, -2.0, -4.0, 9.0) | mat3x4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3x4(-32.0, 64.0, -51.0, 24.0, -32.0, 64.0, -51.0, 24.0, 1.0, 1.0, 1.0, 1.0) | mat3x4(0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat3x4(1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, -32.0, 64.0, -51.0, 24.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_float_float_float_int_int_bool_bool_bool_to_mat3x4
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(0.0, 0.5) | vec2(-32.0, 64.0) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) | vec2(-0.5, -2.25) | vec2(-0.5, -2.25) ];
+ input ivec2 in1 = [ ivec2(0, 0) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) | ivec2(1, 1) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, -2) | ivec2(0, 0) | ivec2(0, -2) ];
+ input float in2 = [ 1.0 | -8.25 | 2.0 | 3.5 | -20.125 | 36.8125 | 0.0 | 1.0 | -0.5 | 0.0 ];
+ input float in3 = [ -0.5 | 36.8125 | 1.0 | 1.0 | 0.0 | 3.5 | 2.0 | 0.0 | -8.25 | -20.125 ];
+ input float in4 = [ -8.25 | 1.0 | 1.0 | 0.0 | 2.0 | 36.8125 | 0.0 | -20.125 | 3.5 | -0.5 ];
+ input int in5 = [ 11 | 2 | 8 | 5 | 0 | -192 | 1 | -12 | 255 | -66 ];
+ input int in6 = [ -12 | 5 | 8 | 1 | 0 | 255 | 11 | -192 | -66 | 2 ];
+ input bool in7 = [ true | true | true | false | false | false | true | false | true | false ];
+ input bool in8 = [ true | true | true | false | true | false | true | false | false | false ];
+ input bool in9 = [ true | false | true | false | true | true | false | false | false | true ];
+ output mat3x4 out0 = [ mat3x4(1.0, 1.25, 0.0, 0.0, 1.0, -0.5, -8.25, 11.0, -12.0, 1.0, 1.0, 1.0) | mat3x4(0.0, 0.5, 0.0, 0.0, -8.25, 36.8125, 1.0, 2.0, 5.0, 1.0, 1.0, 0.0) | mat3x4(0.0, 0.5, -32.0, 64.0, 2.0, 1.0, 1.0, 8.0, 8.0, 1.0, 1.0, 1.0) | mat3x4(-32.0, 64.0, 1.0, 1.0, 3.5, 1.0, 0.0, 5.0, 1.0, 0.0, 0.0, 0.0) | mat3x4(-32.0, 64.0, 1.0, 1.0, -20.125, 0.0, 2.0, 0.0, 0.0, 0.0, 1.0, 1.0) | mat3x4(-0.75, -0.0322580645161, -32.0, 64.0, 36.8125, 3.5, 36.8125, -192.0, 255.0, 0.0, 0.0, 1.0) | mat3x4(1.0, 1.25, 0.0, 0.0, 0.0, 2.0, 0.0, 1.0, 11.0, 1.0, 1.0, 0.0) | mat3x4(-0.75, -0.0322580645161, 0.0, -2.0, 1.0, 0.0, -20.125, -12.0, -192.0, 0.0, 0.0, 0.0) | mat3x4(-0.5, -2.25, 0.0, 0.0, -0.5, -8.25, 3.5, 255.0, -66.0, 1.0, 0.0, 0.0) | mat3x4(-0.5, -2.25, 0.0, -2.0, 0.0, -20.125, -0.5, -66.0, 2.0, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0, in1, in2, in3, in4, in5, in6, in7, in8, in9);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_vec3_bool_bvec3_float_bool_to_mat3x4
+ version 310 es
+ values
+ {
+ input bool in0 = [ false | false | true | true | true | true | false | false | false | true ];
+ input float in1 = [ 36.8125 | -8.25 | 1.0 | 0.0 | 0.0 | 1.0 | 2.0 | 3.5 | -0.5 | -20.125 ];
+ input int in2 = [ -66 | -192 | 255 | 8 | 0 | -12 | 5 | 2 | 11 | 1 ];
+ input vec3 in3 = [ vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(-32.0, 64.0, -51.0) | vec3(0.0, 0.5, 0.75) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(0.0, 0.5, 0.75) | vec3(-32.0, 64.0, -51.0) | vec3(1.0, 1.25, 1.125) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-0.5, -2.25, -4.875) ];
+ input bool in4 = [ false | true | true | true | false | false | true | true | false | false ];
+ input bvec3 in5 = [ bvec3(true, false, false) | bvec3(true, false, false) | bvec3(false, true, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, false, false) ];
+ input float in6 = [ -8.25 | 1.0 | -0.5 | 36.8125 | 0.0 | 2.0 | -20.125 | 1.0 | 0.0 | 3.5 ];
+ input bool in7 = [ true | false | false | true | true | false | true | false | false | true ];
+ output mat3x4 out0 = [ mat3x4(0.0, 36.8125, -66.0, -0.75, -0.0322580645161, 0.0526315789474, 0.0, 1.0, 0.0, 0.0, -8.25, 1.0) | mat3x4(0.0, -8.25, -192.0, -32.0, 64.0, -51.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(1.0, 1.0, 255.0, 0.0, 0.5, 0.75, 1.0, 0.0, 1.0, 0.0, -0.5, 0.0) | mat3x4(1.0, 0.0, 8.0, -0.75, -0.0322580645161, 0.0526315789474, 1.0, 0.0, 0.0, 0.0, 36.8125, 1.0) | mat3x4(1.0, 0.0, 0.0, 0.0, 0.5, 0.75, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0) | mat3x4(1.0, 1.0, -12.0, -32.0, 64.0, -51.0, 0.0, 1.0, 1.0, 1.0, 2.0, 0.0) | mat3x4(0.0, 2.0, 5.0, 1.0, 1.25, 1.125, 1.0, 1.0, 1.0, 1.0, -20.125, 1.0) | mat3x4(0.0, 3.5, 2.0, 1.0, 1.25, 1.125, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0) | mat3x4(0.0, -0.5, 11.0, -0.5, -2.25, -4.875, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat3x4(1.0, -20.125, 1.0, -0.5, -2.25, -4.875, 0.0, 0.0, 0.0, 0.0, 3.5, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0, in1, in2, in3, in4, in5, in6, in7);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bvec4_int_vec4_bool_float_to_mat3x4
+ version 310 es
+ values
+ {
+ input bool in0 = [ false | true | true | true | false | false | false | true | false | true ];
+ input bvec4 in1 = [ bvec4(false, false, false, false) | bvec4(true, false, false, true) | bvec4(false, true, false, false) | bvec4(false, false, false, true) | bvec4(true, true, true, true) | bvec4(false, false, false, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, false, false, true) ];
+ input int in2 = [ 255 | 2 | -192 | -12 | 11 | 1 | 0 | -66 | 8 | 5 ];
+ input vec4 in3 = [ vec4(-0.5, -2.25, -4.875, 9.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-0.5, -2.25, -4.875, 9.0) ];
+ input bool in4 = [ true | true | true | false | false | false | true | true | false | false ];
+ input float in5 = [ 36.8125 | 2.0 | -8.25 | 0.0 | 1.0 | 1.0 | -0.5 | 3.5 | 0.0 | -20.125 ];
+ output mat3x4 out0 = [ mat3x4(0.0, 0.0, 0.0, 0.0, 0.0, 255.0, -0.5, -2.25, -4.875, 9.0, 1.0, 36.8125) | mat3x4(1.0, 1.0, 0.0, 0.0, 1.0, 2.0, 1.0, 1.25, 1.125, 1.75, 1.0, 2.0) | mat3x4(1.0, 0.0, 1.0, 0.0, 0.0, -192.0, 1.0, 1.25, 1.125, 1.75, 1.0, -8.25) | mat3x4(1.0, 0.0, 0.0, 0.0, 1.0, -12.0, 0.0, 0.5, 0.75, 0.825, 0.0, 0.0) | mat3x4(0.0, 1.0, 1.0, 1.0, 1.0, 11.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25, 0.0, 1.0) | mat3x4(0.0, 0.0, 0.0, 0.0, 1.0, 1.0, -32.0, 64.0, -51.0, 24.0, 0.0, 1.0) | mat3x4(0.0, 1.0, 1.0, 1.0, 1.0, 0.0, -32.0, 64.0, -51.0, 24.0, 1.0, -0.5) | mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, -66.0, 0.0, 0.5, 0.75, 0.825, 1.0, 3.5) | mat3x4(0.0, 0.0, 1.0, 0.0, 0.0, 8.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25, 0.0, 0.0) | mat3x4(1.0, 1.0, 0.0, 0.0, 1.0, 5.0, -0.5, -2.25, -4.875, 9.0, 0.0, -20.125) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_bvec4_ivec4_bool_bool_int_to_mat3x4
+ version 310 es
+ values
+ {
+ input float in0 = [ 36.8125 | 1.0 | 0.0 | 3.5 | -8.25 | -20.125 | 2.0 | 0.0 | 1.0 | -0.5 ];
+ input bvec4 in1 = [ bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(false, false, false, true) | bvec4(true, true, true, true) | bvec4(true, false, false, true) | bvec4(true, false, false, true) | bvec4(false, true, false, false) | bvec4(false, false, false, true) | bvec4(false, false, false, false) ];
+ input ivec4 in2 = [ ivec4(0, 0, 0, 0) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, -2, -4, 9) | ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) ];
+ input bool in3 = [ true | false | true | true | false | true | true | false | false | false ];
+ input bool in4 = [ true | false | false | true | true | false | false | false | true | true ];
+ input int in5 = [ 1 | 5 | -12 | 8 | -192 | 2 | -66 | 255 | 11 | 0 ];
+ output mat3x4 out0 = [ mat3x4(36.8125, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0) | mat3x4(1.0, 0.0, 0.0, 0.0, 0.0, 0.0, -2.0, -4.0, 9.0, 0.0, 0.0, 5.0) | mat3x4(0.0, 0.0, 1.0, 0.0, 0.0, -32.0, 64.0, -51.0, 24.0, 1.0, 0.0, -12.0) | mat3x4(3.5, 0.0, 0.0, 0.0, 1.0, 0.0, -2.0, -4.0, 9.0, 1.0, 1.0, 8.0) | mat3x4(-8.25, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, -192.0) | mat3x4(-20.125, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 2.0) | mat3x4(2.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -66.0) | mat3x4(0.0, 0.0, 1.0, 0.0, 0.0, -32.0, 64.0, -51.0, 24.0, 0.0, 0.0, 255.0) | mat3x4(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 11.0) | mat3x4(-0.5, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat3x4(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec3_vec3_vec2_to_mat4x2
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(1.0, 1.25, 1.125) | vec3(-32.0, 64.0, -51.0) | vec3(0.0, 0.5, 0.75) | vec3(-0.5, -2.25, -4.875) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ input vec3 in1 = [ vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(-0.5, -2.25, -4.875) | vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) ];
+ input vec2 in2 = [ vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(0.0, 0.5) ];
+ output mat4x2 out0 = [ mat4x2(1.0, 1.25, 1.125, -32.0, 64.0, -51.0, 1.0, 1.25) | mat4x2(-32.0, 64.0, -51.0, -0.75, -0.0322580645161, 0.0526315789474, -0.5, -2.25) | mat4x2(0.0, 0.5, 0.75, -0.5, -2.25, -4.875, -0.75, -0.0322580645161) | mat4x2(-0.5, -2.25, -4.875, 0.0, 0.5, 0.75, -32.0, 64.0) | mat4x2(-0.75, -0.0322580645161, 0.0526315789474, 1.0, 1.25, 1.125, 0.0, 0.5) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3_ivec3_ivec2_to_mat4x2
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(0, 0, 0) | ivec3(-32, 64, -51) ];
+ input ivec3 in1 = [ ivec3(0, -2, -4) | ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, 0, 0) | ivec3(-32, 64, -51) ];
+ input ivec2 in2 = [ ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) ];
+ output mat4x2 out0 = [ mat4x2(0.0, 0.0, 0.0, 0.0, -2.0, -4.0, -32.0, 64.0) | mat4x2(1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0) | mat4x2(0.0, -2.0, -4.0, 1.0, 1.0, 1.0, 0.0, 0.0) | mat4x2(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0) | mat4x2(-32.0, 64.0, -51.0, -32.0, 64.0, -51.0, 0.0, -2.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_float_float_int_bool_to_mat4x2
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(-0.5, -2.25) | vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(0.0, 0.5) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) | vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(-0.5, -2.25) | vec2(1.0, 1.25) ];
+ input ivec2 in1 = [ ivec2(0, -2) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(1, 1) | ivec2(1, 1) | ivec2(0, 0) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, 0) | ivec2(0, -2) ];
+ input float in2 = [ 3.5 | -8.25 | 2.0 | 36.8125 | -0.5 | 1.0 | 1.0 | 0.0 | -20.125 | 0.0 ];
+ input float in3 = [ 0.0 | 36.8125 | 3.5 | 1.0 | -0.5 | -8.25 | 2.0 | 0.0 | -20.125 | 1.0 ];
+ input int in4 = [ -12 | -66 | 11 | 5 | 8 | 255 | -192 | 2 | 1 | 0 ];
+ input bool in5 = [ true | true | false | true | false | true | false | true | false | false ];
+ output mat4x2 out0 = [ mat4x2(-0.5, -2.25, 0.0, -2.0, 3.5, 0.0, -12.0, 1.0) | mat4x2(0.0, 0.5, 0.0, 0.0, -8.25, 36.8125, -66.0, 1.0) | mat4x2(1.0, 1.25, -32.0, 64.0, 2.0, 3.5, 11.0, 0.0) | mat4x2(0.0, 0.5, 1.0, 1.0, 36.8125, 1.0, 5.0, 1.0) | mat4x2(-32.0, 64.0, 1.0, 1.0, -0.5, -0.5, 8.0, 0.0) | mat4x2(-0.75, -0.0322580645161, 0.0, 0.0, 1.0, -8.25, 255.0, 1.0) | mat4x2(-0.75, -0.0322580645161, -32.0, 64.0, 1.0, 2.0, -192.0, 0.0) | mat4x2(-32.0, 64.0, 0.0, 0.0, 0.0, 0.0, 2.0, 1.0) | mat4x2(-0.5, -2.25, 0.0, 0.0, -20.125, -20.125, 1.0, 0.0) | mat4x2(1.0, 1.25, 0.0, -2.0, 0.0, 1.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_vec2_bool_bvec2_to_mat4x2
+ version 310 es
+ values
+ {
+ input bool in0 = [ false | false | true | true | true | false | false | true | false | true ];
+ input float in1 = [ 36.8125 | -8.25 | 3.5 | 1.0 | 2.0 | -0.5 | 0.0 | 1.0 | -20.125 | 0.0 ];
+ input int in2 = [ -66 | 1 | -192 | 2 | 11 | 0 | 255 | 8 | 5 | -12 ];
+ input vec2 in3 = [ vec2(-0.75, -0.0322580645161) | vec2(-0.75, -0.0322580645161) | vec2(-32.0, 64.0) | vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(0.0, 0.5) | vec2(-0.5, -2.25) ];
+ input bool in4 = [ true | false | false | false | false | true | true | true | false | true ];
+ input bvec2 in5 = [ bvec2(false, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) | bvec2(true, false) ];
+ output mat4x2 out0 = [ mat4x2(0.0, 36.8125, -66.0, -0.75, -0.0322580645161, 1.0, 0.0, 0.0) | mat4x2(0.0, -8.25, 1.0, -0.75, -0.0322580645161, 0.0, 0.0, 1.0) | mat4x2(1.0, 3.5, -192.0, -32.0, 64.0, 0.0, 0.0, 0.0) | mat4x2(1.0, 1.0, 2.0, 0.0, 0.5, 0.0, 1.0, 1.0) | mat4x2(1.0, 2.0, 11.0, 1.0, 1.25, 0.0, 1.0, 0.0) | mat4x2(0.0, -0.5, 0.0, 1.0, 1.25, 1.0, 0.0, 1.0) | mat4x2(0.0, 0.0, 255.0, -0.5, -2.25, 1.0, 0.0, 0.0) | mat4x2(1.0, 1.0, 8.0, -32.0, 64.0, 1.0, 1.0, 1.0) | mat4x2(0.0, -20.125, 5.0, 0.0, 0.5, 0.0, 0.0, 0.0) | mat4x2(1.0, 0.0, -12.0, -0.5, -2.25, 1.0, 1.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bvec2_int_vec4_to_mat4x2
+ version 310 es
+ values
+ {
+ input bool in0 = [ false | false | true | false | true | false | true | true | true | false ];
+ input bvec2 in1 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, false) | bvec2(false, true) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(true, true) ];
+ input int in2 = [ -12 | 8 | 2 | 255 | 5 | -192 | 0 | 11 | 1 | -66 ];
+ input vec4 in3 = [ vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.0, 0.5, 0.75, 0.825) ];
+ output mat4x2 out0 = [ mat4x2(0.0, 1.0, 0.0, -12.0, 1.0, 1.25, 1.125, 1.75) | mat4x2(0.0, 0.0, 0.0, 8.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25) | mat4x2(1.0, 0.0, 0.0, 2.0, -32.0, 64.0, -51.0, 24.0) | mat4x2(0.0, 0.0, 0.0, 255.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25) | mat4x2(1.0, 1.0, 0.0, 5.0, -0.5, -2.25, -4.875, 9.0) | mat4x2(0.0, 0.0, 1.0, -192.0, -0.5, -2.25, -4.875, 9.0) | mat4x2(1.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.75, 0.825) | mat4x2(1.0, 0.0, 1.0, 11.0, -32.0, 64.0, -51.0, 24.0) | mat4x2(1.0, 1.0, 1.0, 1.0, 1.0, 1.25, 1.125, 1.75) | mat4x2(0.0, 1.0, 1.0, -66.0, 0.0, 0.5, 0.75, 0.825) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_bvec4_ivec2_bool_to_mat4x2
+ version 310 es
+ values
+ {
+ input float in0 = [ 1.0 | -8.25 | -20.125 | 3.5 | -0.5 | 2.0 | 36.8125 | 0.0 ];
+ input bvec4 in1 = [ bvec4(false, false, false, true) | bvec4(true, false, false, true) | bvec4(true, true, true, true) | bvec4(false, true, false, false) | bvec4(false, false, false, false) | bvec4(true, false, false, true) | bvec4(false, true, false, false) | bvec4(false, false, false, true) ];
+ input ivec2 in2 = [ ivec2(-32, 64) | ivec2(0, -2) | ivec2(0, 0) | ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(1, 1) | ivec2(0, 0) ];
+ input bool in3 = [ true | true | false | true | true | false | false | false ];
+ output mat4x2 out0 = [ mat4x2(1.0, 0.0, 0.0, 0.0, 1.0, -32.0, 64.0, 1.0) | mat4x2(-8.25, 1.0, 0.0, 0.0, 1.0, 0.0, -2.0, 1.0) | mat4x2(-20.125, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0) | mat4x2(3.5, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4x2(-0.5, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0) | mat4x2(2.0, 1.0, 0.0, 0.0, 1.0, 0.0, -2.0, 0.0) | mat4x2(36.8125, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0) | mat4x2(0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x2(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_vec4_vec4_to_mat4x3
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(-0.5, -2.25, -4.875, 9.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-32.0, 64.0, -51.0, 24.0) ];
+ input vec4 in1 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ input vec4 in2 = [ vec4(-32.0, 64.0, -51.0, 24.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output mat4x3 out0 = [ mat4x3(-0.5, -2.25, -4.875, 9.0, 0.0, 0.5, 0.75, 0.825, -32.0, 64.0, -51.0, 24.0) | mat4x3(1.0, 1.25, 1.125, 1.75, -0.5, -2.25, -4.875, 9.0, 1.0, 1.25, 1.125, 1.75) | mat4x3(0.0, 0.5, 0.75, 0.825, -32.0, 64.0, -51.0, 24.0, -0.5, -2.25, -4.875, 9.0) | mat4x3(-0.75, -0.0322580645161, 0.0526315789474, 0.25, 1.0, 1.25, 1.125, 1.75, 0.0, 0.5, 0.75, 0.825) | mat4x3(-32.0, 64.0, -51.0, 24.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25, -0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_ivec4_ivec4_to_mat4x3
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ input ivec4 in1 = [ ivec4(0, 0, 0, 0) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) | ivec4(0, -2, -4, 9) | ivec4(1, 1, 1, 1) ];
+ input ivec4 in2 = [ ivec4(-32, 64, -51, 24) | ivec4(0, -2, -4, 9) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) | ivec4(0, 0, 0, 0) ];
+ output mat4x3 out0 = [ mat4x3(1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, -32.0, 64.0, -51.0, 24.0) | mat4x3(0.0, 0.0, 0.0, 0.0, -32.0, 64.0, -51.0, 24.0, 0.0, -2.0, -4.0, 9.0) | mat4x3(0.0, -2.0, -4.0, 9.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0) | mat4x3(-32.0, 64.0, -51.0, 24.0, 0.0, -2.0, -4.0, 9.0, 0.0, 0.0, 0.0, 0.0) | mat4x3(0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0, in1, in2);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec2_ivec2_float_float_float_int_int_bool_bool_bool_to_mat4x3
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(-0.5, -2.25) | vec2(0.0, 0.5) | vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.75, -0.0322580645161) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(1.0, 1.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ input ivec2 in1 = [ ivec2(0, -2) | ivec2(-32, 64) | ivec2(1, 1) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, 0) | ivec2(0, 0) | ivec2(0, -2) | ivec2(0, 0) | ivec2(1, 1) ];
+ input float in2 = [ -20.125 | 3.5 | 2.0 | -0.5 | -8.25 | 0.0 | 1.0 | 0.0 | 1.0 | 36.8125 ];
+ input float in3 = [ 0.0 | -8.25 | 36.8125 | 1.0 | 0.0 | -20.125 | 3.5 | 2.0 | -0.5 | 1.0 ];
+ input float in4 = [ 0.0 | 1.0 | 3.5 | -20.125 | 0.0 | 36.8125 | 1.0 | -8.25 | 2.0 | -0.5 ];
+ input int in5 = [ 2 | 8 | 1 | -192 | 0 | -12 | 11 | 255 | 5 | -66 ];
+ input int in6 = [ 2 | -12 | 5 | 8 | 11 | 255 | 0 | -66 | 1 | -192 ];
+ input bool in7 = [ true | true | false | true | false | false | false | true | false | true ];
+ input bool in8 = [ true | false | false | true | true | false | true | true | false | false ];
+ input bool in9 = [ false | true | false | false | false | false | true | true | true | true ];
+ output mat4x3 out0 = [ mat4x3(-0.5, -2.25, 0.0, -2.0, -20.125, 0.0, 0.0, 2.0, 2.0, 1.0, 1.0, 0.0) | mat4x3(0.0, 0.5, -32.0, 64.0, 3.5, -8.25, 1.0, 8.0, -12.0, 1.0, 0.0, 1.0) | mat4x3(0.0, 0.5, 1.0, 1.0, 2.0, 36.8125, 3.5, 1.0, 5.0, 0.0, 0.0, 0.0) | mat4x3(1.0, 1.25, -32.0, 64.0, -0.5, 1.0, -20.125, -192.0, 8.0, 1.0, 1.0, 0.0) | mat4x3(-0.75, -0.0322580645161, 0.0, 0.0, -8.25, 0.0, 0.0, 0.0, 11.0, 0.0, 1.0, 0.0) | mat4x3(-0.5, -2.25, 0.0, 0.0, 0.0, -20.125, 36.8125, -12.0, 255.0, 0.0, 0.0, 0.0) | mat4x3(-32.0, 64.0, 0.0, 0.0, 1.0, 3.5, 1.0, 11.0, 0.0, 0.0, 1.0, 1.0) | mat4x3(1.0, 1.25, 0.0, -2.0, 0.0, 2.0, -8.25, 255.0, -66.0, 1.0, 1.0, 1.0) | mat4x3(-32.0, 64.0, 0.0, 0.0, 1.0, -0.5, 2.0, 5.0, 1.0, 0.0, 0.0, 1.0) | mat4x3(-0.75, -0.0322580645161, 1.0, 1.0, 36.8125, 1.0, -0.5, -66.0, -192.0, 1.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0, in1, in2, in3, in4, in5, in6, in7, in8, in9);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_float_int_vec3_bool_bvec3_float_bool_to_mat4x3
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | true | false | false | true | true | true | false | false | false ];
+ input float in1 = [ -8.25 | 2.0 | 1.0 | -0.5 | 0.0 | 0.0 | 36.8125 | -20.125 | 3.5 | 1.0 ];
+ input int in2 = [ 255 | 2 | 11 | 1 | 8 | -192 | 0 | -66 | -12 | 5 ];
+ input vec3 in3 = [ vec3(-0.75, -0.0322580645161, 0.0526315789474) | vec3(0.0, 0.5, 0.75) | vec3(0.0, 0.5, 0.75) | vec3(-32.0, 64.0, -51.0) | vec3(-0.5, -2.25, -4.875) | vec3(1.0, 1.25, 1.125) | vec3(-32.0, 64.0, -51.0) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ input bool in4 = [ true | true | false | false | true | false | false | false | true | true ];
+ input bvec3 in5 = [ bvec3(false, false, false) | bvec3(false, true, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, false, false) | bvec3(true, false, false) | bvec3(true, true, true) | bvec3(true, true, true) | bvec3(false, false, false) | bvec3(false, false, false) ];
+ input float in6 = [ 1.0 | 0.0 | -0.5 | 36.8125 | 1.0 | -20.125 | 2.0 | 0.0 | -8.25 | 3.5 ];
+ input bool in7 = [ true | true | false | false | false | false | true | true | false | true ];
+ output mat4x3 out0 = [ mat4x3(1.0, -8.25, 255.0, -0.75, -0.0322580645161, 0.0526315789474, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0) | mat4x3(1.0, 2.0, 2.0, 0.0, 0.5, 0.75, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0) | mat4x3(0.0, 1.0, 11.0, 0.0, 0.5, 0.75, 0.0, 0.0, 0.0, 0.0, -0.5, 0.0) | mat4x3(0.0, -0.5, 1.0, -32.0, 64.0, -51.0, 0.0, 0.0, 1.0, 0.0, 36.8125, 0.0) | mat4x3(1.0, 0.0, 8.0, -0.5, -2.25, -4.875, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0) | mat4x3(1.0, 0.0, -192.0, 1.0, 1.25, 1.125, 0.0, 1.0, 0.0, 0.0, -20.125, 0.0) | mat4x3(1.0, 36.8125, 0.0, -32.0, 64.0, -51.0, 0.0, 1.0, 1.0, 1.0, 2.0, 1.0) | mat4x3(0.0, -20.125, -66.0, 1.0, 1.25, 1.125, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0) | mat4x3(0.0, 3.5, -12.0, -0.5, -2.25, -4.875, 1.0, 0.0, 0.0, 0.0, -8.25, 0.0) | mat4x3(0.0, 1.0, 5.0, -0.75, -0.0322580645161, 0.0526315789474, 1.0, 0.0, 0.0, 0.0, 3.5, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0, in1, in2, in3, in4, in5, in6, in7);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bvec4_int_vec4_bool_float_to_mat4x3
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | true | true | false | true | false | false | true | false | false ];
+ input bvec4 in1 = [ bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(true, false, false, true) | bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, false, false, false) | bvec4(false, false, false, true) ];
+ input int in2 = [ 5 | 11 | 0 | -192 | -66 | 255 | 1 | -12 | 8 | 2 ];
+ input vec4 in3 = [ vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(0.0, 0.5, 0.75, 0.825) ];
+ input bool in4 = [ false | true | true | false | true | false | true | true | false | false ];
+ input float in5 = [ -20.125 | 0.0 | 1.0 | -0.5 | 3.5 | -8.25 | 0.0 | 1.0 | 2.0 | 36.8125 ];
+ output mat4x3 out0 = [ mat4x3(1.0, 0.0, 0.0, 0.0, 0.0, 5.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25, 0.0, -20.125) | mat4x3(1.0, 0.0, 1.0, 0.0, 0.0, 11.0, -32.0, 64.0, -51.0, 24.0, 1.0, 0.0) | mat4x3(1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.25, 1.125, 1.75, 1.0, 1.0) | mat4x3(0.0, 1.0, 1.0, 1.0, 1.0, -192.0, -0.5, -2.25, -4.875, 9.0, 0.0, -0.5) | mat4x3(1.0, 1.0, 1.0, 1.0, 1.0, -66.0, 1.0, 1.25, 1.125, 1.75, 1.0, 3.5) | mat4x3(0.0, 1.0, 0.0, 0.0, 1.0, 255.0, -32.0, 64.0, -51.0, 24.0, 0.0, -8.25) | mat4x3(0.0, 1.0, 0.0, 0.0, 1.0, 1.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25, 1.0, 0.0) | mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, -12.0, -0.5, -2.25, -4.875, 9.0, 1.0, 1.0) | mat4x3(0.0, 0.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.5, 0.75, 0.825, 0.0, 2.0) | mat4x3(0.0, 0.0, 0.0, 0.0, 1.0, 2.0, 0.0, 0.5, 0.75, 0.825, 0.0, 36.8125) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_bvec4_ivec4_bool_bool_int_to_mat4x3
+ version 310 es
+ values
+ {
+ input float in0 = [ 36.8125 | -0.5 | 3.5 | 2.0 | 1.0 | -20.125 | 0.0 | 0.0 | -8.25 | 1.0 ];
+ input bvec4 in1 = [ bvec4(false, false, false, false) | bvec4(false, false, false, true) | bvec4(true, false, false, true) | bvec4(false, true, false, false) | bvec4(false, false, false, false) | bvec4(true, false, false, true) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, true, false, false) | bvec4(false, false, false, true) ];
+ input ivec4 in2 = [ ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) | ivec4(0, 0, 0, 0) | ivec4(0, 0, 0, 0) | ivec4(-32, 64, -51, 24) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(0, -2, -4, 9) ];
+ input bool in3 = [ false | true | false | true | false | false | false | true | true | true ];
+ input bool in4 = [ false | true | false | true | false | true | false | false | true | true ];
+ input int in5 = [ 2 | 1 | 8 | 11 | 255 | 5 | 0 | -66 | -192 | -12 ];
+ output mat4x3 out0 = [ mat4x3(36.8125, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 2.0) | mat4x3(-0.5, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0) | mat4x3(3.5, 1.0, 0.0, 0.0, 1.0, -32.0, 64.0, -51.0, 24.0, 0.0, 0.0, 8.0) | mat4x3(2.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 11.0) | mat4x3(1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 255.0) | mat4x3(-20.125, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 5.0) | mat4x3(0.0, 1.0, 1.0, 1.0, 1.0, -32.0, 64.0, -51.0, 24.0, 0.0, 0.0, 0.0) | mat4x3(0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, -66.0) | mat4x3(-8.25, 0.0, 1.0, 0.0, 0.0, 0.0, -2.0, -4.0, 9.0, 1.0, 1.0, -192.0) | mat4x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, -2.0, -4.0, 9.0, 1.0, 1.0, -12.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4x3(in0, in1, in2, in3, in4, in5);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case vec4_vec4_vec4_vec4_to_mat4
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.0, 0.5, 0.75, 0.825) ];
+ input vec4 in1 = [ vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.0, 0.5, 0.75, 0.825) ];
+ input vec4 in2 = [ vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.0, 0.5, 0.75, 0.825) ];
+ input vec4 in3 = [ vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(-0.5, -2.25, -4.875, 9.0) ];
+ output mat4 out0 = [ mat4(-0.75, -0.0322580645161, 0.0526315789474, 0.25, -0.75, -0.0322580645161, 0.0526315789474, 0.25, -32.0, 64.0, -51.0, 24.0, -32.0, 64.0, -51.0, 24.0) | mat4(-32.0, 64.0, -51.0, 24.0, -32.0, 64.0, -51.0, 24.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25, -0.75, -0.0322580645161, 0.0526315789474, 0.25) | mat4(-0.5, -2.25, -4.875, 9.0, -0.5, -2.25, -4.875, 9.0, -0.5, -2.25, -4.875, 9.0, 1.0, 1.25, 1.125, 1.75) | mat4(1.0, 1.25, 1.125, 1.75, 1.0, 1.25, 1.125, 1.75, 1.0, 1.25, 1.125, 1.75, 0.0, 0.5, 0.75, 0.825) | mat4(0.0, 0.5, 0.75, 0.825, 0.0, 0.5, 0.75, 0.825, 0.0, 0.5, 0.75, 0.825, -0.5, -2.25, -4.875, 9.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4_ivec4_ivec4_ivec4_to_mat4
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(-32, 64, -51, 24) | ivec4(0, -2, -4, 9) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) | ivec4(0, 0, 0, 0) ];
+ input ivec4 in1 = [ ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(0, 0, 0, 0) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ input ivec4 in2 = [ ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) | ivec4(0, -2, -4, 9) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) ];
+ input ivec4 in3 = [ ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(0, 0, 0, 0) | ivec4(0, 0, 0, 0) | ivec4(-32, 64, -51, 24) ];
+ output mat4 out0 = [ mat4(-32.0, 64.0, -51.0, 24.0, 1.0, 1.0, 1.0, 1.0, -32.0, 64.0, -51.0, 24.0, 1.0, 1.0, 1.0, 1.0) | mat4(0.0, -2.0, -4.0, 9.0, 0.0, -2.0, -4.0, 9.0, 0.0, 0.0, 0.0, 0.0, 0.0, -2.0, -4.0, 9.0) | mat4(1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, -2.0, -4.0, 9.0, 0.0, 0.0, 0.0, 0.0) | mat4(0.0, 0.0, 0.0, 0.0, -32.0, 64.0, -51.0, 24.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -32.0, 64.0, -51.0, 24.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bvec4_bvec4_bvec4_bvec4_to_mat4
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(false, false, false, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(true, false, false, true) ];
+ input bvec4 in1 = [ bvec4(false, true, false, false) | bvec4(false, false, false, true) | bvec4(true, false, false, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ input bvec4 in2 = [ bvec4(false, true, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, true) | bvec4(true, false, false, true) ];
+ input bvec4 in3 = [ bvec4(true, true, true, true) | bvec4(false, false, false, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, false, false, true) ];
+ output mat4 out0 = [ mat4(0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0) | mat4(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0) | mat4(0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0) | mat4(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0) | mat4(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0, in1, in2, in3);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_ivec3_bvec3_vec4_ivec2_float_vec2_to_mat4
+ version 310 es
+ values
+ {
+ input float in0 = [ 2.0 | 1.0 | 3.5 | 0.0 | -20.125 | 36.8125 | -0.5 | -8.25 ];
+ input ivec3 in1 = [ ivec3(0, 0, 0) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(0, 0, 0) | ivec3(0, -2, -4) ];
+ input bvec3 in2 = [ bvec3(true, false, false) | bvec3(true, true, true) | bvec3(false, false, false) | bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(false, false, false) | bvec3(false, true, false) ];
+ input vec4 in3 = [ vec4(-0.5, -2.25, -4.875, 9.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(0.0, 0.5, 0.75, 0.825) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(0.0, 0.5, 0.75, 0.825) ];
+ input ivec2 in4 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(0, 0) | ivec2(1, 1) | ivec2(-32, 64) | ivec2(0, 0) | ivec2(0, -2) ];
+ input float in5 = [ 2.0 | 3.5 | 36.8125 | -8.25 | 0.0 | -20.125 | 1.0 | -0.5 ];
+ input vec2 in6 = [ vec2(0.0, 0.5) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(0.0, 0.5) | vec2(-0.75, -0.0322580645161) | vec2(-0.5, -2.25) | vec2(1.0, 1.25) | vec2(1.0, 1.25) ];
+ output mat4 out0 = [ mat4(2.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, -0.5, -2.25, -4.875, 9.0, 0.0, 0.0, 2.0, 0.0, 0.5) | mat4(1.0, -32.0, 64.0, -51.0, 1.0, 1.0, 1.0, 1.0, 1.25, 1.125, 1.75, 1.0, 1.0, 3.5, -0.5, -2.25) | mat4(3.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.75, 0.825, 0.0, -2.0, 36.8125, -32.0, 64.0) | mat4(0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, -0.5, -2.25, -4.875, 9.0, 0.0, 0.0, -8.25, 0.0, 0.5) | mat4(-20.125, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.25, 1.125, 1.75, 1.0, 1.0, 0.0, -0.75, -0.0322580645161) | mat4(36.8125, 0.0, -2.0, -4.0, 0.0, 1.0, 0.0, -0.75, -0.0322580645161, 0.0526315789474, 0.25, -32.0, 64.0, -20.125, -0.5, -2.25) | mat4(-0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -32.0, 64.0, -51.0, 24.0, 0.0, 0.0, 1.0, 1.0, 1.25) | mat4(-8.25, 0.0, -2.0, -4.0, 0.0, 1.0, 0.0, 0.0, 0.5, 0.75, 0.825, 0.0, -2.0, -0.5, 1.0, 1.25) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = mat4(in0, in1, in2, in3, in4, in5, in6);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # matrix_combine
--- /dev/null
+# Tests todo:
+# - inout with varyings, attributes, uniforms (and arrays of 'em)
+# - inout with arrays, array elements
+# - inout with array elements
+# - inout by-value semantics (arrays & elements & structs)
+
+# Done:
+# - control flow: return, return in loop, etc.
+
+group datatypes "Function Parameter Data Types"
+
+ case float_float
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ return -a;
+ }
+
+ void main()
+ {
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_vec2
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 1.0) | vec2(2.0, 2.5) ];
+ output float out0 = [ -1.0 | -4.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (vec2 a)
+ {
+ return -(a.x + a.y);
+ }
+
+ void main()
+ {
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_vec3
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 1.0, -2.0) | vec3(2.0, 2.5, -4.0) ];
+ output float out0 = [ 1.0 | -0.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (vec3 a)
+ {
+ return -(a.x + a.y + a.z);
+ }
+
+ void main()
+ {
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_vec4
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 1.0, -2.0, 0.5) | vec4(2.0, 2.5, 4.0, -7.0) ];
+ output float out0 = [ 0.5 | -1.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (vec4 a)
+ {
+ return -(a.x + a.y + a.z + a.w);
+ }
+
+ void main()
+ {
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_mat2
+ version 310 es
+ values
+ {
+ input mat2 in0 = [ mat2(0.0, 1.0, -2.0, 0.5) | mat2(2.0, 2.5, 4.0, -7.0) ];
+ output float out0 = [ 0.5 | -1.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (mat2 a)
+ {
+ return -(a[0][0] + a[0][1] + a[1][0] + a[1][1]);
+ }
+
+ void main()
+ {
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_mat3
+ version 310 es
+ values
+ {
+ input mat3 in0 = [ mat3(0.0, 1.0, -2.0, 0.5, 1.0, -1.0, 2.0, 4.0, -1.0) | mat3(2.0, 2.5, 4.0, -7.0, 2.5, 3.0, 0.5, -3.5, 1.0) ];
+ output float out0 = [ -4.5 | -5.0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (mat3 a)
+ {
+ return -(a[0][0] + a[0][1] + a[0][2] + a[1][0] + a[1][1] + a[1][2] + a[2][0] + a[2][1] + a[2][2]);
+ }
+
+ void main()
+ {
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_mat4
+ version 310 es
+ values
+ {
+ input mat4 in0 = [ mat4(0.0, 1.0, -2.0, 0.5, 1.0, -1.0, 2.0, 4.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -2.0, -2.0) | mat4(2.0, 2.5, 4.0, -7.0, 2.5, 3.0, 0.5, -3.5, 1.0, 0.0, 2.0, -1.0, 1.0, 0.0, -1.0, 3.0) ];
+ output float out0 = [ -5.5 | -9.0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (mat4 a)
+ {
+ return -(a[0][0] + a[0][1] + a[0][2] + a[0][3] + a[1][0] + a[1][1] + a[1][2] + a[1][3] + a[2][0] + a[2][1] + a[2][2] + a[2][3] + a[3][0] + a[3][1] + a[3][2] + a[3][3]);
+ }
+
+ void main()
+ {
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_int
+ version 310 es
+ values
+ {
+ input int in0 = [ -1 | 0 | 1 | 4 ];
+ output int out0 = [ 1 | 0 | -1 | -4 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (int a)
+ {
+ return -a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_ivec2
+ version 310 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(-1, 0) | ivec2(1, 4) ];
+ output int out0 = [ 1 | -5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (ivec2 a)
+ {
+ return -(a.x + a.y);
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_ivec3
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(-1, 0, 2) | ivec3(1, 4, -8) ];
+ output int out0 = [ -1 | 3 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (ivec3 a)
+ {
+ return -(a.x + a.y + a.z);
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case int_ivec4
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(-1, 0, 2, 2) | ivec4(1, 4, -8, 2) ];
+ output int out0 = [ -3 | 1 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (ivec4 a)
+ {
+ return -(a.x + a.y + a.z + a.w);
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uint
+ version 310 es
+ values
+ {
+ input uint in0 = [ 1 | 0 | 2 | 4 ];
+ output uint out0 = [ 1 | 0 | 4 | 16 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ uint func (uint a)
+ {
+ return a*a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uvec2
+ version 310 es
+ values
+ {
+ input uvec2 in0 = [ uvec2(1, 0) | uvec2(2, 4) ];
+ output uint out0 = [ 1 | 6 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ uint func (uvec2 a)
+ {
+ return (a.x + a.y);
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uvec3
+ version 310 es
+ values
+ {
+ input uvec3 in0 = [ uvec3(1, 0, 2) | uvec3(1, 4, 8) ];
+ output uint out0 = [ 3 | 13 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ uint func (uvec3 a)
+ {
+ return (a.x + a.y + a.z);
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case uint_uvec4
+ version 310 es
+ values
+ {
+ input uvec4 in0 = [ uvec4(1, 0, 2, 2) | uvec4(1, 4, 8, 2) ];
+ output uint out0 = [ 5 | 15 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ uint func (uvec4 a)
+ {
+ return (a.x + a.y + a.z + a.w);
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bool
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output bool out0 = [ false | true ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ bool func (bool a)
+ {
+ return !a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bvec2
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, true) | bvec2(false, true) ];
+ output bool out0 = [ false | true ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ bool func (bvec2 a)
+ {
+ return !(a.x == a.y);
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bvec3
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, true, false) | bvec3(true, false, false) ];
+ output bool out0 = [ false | true ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ bool func (bvec3 a)
+ {
+ return (a.x == a.y) == a.z;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case bool_bvec4
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, true, true, false) | bvec4(false, false, true, true) | bvec4(true, false, false, true) ];
+ output bool out0 = [ false | true | true ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ bool func (bvec4 a)
+ {
+ return ((a.x == a.y) == (a.z == a.w));
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mat2
+ version 310 es
+ values
+ {
+ input mat2 in0 = [ mat2(-2.0, 0.5, -1.0, 1.0) | mat2(1.0, -3.5, -3.5, 2.5) | mat2(-2.0, -2.0, 3.5, 0.0) ];
+ output mat2 out0 = [ mat2(4.0, -1.0, 2.0, -2.0) | mat2(-2.0, 7.0, 7.0, -5.0) | mat2(4.0, 4.0, -7.0, -0.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ mat2 func (mat2 a)
+ {
+ return -2.0*a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mat2x3
+ version 310 es
+ values
+ {
+ input mat2x3 in0 = [ mat2x3(2.5, 0.0, 1.0, -2.5, 1.0, 3.0) | mat2x3(0.0, 2.0, 1.5, -3.5, 2.0, 0.5) | mat2x3(-1.5, -3.5, 2.5, 0.0, 1.5, 3.0) ];
+ output mat2x3 out0 = [ mat2x3(-5.0, -0.0, -2.0, 5.0, -2.0, -6.0) | mat2x3(-0.0, -4.0, -3.0, 7.0, -4.0, -1.0) | mat2x3(3.0, 7.0, -5.0, -0.0, -3.0, -6.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ mat2x3 func (mat2x3 a)
+ {
+ return -2.0*a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mat2x4
+ version 310 es
+ values
+ {
+ input mat2x4 in0 = [ mat2x4(1.5, 3.0, -1.0, 2.5, -0.5, 3.5, 3.0, -3.0) | mat2x4(-2.5, -2.0, 3.5, -0.5, 1.0, -1.5, 0.0, -1.0) | mat2x4(-1.0, 0.5, 0.5, 3.0, 1.5, 3.0, 2.5, 3.5) ];
+ output mat2x4 out0 = [ mat2x4(-3.0, -6.0, 2.0, -5.0, 1.0, -7.0, -6.0, 6.0) | mat2x4(5.0, 4.0, -7.0, 1.0, -2.0, 3.0, -0.0, 2.0) | mat2x4(2.0, -1.0, -1.0, -6.0, -3.0, -6.0, -5.0, -7.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ mat2x4 func (mat2x4 a)
+ {
+ return -2.0*a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mat3x2
+ version 310 es
+ values
+ {
+ input mat3x2 in0 = [ mat3x2(1.5, -2.5, 2.5, 3.5, 3.0, 0.5) | mat3x2(1.5, -2.0, 2.5, 0.5, -1.5, -3.5) | mat3x2(2.5, 3.5, -3.0, 2.5, -0.5, -2.5) ];
+ output mat3x2 out0 = [ mat3x2(-3.0, 5.0, -5.0, -7.0, -6.0, -1.0) | mat3x2(-3.0, 4.0, -5.0, -1.0, 3.0, 7.0) | mat3x2(-5.0, -7.0, 6.0, -5.0, 1.0, 5.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ mat3x2 func (mat3x2 a)
+ {
+ return -2.0*a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mat3
+ version 310 es
+ values
+ {
+ input mat3 in0 = [ mat3(-1.5, 2.0, 3.0, -3.5, 1.0, -3.5, 1.5, -1.5, 3.0) | mat3(3.5, 0.0, 3.5, -1.5, -3.0, 0.5, -3.5, -2.5, -0.5) | mat3(1.0, -2.5, -3.5, 3.0, -1.5, 3.5, 3.0, -1.0, -0.5) ];
+ output mat3 out0 = [ mat3(3.0, -4.0, -6.0, 7.0, -2.0, 7.0, -3.0, 3.0, -6.0) | mat3(-7.0, -0.0, -7.0, 3.0, 6.0, -1.0, 7.0, 5.0, 1.0) | mat3(-2.0, 5.0, 7.0, -6.0, 3.0, -7.0, -6.0, 2.0, 1.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ mat3 func (mat3 a)
+ {
+ return -2.0*a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mat3x4
+ version 310 es
+ values
+ {
+ input mat3x4 in0 = [ mat3x4(0.0, 1.0, 0.5, 0.5, 1.0, 3.5, 0.0, -0.5, 1.5, -2.0, -1.5, 3.5) | mat3x4(0.0, 0.5, -3.5, -0.5, 0.5, -3.5, 1.0, 1.0, -3.5, 1.0, -0.5, 1.5) | mat3x4(-1.0, 1.5, 2.0, -3.5, -3.5, 1.5, 3.5, -2.0, -0.5, 0.5, -1.5, -1.0) ];
+ output mat3x4 out0 = [ mat3x4(-0.0, -2.0, -1.0, -1.0, -2.0, -7.0, -0.0, 1.0, -3.0, 4.0, 3.0, -7.0) | mat3x4(-0.0, -1.0, 7.0, 1.0, -1.0, 7.0, -2.0, -2.0, 7.0, -2.0, 1.0, -3.0) | mat3x4(2.0, -3.0, -4.0, 7.0, 7.0, -3.0, -7.0, 4.0, 1.0, -1.0, 3.0, 2.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ mat3x4 func (mat3x4 a)
+ {
+ return -2.0*a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mat4x2
+ version 310 es
+ values
+ {
+ input mat4x2 in0 = [ mat4x2(-1.5, -1.0, 0.5, -1.5, -1.0, 2.0, -3.5, 0.5) | mat4x2(2.0, -1.5, -2.0, 2.5, -2.0, -2.5, -0.5, 1.5) | mat4x2(-3.0, -1.5, -1.0, 2.5, -0.5, 2.5, -2.5, -1.0) ];
+ output mat4x2 out0 = [ mat4x2(3.0, 2.0, -1.0, 3.0, 2.0, -4.0, 7.0, -1.0) | mat4x2(-4.0, 3.0, 4.0, -5.0, 4.0, 5.0, 1.0, -3.0) | mat4x2(6.0, 3.0, 2.0, -5.0, 1.0, -5.0, 5.0, 2.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ mat4x2 func (mat4x2 a)
+ {
+ return -2.0*a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mat4x3
+ version 310 es
+ values
+ {
+ input mat4x3 in0 = [ mat4x3(1.0, 3.0, -0.5, -2.0, -3.0, 0.0, -2.5, 2.5, 2.5, -2.5, -1.5, 2.5) | mat4x3(1.0, 2.5, -1.0, -3.0, -1.5, 2.0, -1.5, -1.0, -0.5, -0.5, -0.5, 3.0) | mat4x3(-2.5, -3.5, 3.5, 3.0, 3.5, -0.5, 3.5, 3.0, -2.0, 2.0, 2.5, 1.0) ];
+ output mat4x3 out0 = [ mat4x3(-2.0, -6.0, 1.0, 4.0, 6.0, -0.0, 5.0, -5.0, -5.0, 5.0, 3.0, -5.0) | mat4x3(-2.0, -5.0, 2.0, 6.0, 3.0, -4.0, 3.0, 2.0, 1.0, 1.0, 1.0, -6.0) | mat4x3(5.0, 7.0, -7.0, -6.0, -7.0, 1.0, -7.0, -6.0, 4.0, -4.0, -5.0, -2.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ mat4x3 func (mat4x3 a)
+ {
+ return -2.0*a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+ case mat4
+ version 310 es
+ values
+ {
+ input mat4 in0 = [ mat4(0.0, -1.5, -1.0, -2.0, -3.0, 0.5, -1.5, 2.5, -3.5, 3.0, 1.5, 3.0, 3.0, 3.0, 0.5, -3.5) | mat4(2.0, -2.5, -1.5, 1.0, 0.0, -0.5, 3.5, 1.0, -1.0, -2.0, 2.5, 0.0, 2.0, -1.0, -2.5, 0.5) | mat4(2.5, -2.5, 2.0, 3.0, 2.5, 2.5, -3.5, 1.0, 2.5, -3.5, -1.5, -1.5, 0.0, -0.5, 0.0, 2.0) ];
+ output mat4 out0 = [ mat4(-0.0, 3.0, 2.0, 4.0, 6.0, -1.0, 3.0, -5.0, 7.0, -6.0, -3.0, -6.0, -6.0, -6.0, -1.0, 7.0) | mat4(-4.0, 5.0, 3.0, -2.0, -0.0, 1.0, -7.0, -2.0, 2.0, 4.0, -5.0, -0.0, -4.0, 2.0, 5.0, -1.0) | mat4(-5.0, 5.0, -4.0, -6.0, -5.0, -5.0, 7.0, -2.0, -5.0, 7.0, 3.0, 3.0, -0.0, 1.0, -0.0, -4.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ mat4 func (mat4 a)
+ {
+ return -2.0*a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case float_struct
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 1.0, -2.0) | vec3(2.0, 2.5, -4.0) ];
+ output float out0 = [ 1.0 | -0.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ struct Pos { float a, b, c; };
+
+ float func (Pos p)
+ {
+ return -(p.a + p.b + p.c);
+ }
+
+ void main()
+ {
+ Pos p = Pos(in0.x, in0.y, in0.z);
+ out0 = func(p);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case struct_struct
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 1.0, -2.0) | vec3(2.0, 2.5, -4.0) ];
+ output float out0 = [ 1.0 | -0.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ struct Pos { float a, b, c; };
+
+ Pos func (Pos p)
+ {
+ return Pos(-p.a, -p.b, -p.c);
+ }
+
+ void main()
+ {
+ Pos p = Pos(in0.x, in0.y, in0.z);
+ p = func(p);
+ out0 = p.a + p.b + p.c;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case struct_nested_struct
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 1.0, -2.0) | vec3(2.0, 2.5, -4.0) ];
+ output float out0 = [ 1.0 | -0.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ struct Pos { float a, b, c; };
+ struct Line { Pos start, end; };
+
+ Line func (Pos p)
+ {
+ return Line(p, Pos(-p.a, -p.b, -p.c));
+ }
+
+ float sum (Pos p)
+ {
+ return (p.a + p.b + p.c);
+ }
+
+ void main()
+ {
+ Pos p = Pos(in0.x, in0.y, in0.z);
+ Line line = func(p);
+ out0 = sum(line.start) + (2.0 * sum(line.end));
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # datatypes
+
+group qualifiers "Function Parameter Qualifiers"
+
+ case in_float
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ float func (in float a)
+ {
+ a = -a;
+ return 2.0 * a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float f = in0;
+ float g = func(f);
+ out0 = f + g;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case out_float
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ void func (out float a)
+ {
+ a = -1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float f = 1.0;
+ func(f);
+ out0 = f * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case inout_float
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ void func (inout float a)
+ {
+ a = -a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float f = 1.0;
+ func(f);
+ out0 = f * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case in_lowp_float
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ float func (in lowp float a)
+ {
+ a = -a;
+ return 2.0 * a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float f = in0;
+ float g = func(f);
+ out0 = f + g;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case out_lowp_float
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ void func (out lowp float a)
+ {
+ a = -1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float f = 1.0;
+ func(f);
+ out0 = f * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case inout_lowp_float
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ void func (inout lowp float a)
+ {
+ a = -a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float f = 1.0;
+ func(f);
+ out0 = f * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case in_highp_float
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ float func (in highp float a)
+ {
+ a = -a;
+ return 2.0 * a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float f = in0;
+ float g = func(f);
+ out0 = f + g;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case out_highp_float
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ void func (out highp float a)
+ {
+ a = -1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float f = 1.0;
+ func(f);
+ out0 = f * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case inout_highp_float
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ void func (inout highp float a)
+ {
+ a = -a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float f = 1.0;
+ func(f);
+ out0 = f * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case const_float
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ float func (const float a)
+ {
+ float b = -a;
+ return 2.0 * b;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float f = in0;
+ float g = func(f);
+ out0 = f + g;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case const_in_float
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ float func (const in float a)
+ {
+ float b = -a;
+ return 2.0 * b;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ float f = in0;
+ float g = func(f);
+ out0 = f + g;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case in_int
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | 1 | -2 | 4 ];
+ output int out0 = [ 0 | -1 | 2 | -4 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (in int a)
+ {
+ a = -a;
+ return 2 * a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ int f = in0;
+ int g = func(f);
+ out0 = f + g;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case out_int
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | 1 | -2 | 6 ];
+ output int out0 = [ 0 | -1 | 2 | -6 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ void func (out int a)
+ {
+ a = -1;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ int f = 1;
+ func(f);
+ out0 = f * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case inout_int
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | 1 | -2 | 6 ];
+ output int out0 = [ 0 | -1 | 2 | -6 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ void func (inout int a)
+ {
+ a = -a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ int f = 1;
+ func(f);
+ out0 = f * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case in_lowp_int
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | 1 | -2 | 4 ];
+ output int out0 = [ 0 | -1 | 2 | -4 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (in lowp int a)
+ {
+ a = -a;
+ return 2 * a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ int f = in0;
+ int g = func(f);
+ out0 = f + g;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case out_lowp_int
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | 1 | -2 | 6 ];
+ output int out0 = [ 0 | -1 | 2 | -6 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ void func (out lowp int a)
+ {
+ a = -1;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ int f = 1;
+ func(f);
+ out0 = f * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case inout_lowp_int
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | 1 | -2 | 6 ];
+ output int out0 = [ 0 | -1 | 2 | -6 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ void func (inout lowp int a)
+ {
+ a = -a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ int f = 1;
+ func(f);
+ out0 = f * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case in_highp_int
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | 1 | -2 | 4 ];
+ output int out0 = [ 0 | -1 | 2 | -4 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (in highp int a)
+ {
+ a = -a;
+ return 2 * a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ int f = in0;
+ int g = func(f);
+ out0 = f + g;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case out_highp_int
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | 1 | -2 | 6 ];
+ output int out0 = [ 0 | -1 | 2 | -6 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ void func (out highp int a)
+ {
+ a = -1;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ int f = 1;
+ func(f);
+ out0 = f * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case inout_highp_int
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | 1 | -2 | 6 ];
+ output int out0 = [ 0 | -1 | 2 | -6 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ void func (inout highp int a)
+ {
+ a = -a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ int f = 1;
+ func(f);
+ out0 = f * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case const_int
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | 1 | -2 | 4 ];
+ output int out0 = [ 0 | -1 | 2 | -4 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (const int a)
+ {
+ int b = -a;
+ return 2 * b;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ int f = in0;
+ int g = func(f);
+ out0 = f + g;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case const_in_int
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | 1 | -2 | 4 ];
+ output int out0 = [ 0 | -1 | 2 | -4 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (const in int a)
+ {
+ int b = -a;
+ return 2 * b;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ int f = in0;
+ int g = func(f);
+ out0 = f + g;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case in_bool
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output bool out0 = [ true | true ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ bool func (in bool a)
+ {
+ a = !a;
+ return a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ bool f = in0;
+ bool g = func(f);
+ out0 = (f != g);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case out_bool
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output bool out0 = [ false | true ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void func (out bool a)
+ {
+ a = false;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ bool f = true;
+ func(f);
+ out0 = (in0 == f);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case inout_bool
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output bool out0 = [ false | true ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ void func (inout bool a)
+ {
+ a = !a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ bool f = true;
+ func(f);
+ out0 = (in0 == f);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case const_bool
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output bool out0 = [ true | true ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ bool func (const bool a)
+ {
+ bool b = !a;
+ return b;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ bool f = in0;
+ bool g = func(f);
+ out0 = (f != g);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # qualifiers
+
+group declarations "Function Declarations"
+
+ case basic
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (void);
+
+ float func (void)
+ {
+ return -1.0;
+ }
+
+ void main()
+ {
+ out0 = func() * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case basic_arg
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float f);
+
+ float func (float f)
+ {
+ return -f;
+ }
+
+ void main()
+ {
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case define_after_use
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (void);
+
+ void main()
+ {
+ out0 = func() * in0;
+ ${OUTPUT}
+ }
+
+ float func (void)
+ {
+ return -1.0;
+ }
+ ""
+ end
+
+ case double_declare
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (void);
+
+ float func (void);
+
+ float func (void)
+ {
+ return -1.0;
+ }
+
+ void main()
+ {
+ out0 = func() * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case declare_after_define
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (void)
+ {
+ return -1.0;
+ }
+
+ float func (void);
+
+ void main()
+ {
+ out0 = func() * in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case void_vs_no_void
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func ();
+
+ void main()
+ {
+ out0 = func() * in0;
+ ${OUTPUT}
+ }
+
+ float func (void)
+ {
+ return -1.0;
+ }
+ ""
+ end
+
+ case in_vs_no_in
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float f);
+
+ void main()
+ {
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+
+ float func (in float f)
+ {
+ return -f;
+ }
+ ""
+ end
+
+ case default_vs_explicit_precision
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float f);
+
+ void main()
+ {
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+
+ float func (mediump float f)
+ {
+ return -f;
+ }
+ ""
+ end
+
+
+end # declarations
+
+group overloading "Function Overloading"
+
+ case user_func_arg_type_simple
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ return -a;
+ }
+
+ int func (int a)
+ {
+ return -a;
+ }
+
+ void main()
+ {
+ out0 = func(in0) * float(func(-1));
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case user_func_arg_float_types
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ float func (float a) { return -a; }
+ vec2 func (vec2 a) { return a.yx; }
+ vec3 func (vec3 a) { return a.xxx; }
+ vec4 func (vec4 a) { return a.wwww; }
+
+ void main()
+ {
+ out0 = func(func(func(func(vec4(in0)).xyz).xy).x);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case user_func_arg_int_types
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | 1 | -2 | 6 ];
+ output int out0 = [ 0 | -1 | 2 | -6 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (int a) { return -a; }
+ ivec2 func (ivec2 a) { return a.yx; }
+ ivec3 func (ivec3 a) { return a.xxx; }
+ ivec4 func (ivec4 a) { return a.wwww; }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(func(func(func(ivec4(in0)).xyz).xy).x);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case user_func_arg_bool_types
+ version 310 es
+ values
+ {
+ input bool in0 = [ true | false ];
+ output bool out0 = [ false | true ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ bool func (bool a) { return !a; }
+ bvec2 func (bvec2 a) { return a.yx; }
+ bvec3 func (bvec3 a) { return a.xxx; }
+ bvec4 func (bvec4 a) { return a.wwww; }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(func(func(func(bvec4(in0)).xyz).xy).x);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case user_func_arg_basic_types
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ float func (float a) { return -a; }
+ vec2 func (vec2 a) { return a.yx; }
+ vec3 func (vec3 a) { return a.xxx; }
+ vec4 func (vec4 a) { return a.wwww; }
+ int func (int a) { return -a; }
+ ivec2 func (ivec2 a) { return a.yx; }
+ ivec3 func (ivec3 a) { return a.xxx; }
+ ivec4 func (ivec4 a) { return a.wwww; }
+ bool func (bool a) { return !a; }
+ bvec2 func (bvec2 a) { return a.yx; }
+ bvec3 func (bvec3 a) { return a.xxx; }
+ bvec4 func (bvec4 a) { return a.wwww; }
+
+ void main()
+ {
+ ${SETUP}
+ if (func(func(bvec4(false)).x))
+ out0 = func(in0) * float(func(-1));
+ else
+ out0 = float(func(func(ivec4(func(func(func(vec4(0.5)).xyz).xy).xxxx)).xy).x);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case user_func_arg_complex_types
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ struct Pos { float a, b, c; };
+ struct Line { Pos start, end; };
+
+ float func (float a) { return -a; }
+ float func (float a[4]) { return a[0] + a[3]; }
+ vec2 func (vec2 a) { return a.yx; }
+ vec3 func (vec3 a) { return a.xxx; }
+ vec4 func (vec4 a) { return a.wwww; }
+ vec4 func (vec4 a[4]) { return a[1] + a[2]; }
+ int func (int a) { return -a; }
+ ivec2 func (ivec2 a) { return a.yx; }
+ ivec3 func (ivec3 a) { return a.xxx; }
+ ivec4 func (ivec4 a) { return a.wwww; }
+ bool func (bool a) { return !a; }
+ bvec2 func (bvec2 a) { return a.yx; }
+ bvec3 func (bvec3 a) { return a.xxx; }
+ bvec4 func (bvec4 a) { return a.wwww; }
+ Pos func (Pos a) { return a; }
+ Line func (Line a) { return Line(a.end, a.start); }
+
+ void main()
+ {
+ ${SETUP}
+ float arr[4];
+ vec4 arr2[4];
+ out0 = func(arr) + func(arr2).x;
+ if (func(func(bvec4(false)).x))
+ out0 = func(in0) * float(func(-1));
+ else
+ out0 = float(func(func(ivec4(func(func(func(vec4(0.5)).xyz).xy).xxxx)).xy).x);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case user_func_arguments
+ version 310 es
+ values
+ {
+ input float in0 = [ 0.0 | 1.0 | -2.0 | 2.5 ];
+ output float out0 = [ 0.0 | -1.0 | 2.0 | -2.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ return -a;
+ }
+
+ float func (float a, float b)
+ {
+ return a * b;
+ }
+
+ void main()
+ {
+ out0 = func(in0) * func(-0.5, -2.0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case array_size
+ version 310 es
+ values
+ {
+ output float out0 = [ 1.0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float f[3])
+ {
+ return f[0];
+ }
+
+ float func (float f[4])
+ {
+ return f[1];
+ }
+
+ void main ()
+ {
+ ${SETUP}
+ float[4] x = float[4] (-1.0, 1.0, 0.0, 0.0);
+ out0 = func(x);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # overloading
+
+group array_arguments "Arrays as Arguments"
+
+ case local_in_float
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 1.0, 2.0, -4.0) | vec4(-7.5, 12.125, -0.25, 16.0) ];
+ output vec4 out0 = [ vec4(0.0, -1.0, -2.0, 4.0) | vec4(7.5, -12.125, 0.25, -16.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (in float a[4])
+ {
+ a[0] = -1.0;
+ a[2] = -4.0;
+ a[3] = -3.0 * a[1];
+ return a[0];
+ }
+
+ void main()
+ {
+ float arr[4];
+ arr[0] = in0.x;
+ arr[1] = in0.y;
+ arr[2] = in0.z;
+ arr[3] = in0.w;
+ float f = func(arr);
+ out0 = f * vec4(arr[0], arr[1], arr[2], arr[3]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case global_in_float
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 1.0, 2.0, -4.0) | vec4(-7.5, 12.125, -0.25, 16.0) ];
+ output vec4 out0 = [ vec4(0.0, -1.0, -2.0, 4.0) | vec4(7.5, -12.125, 0.25, -16.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (in float a[4])
+ {
+ a[0] = -1.0;
+ a[2] = -4.0;
+ a[3] = -3.0 * a[1];
+ return a[0];
+ }
+
+ float arr[4];
+
+ void main()
+ {
+ arr[0] = in0.x;
+ arr[1] = in0.y;
+ arr[2] = in0.z;
+ arr[3] = in0.w;
+ float f = func(arr);
+ out0 = f * vec4(arr[0], arr[1], arr[2], arr[3]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case local_in_int
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 1, 2, -4) | ivec4(-7, -11, 13, 19) ];
+ output ivec4 out0 = [ ivec4(0, -1, -2, 4) | ivec4(7, 11, -13, -19) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (in int a[4])
+ {
+ a[0] = -1;
+ a[2] = -4;
+ a[3] = -3 * a[1];
+ return a[0];
+ }
+
+ void main()
+ {
+ ${SETUP}
+ int arr[4];
+ arr[0] = in0.x;
+ arr[1] = in0.y;
+ arr[2] = in0.z;
+ arr[3] = in0.w;
+ int f = func(arr);
+ out0 = f * ivec4(arr[0], arr[1], arr[2], arr[3]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case global_in_int
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 1, 2, 4) | ivec4(-7, -11, 13, 19) ];
+ output ivec4 out0 = [ ivec4(0, -1, -2, -4) | ivec4(7, 11, -13, -19) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int func (in int a[4])
+ {
+ a[0] = -1;
+ a[2] = -4;
+ a[3] = -3 * a[1];
+ return a[0];
+ }
+
+ int arr[4];
+
+ void main()
+ {
+ ${SETUP}
+ arr[0] = in0.x;
+ arr[1] = in0.y;
+ arr[2] = in0.z;
+ arr[3] = in0.w;
+ int f = func(arr);
+ out0 = f * ivec4(arr[0], arr[1], arr[2], arr[3]);
+ ${OUTPUT}
+ }
+
+ ""
+ end
+
+ case local_in_bool
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, true, false, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, true, false) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ bool func (in bool a[4])
+ {
+ a[0] = false;
+ a[2] = true;
+ a[3] = !a[1];
+ return a[0];
+ }
+
+ void main()
+ {
+ ${SETUP}
+ bool arr[4];
+ arr[0] = !in0.x;
+ arr[1] = !in0.y;
+ arr[2] = !in0.z;
+ arr[3] = !in0.w;
+ func(arr);
+ out0 = bvec4(arr[0], arr[1], arr[2], arr[3]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case global_in_bool
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, true, false, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, true, false) | bvec4(true, true, true, true) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ bool func (in bool a[4])
+ {
+ a[0] = false;
+ a[2] = true;
+ a[3] = !a[1];
+ return a[0];
+ }
+
+ bool arr[4];
+
+ void main()
+ {
+ ${SETUP}
+ arr[0] = !in0.x;
+ arr[1] = !in0.y;
+ arr[2] = !in0.z;
+ arr[3] = !in0.w;
+ func(arr);
+ out0 = bvec4(arr[0], arr[1], arr[2], arr[3]);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case test_helpers
+ version 310 es
+ desc "Check that helper functions are supported properly."
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 1.0, 2.0, -4.0) | vec4(-7.5, 12.125, -0.25, 16.0) ];
+ output float out0 = [ 1.0 | 1.0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ vec4 get (in float arr[4]);
+ void set (out float arr[4], vec4 val);
+ void negate (inout float arr[4]);
+ bool test (in float arr[4], vec4 ref);
+ bool isEqual (in float a[4], in float b[4]);
+
+ void main()
+ {
+ float arr[4];
+ set(arr, in0);
+ negate(arr);
+ out0 = float(test(arr, -in0));
+ ${OUTPUT}
+ }
+
+ float absDiff (vec4 a, vec4 b) { vec4 d = abs(a - b); return max(max(d.x, d.y), max(d.z, d.w)); }
+ vec4 get (in float arr[4]) { return vec4(arr[0], arr[1], arr[2], arr[3]); }
+ void set (out float arr[4], vec4 val) { arr[0] = val.x; arr[1] = val.y; arr[2] = val.z; arr[3] = val.w; }
+ void negate (inout float arr[4]) { set(arr, -get(arr)); }
+ bool test (in float arr[4], vec4 ref) { return (absDiff(get(arr), ref) < 0.1); }
+ bool isEqual (in float a[4], in float b[4]) { return (absDiff(get(a), get(b)) < 0.1); }
+ ""
+ end
+
+ case copy_local_in_on_call
+ version 310 es
+ desc "Check that local 'in' arguments are copied on call and don't alias."
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 1.0, 2.0, -4.0) | vec4(-7.5, 12.125, -0.25, 16.0) ];
+ output vec4 out0 = [ vec4(0.0, -1.0, -2.0, 4.0) | vec4(7.5, -12.125, 0.25, -16.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ vec4 get (in float arr[4]);
+ void set (out float arr[4], vec4 val);
+ void negate (inout float arr[4]);
+ bool test (in float arr[4], vec4 ref);
+ bool isEqual (in float a[4], in float b[4]);
+
+ float func (in float a[4], in float b[4])
+ {
+ a[0] = 2.123;
+ a[2] = -4.123;
+ return isEqual(a, b) ? 1.0 : -1.0;
+ }
+
+ void main()
+ {
+ float arr[4];
+ set(arr, in0);
+ out0 = in0 * func(arr, arr);
+ ${OUTPUT}
+ }
+
+ float absDiff (vec4 a, vec4 b) { vec4 d = abs(a - b); return max(max(d.x, d.y), max(d.z, d.w)); }
+ vec4 get (in float arr[4]) { return vec4(arr[0], arr[1], arr[2], arr[3]); }
+ void set (out float arr[4], vec4 val) { arr[0] = val.x; arr[1] = val.y; arr[2] = val.z; arr[3] = val.w; }
+ void negate (inout float arr[4]) { set(arr, -get(arr)); }
+ bool test (in float arr[4], vec4 ref) { return (absDiff(get(arr), ref) < 0.1); }
+ bool isEqual (in float a[4], in float b[4]) { return (absDiff(get(a), get(b)) < 0.1); }
+ ""
+ end
+
+ case copy_global_in_on_call
+ version 310 es
+ desc "Check that global 'in' arguments are copied on call and don't alias."
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 1.0, 2.0, -4.0) | vec4(-7.5, 12.125, -0.25, 16.0) ];
+ output vec4 out0 = [ vec4(0.0, -1.0, -2.0, 4.0) | vec4(7.5, -12.125, 0.25, -16.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ vec4 get (in float arr[4]);
+ void set (out float arr[4], vec4 val);
+ void negate (inout float arr[4]);
+ bool test (in float arr[4], vec4 ref);
+ bool isEqual (in float a[4], in float b[4]);
+
+ float func (in float a[4], in float b[4])
+ {
+ a[0] = 2.123;
+ a[2] = -4.123;
+ return isEqual(a, b) ? 1.0 : -1.0;
+ }
+
+ float arr[4];
+
+ void main()
+ {
+ set(arr, in0);
+ out0 = in0 * func(arr, arr);
+ ${OUTPUT}
+ }
+
+ float absDiff (vec4 a, vec4 b) { vec4 d = abs(a - b); return max(max(d.x, d.y), max(d.z, d.w)); }
+ vec4 get (in float arr[4]) { return vec4(arr[0], arr[1], arr[2], arr[3]); }
+ void set (out float arr[4], vec4 val) { arr[0] = val.x; arr[1] = val.y; arr[2] = val.z; arr[3] = val.w; }
+ void negate (inout float arr[4]) { set(arr, -get(arr)); }
+ bool test (in float arr[4], vec4 ref) { return (absDiff(get(arr), ref) < 0.1); }
+ bool isEqual (in float a[4], in float b[4]) { return (absDiff(get(a), get(b)) < 0.1); }
+ ""
+ end
+
+ case copy_local_inout_on_call
+ version 310 es
+ desc "Check that local 'in' arguments are copied on call and don't alias."
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 1.0, 2.0, -4.0) | vec4(-7.5, 12.125, -0.25, 16.0) ];
+ output vec4 out0 = [ vec4(0.0, -1.0, -2.0, 4.0) | vec4(7.5, -12.125, 0.25, -16.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ vec4 get (in float arr[4]);
+ void set (out float arr[4], vec4 val);
+ void negate (inout float arr[4]);
+ bool test (in float arr[4], vec4 ref);
+ bool isEqual (in float a[4], in float b[4]);
+
+ float func (inout float a[4], inout float b[4])
+ {
+ negate(a);
+ return isEqual(a, b) ? 1.0 : -1.0;
+ }
+
+ void main()
+ {
+ float arr[4];
+ set(arr, in0);
+ float m = func(arr, arr); // returns -1.0
+ float n = float(test(arr, in0) || test(arr, -in0));
+ out0 = in0 * m * n;
+ ${OUTPUT}
+ }
+
+ float absDiff (vec4 a, vec4 b) { vec4 d = abs(a - b); return max(max(d.x, d.y), max(d.z, d.w)); }
+ vec4 get (in float arr[4]) { return vec4(arr[0], arr[1], arr[2], arr[3]); }
+ void set (out float arr[4], vec4 val) { arr[0] = val.x; arr[1] = val.y; arr[2] = val.z; arr[3] = val.w; }
+ void negate (inout float arr[4]) { set(arr, -get(arr)); }
+ bool test (in float arr[4], vec4 ref) { return (absDiff(get(arr), ref) < 0.1); }
+ bool isEqual (in float a[4], in float b[4]) { return (absDiff(get(a), get(b)) < 0.1); }
+ ""
+ end
+
+ case copy_global_inout_on_call
+ version 310 es
+ desc "Check that global 'in' arguments are copied on call and don't alias."
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 1.0, 2.0, -4.0) | vec4(-7.5, 12.125, -0.25, 16.0) ];
+ output vec4 out0 = [ vec4(0.0, -1.0, -2.0, 4.0) | vec4(7.5, -12.125, 0.25, -16.0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ vec4 get (in float arr[4]);
+ void set (out float arr[4], vec4 val);
+ void negate (inout float arr[4]);
+ bool test (in float arr[4], vec4 ref);
+ bool isEqual (in float a[4], in float b[4]);
+
+ float func (in float a[4], in float b[4])
+ {
+ negate(a);
+ return isEqual(a, b) ? 1.0 : -1.0;
+ }
+
+ float arr[4];
+
+ void main()
+ {
+ set(arr, in0);
+ float m = func(arr, arr); // returns -1.0
+ float n = float(test(arr, in0) || test(arr, -in0));
+ out0 = in0 * m * n;
+ ${OUTPUT}
+ }
+
+ float absDiff (vec4 a, vec4 b) { vec4 d = abs(a - b); return max(max(d.x, d.y), max(d.z, d.w)); }
+ vec4 get (in float arr[4]) { return vec4(arr[0], arr[1], arr[2], arr[3]); }
+ void set (out float arr[4], vec4 val) { arr[0] = val.x; arr[1] = val.y; arr[2] = val.z; arr[3] = val.w; }
+ void negate (inout float arr[4]) { set(arr, -get(arr)); }
+ bool test (in float arr[4], vec4 ref) { return (absDiff(get(arr), ref) < 0.1); }
+ bool isEqual (in float a[4], in float b[4]) { return (absDiff(get(a), get(b)) < 0.1); }
+ ""
+ end
+
+# vec4 get (in float arr[4]);
+# void set (out float arr[4], vec4 val);
+# void negate (inout float arr[4]);
+# bool test (in float arr[4], vec4 ref);
+# bool isEqual (in float a[4], in float b[4]);
+
+# float absDiff (vec4 a, vec4 b) { vec4 d = abs(a - b); return max(max(d.x, d.y), max(d.z, d.w)); }
+# vec4 get (in float arr[4]) { return vec4(arr[0], arr[1], arr[2], arr[3]); }
+# void set (out float arr[4], vec4 val) { arr[0] = val.x; arr[1] = val.y; arr[2] = val.z; arr[3] = val.w; }
+# void negate (inout float arr[4]) { set(arr, -get(arr)); }
+# bool test (in float arr[4], vec4 ref) { return (absDiff(get(arr), ref) < 0.1); }
+# bool isEqual (in float a[4], in float b[4]) { return (absDiff(get(a), get(b)) < 0.1); }
+
+end # array_arguments
+
+#group qualifiers "Function Parameter Qualifiers"
+#
+#end # qualifiers
+
+group control_flow "Control Flow In Functions"
+
+ case simple_return
+ version 310 es
+ values
+ {
+ input float in0 = [ -0.5 | 1.5 ];
+ output float out0 = [ 0.5 | -1.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ return -a;
+ a = a * -1.0;
+ return 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case return_in_if
+ version 310 es
+ values
+ {
+ input float in0 = [ -0.5 | 1.5 ];
+ output float out0 = [ 0.5 | -1.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ if (a != 0.0)
+ return -a;
+ return 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case return_in_else
+ version 310 es
+ values
+ {
+ input float in0 = [ -0.5 | 1.5 ];
+ output float out0 = [ 0.5 | -1.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ if (a == 0.0)
+ return 1.0;
+ else
+ return -a;
+ return 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case return_in_loop
+ version 310 es
+ values
+ {
+ input float in0 = [ -0.5 | 1.5 ];
+ output float out0 = [ 0.5 | -1.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ while (a < 100.0)
+ return -a;
+ return 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case return_in_loop_if
+ version 310 es
+ values
+ {
+ input float in0 = [ -0.5 | 1.5 ];
+ output float out0 = [ 0.5 | -1.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ while (a < 100.0)
+ {
+ a = -a;
+ if (a != 0.0)
+ return a;
+ else
+ return -1.0;
+ }
+ return 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case return_after_loop
+ version 310 es
+ values
+ {
+ input float in0 = [ -0.5 | 1.5 ];
+ output float out0 = [ 0.5 | -1.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ for (int i = 0; i < 5; i++)
+ a = -a;
+ return a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case return_after_break
+ version 310 es
+ values
+ {
+ input float in0 = [ -0.5 | 1.5 ];
+ output float out0 = [ 0.5 | -1.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ for (int i = 0; i < 6; i++)
+ {
+ a = -a;
+ if (i == 4)
+ break;
+ }
+ return a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case return_after_continue
+ version 310 es
+ values
+ {
+ input float in0 = [ -0.5 | 1.5 ];
+ output float out0 = [ 0.5 | -1.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ for (int i = 0; i < 6; i++)
+ {
+ if (i == 4)
+ continue;
+ a = -a;
+ }
+ return a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case return_in_nested_loop
+ version 310 es
+ values
+ {
+ input float in0 = [ -0.5 | 1.5 ];
+ output float out0 = [ 0.5 | -1.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ for (int i = 0; i < 6; i++)
+ {
+ a = -a;
+ for (int j = 0; j < 4; j++)
+ {
+ a = -a;
+ if (i == 1)
+ return a;
+ }
+ if (i == 4)
+ return 1.0;
+ }
+ return 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case return_after_loop_sequence
+ version 310 es
+ values
+ {
+ input float in0 = [ -0.5 | 1.5 ];
+ output float out0 = [ 0.5 | -1.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ int i;
+ for (i = 0; i < 6; i++) // negate a
+ {
+ a = -a;
+ if (i == 4)
+ a = -a;
+ }
+
+ for (; i < 10; i++) // keep a
+ {
+ if (i == 8)
+ continue;
+ else if (i == 9)
+ break;
+ a = -a;
+ }
+
+ return a;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mixed_return_break_continue
+ version 310 es
+ values
+ {
+ input float in0 = [ -0.5 | 1.5 ];
+ output float out0 = [ 0.5 | -1.5 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float func (float a)
+ {
+ int i;
+ for (i = 0; i < 6; i++)
+ {
+ if (i == 0)
+ continue;
+ else if (i == 1)
+ {
+ }
+ else if (i == 3)
+ break;
+ else
+ return a;
+ a = -a;
+ }
+
+ return 1.0;
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # control_flow
+
+group misc "Miscellaneous"
+
+ case multi_arg_float
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 1.0, -2.0, 0.5) | vec4(2.0, 2.5, 4.0, -7.0) ];
+ output float out0 = [ 0.5 | -1.5 ]; # -sum(in0)
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ float sum(vec4 v) { return (v.x + v.y + v.z + v.w); }
+
+ float func (float a, vec3 b, vec2 c, vec2 d, vec4 e)
+ {
+ return -sum(vec4(a, b) + vec4(c, d)) + sum(e);
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0.y, in0.xzw, in0.wz, in0.yx, in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case multi_arg_int
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(-1, 0, 2, 2) | ivec4(1, 4, -8, 2) ];
+ output int out0 = [ -3 | 1 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ precision mediump int;
+ ${DECLARATIONS}
+
+ int sum(ivec4 v) { return (v.x + v.y + v.z + v.w); }
+
+ int func (int a, ivec3 b, ivec2 c, ivec2 d, ivec4 e)
+ {
+ return -sum(ivec4(a, b) + ivec4(c, d)) + sum(e);
+ }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0.y, in0.xzw, in0.wz, in0.yx, in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case argument_eval_order_1
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | 1 | 3 | 5 ];
+ output int out0 = [ -1 | 5 | 11 | 17 ];
+ }
+
+ both ""
+ #version 310 es
+ precision highp float;
+ ${DECLARATIONS}
+
+ int func (float a, int b, bool c, int d)
+ {
+ if (c)
+ return b + int(a) + d;
+ else
+ return -1;
+ }
+
+ void main ()
+ {
+ ${SETUP}
+ float v0 = float(in0);
+ int v1 = in0;
+ out0 = func((v0 += 1.0), v1++, (v0 > 1.5), v1);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case argument_eval_order_2
+ version 310 es
+ values
+ {
+ input int in0 = [ 0 | -1 | 3 | 5 ];
+ output int out0 = [ 3 | -1 | 9 | 13 ];
+ }
+
+ both ""
+ #version 310 es
+ precision highp float;
+ ${DECLARATIONS}
+
+ int g;
+
+ int modG (int v)
+ {
+ g += v;
+ return v;
+ }
+
+ int func (float a, int b, bool c, int d)
+ {
+ if (c)
+ return b + int(a) + d;
+ else
+ return -1;
+ }
+
+ void main ()
+ {
+ ${SETUP}
+ out0 = func(float(g = in0), modG(2), --g > 0, g);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end # misc
--- /dev/null
+
+# Varying tests
+group varying "Varying linkage"
+
+ # Linking rules
+ group rules "Varying linking rules"
+ # not declared in vertex shader, declared in fragment shader
+ case fragment_declare
+ version 310 es
+ desc "varying declared in fragment shader, no reference in vertex shader"
+ values { output float out0 = 1.0; }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ void main()
+ {
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ in mediump float var;
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ {
+ out0 = 1.0;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ # declared in vertex shader, no reference in frag shader
+ case vertex_declare
+ version 310 es
+ desc "varying declared in vertex shader, no reference in fragment shader"
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ out mediump float var;
+ void main()
+ {
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ {
+ ${FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ # declared in vertex shader, declared in frag shader
+ case both_declare
+ version 310 es
+ desc "varying declared in both vertex and fragment shader, but not used"
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ out mediump float var;
+ void main()
+ {
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ in mediump float var;
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ {
+ ${FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ # declared in vertex shader, static use in frag shader
+ case vertex_declare_fragment_use
+ version 310 es
+ desc "varying declared in both shaders, statically used in fragment shader"
+ values { uniform bool u_false = false; }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ out mediump float var;
+ void main()
+ {
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ in mediump float var;
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ {
+ if (u_false)
+ ${FRAG_COLOR} = vec4(var);
+ else
+ ${FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ # static use in vertex shader, no reference in fragment shader
+ case vertex_use_fragment_declare
+ version 310 es
+ desc "varying declared and statically used in vertex shader, no reference in fragment shader"
+ values { uniform bool u_false = false; }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ out mediump float var;
+ void main()
+ {
+ if (u_false)
+ var = 1.0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ {
+ ${FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ # static use in vertex shader, declared in fragment shader
+ case vertex_use_declare_fragment
+ version 310 es
+ desc "varying declared and statically used in vertex shader, only declared in fragment shader"
+ values { uniform bool u_false = false; }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ out mediump float var;
+ void main()
+ {
+ if (u_false)
+ var = 1.0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ in mediump float var;
+ ${FRAGMENT_DECLARATIONS}
+ void main()
+ {
+ ${FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ # static use in vertex shader, used in fragment shader
+ case vertex_use_fragment_use
+ version 310 es
+ desc "varying statically used in both vertex and fragment shader"
+ values { uniform bool u_false = false; }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ out mediump float var;
+ void main()
+ {
+ if (u_false)
+ var = 1.0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float var;
+ void main()
+ {
+ if (u_false)
+ ${FRAG_COLOR} = vec4(var);
+ else
+ ${FRAG_COLOR} = vec4(1.0);
+ }
+ ""
+ end
+
+ # differing precision tests
+ case differing_precision_1
+ version 310 es
+ desc "varying declared as highp in vertex shader, but mediump in fragment shader"
+ values
+ {
+ input float in0 = [ -1.25 | -25.55 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ output float out0 = [ -1.25 | -25.55 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ }
+
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ out highp float var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump float var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ # differing precision tests
+ case differing_precision_2
+ version 310 es
+ desc "varying declared as highp in vertex shader, but lowp in fragment shader"
+ values
+ {
+ input float in0 = [ -1.25 | -25.56 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ output float out0 = [ -1.25 | -25.56 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ }
+
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ out highp vec2 var;
+ void main()
+ {
+ var = vec2(in0, 2.0*in0);
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in lowp vec2 var;
+ void main()
+ {
+ out0 = var.y - var.x;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ # differing precision tests
+ case differing_precision_3
+ version 310 es
+ desc "varying declared as lowp in vertex shader, but mediump in fragment shader"
+ values
+ {
+ input float in0 = [ -1.25 | -25.0 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ output float out0 = [ -1.25 | -25.0 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ }
+
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ out lowp vec4 var;
+ void main()
+ {
+ var = vec4(in0, 2.0*in0, -in0, -in0);
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in mediump vec4 var;
+ void main()
+ {
+ out0 = var.x + var.y + var.z + var.w;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ # different interpolation
+ case differing_interpolation_2
+ version 310 es
+ desc "varying interpolation different (smooth vs. centroid)"
+ values
+ {
+ input float in0 = [ -1.25 | -25.0 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ output float out0 = [ -1.25 | -25.0 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ }
+
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ smooth out mediump float var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ centroid in mediump float var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ end
+
+ group basic_types "Basic varying types"
+ case float
+ version 310 es
+ desc "varying of type float"
+ values
+ {
+ input float in0 = [ -1.25 | -25.65 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ output float out0 = [ -1.25 | -25.65 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ out mediump float var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in float var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case vec2
+ version 310 es
+ desc "varying of type vec2"
+ values
+ {
+ input vec2 in0 = [ vec2(-1.25, 1.25) | vec2(-25.65, -7.25) | vec2(0.0, 1.0) | vec2(2.25, 2.25) | vec2(3.4, 9.5) | vec2(16.0, 32.0) ];
+ output vec2 out0 = [ vec2(-1.25, 1.25) | vec2(-25.65, -7.25) | vec2(0.0, 1.0) | vec2(2.25, 2.25) | vec2(3.4, 9.5) | vec2(16.0, 32.0) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ out mediump vec2 var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in vec2 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case vec3
+ version 310 es
+ desc "varying of type vec3"
+ values
+ {
+ input vec3 in0 = [ vec3(-1.25, 1.25, -9.5) | vec3(-25.65, -7.25, 14.21) | vec3(0.0, 1.0, -1.0) | vec3(2.25, 2.25, 22.5) | vec3(3.4, 9.5, 19.5) | vec3(16.0, 32.0, -64.0) ];
+ output vec3 out0 = [ vec3(-1.25, 1.25, -9.5) | vec3(-25.65, -7.25, 14.21) | vec3(0.0, 1.0, -1.0) | vec3(2.25, 2.25, 22.5) | vec3(3.4, 9.5, 19.5) | vec3(16.0, 32.0, -64.0) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ out mediump vec3 var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in vec3 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case vec4
+ version 310 es
+ desc "varying of type vec4"
+ values
+ {
+ input vec4 in0 = [ vec4(-1.25, 1.25, -9.5, -12.2) | vec4(-25.65, -7.25, 14.21, -77.7) | vec4(0.0, 1.0, -1.0, 2.0) | vec4(2.25, 2.25, 22.5, 225.0) | vec4(3.4, 9.5, 19.5, 29.5) | vec4(16.0, 32.0, -64.0, -128.0) ];
+ output vec4 out0 = [ vec4(-1.25, 1.25, -9.5, -12.2) | vec4(-25.65, -7.25, 14.21, -77.7) | vec4(0.0, 1.0, -1.0, 2.0) | vec4(2.25, 2.25, 22.5, 225.0) | vec4(3.4, 9.5, 19.5, 29.5) | vec4(16.0, 32.0, -64.0, -128.0) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ out mediump vec4 var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in vec4 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case mat2
+ version 310 es
+ desc "varying of type mat2"
+ values
+ {
+ input mat2 in0 = [ mat2(1.0, 1.0, 1.0, 1.0) | mat2(-1.25, 1.25, -9.5, -12.2) | mat2(-25.65, -7.25, 14.21, -77.7) | mat2(0.0, 1.0, -1.0, 2.0) | mat2(2.25, 2.25, 22.5, 225.0) | mat2(3.4, 9.5, 19.5, 29.5) | mat2(16.0, 32.0, -64.0, -128.0) ];
+ output mat2 out0 = [ mat2(1.0, 1.0, 1.0, 1.0) | mat2(-1.25, 1.25, -9.5, -12.2) | mat2(-25.65, -7.25, 14.21, -77.7) | mat2(0.0, 1.0, -1.0, 2.0) | mat2(2.25, 2.25, 22.5, 225.0) | mat2(3.4, 9.5, 19.5, 29.5) | mat2(16.0, 32.0, -64.0, -128.0) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ out mediump mat2 var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in mat2 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x3
+ version 310 es
+ desc "varying of type mat2x3"
+ values
+ {
+ input mat2x3 in0 = [ mat2x3(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25) ];
+ output mat2x3 out0 = [ mat2x3(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ out mediump mat2x3 var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in mat2x3 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x4
+ version 310 es
+ desc "varying of type mat2x4"
+ values
+ {
+ input mat2x4 in0 = [ mat2x4(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7) ];
+ output mat2x4 out0 = [ mat2x4(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ out mediump mat2x4 var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in mat2x4 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x2
+ version 310 es
+ desc "varying of type mat3x2"
+ values
+ {
+ input mat3x2 in0 = [ mat3x2(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25) ];
+ output mat3x2 out0 = [ mat3x2(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ out mediump mat3x2 var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in mat3x2 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case mat3
+ version 310 es
+ desc "varying of type mat3"
+ values
+ {
+ input mat3 in0 = [ mat3(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7, 9.9) | mat3(0.0, 1.0, -1.0, 2.0, 2.25, 2.25, 22.5, 225.0, -9.9) | mat3(3.4, 9.5, 19.5, 29.5, 16.0, 32.0, -64.0, -128.0, 256.0) ];
+ output mat3 out0 = [ mat3(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7, 9.9) | mat3(0.0, 1.0, -1.0, 2.0, 2.25, 2.25, 22.5, 225.0, -9.9) | mat3(3.4, 9.5, 19.5, 29.5, 16.0, 32.0, -64.0, -128.0, 256.0) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ out mediump mat3 var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in mat3 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x4
+ version 310 es
+ desc "varying of type mat3x4"
+ values
+ {
+ input mat3x4 in0 = [ mat3x4(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7, 0.0, 1.0, -1.0, 2.0) ];
+ output mat3x4 out0 = [ mat3x4(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7, 0.0, 1.0, -1.0, 2.0) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ out mediump mat3x4 var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in mat3x4 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x2
+ version 310 es
+ desc "varying of type mat4x2"
+ values
+ {
+ input mat4x2 in0 = [ mat4x2(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7) ];
+ output mat4x2 out0 = [ mat4x2(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ out mediump mat4x2 var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in mat4x2 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x3
+ version 310 es
+ desc "varying of type mat4x3"
+ values
+ {
+ input mat4x3 in0 = [ mat4x3(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7, 0.0, 1.0, -1.0, 2.0) ];
+ output mat4x3 out0 = [ mat4x3(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7, 0.0, 1.0, -1.0, 2.0) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ out mediump mat4x3 var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in mat4x3 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case mat4
+ version 310 es
+ desc "varying of type mat4"
+ values
+ {
+ input mat4 in0 = [ mat4(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7, 0.0, 1.0, -1.0, 2.0, 2.25, 2.25, 22.5, 225.0) ];
+ output mat4 out0 = [ mat4(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7, 0.0, 1.0, -1.0, 2.0, 2.25, 2.25, 22.5, 225.0) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ out mediump mat4 var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in mat4 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case int
+ version 310 es
+ desc "varying of type int"
+ values
+ {
+ input int in0 = [ -1 | -25 | 1 | 2 | 3 | 16 ];
+ output int out0 = [ -1 | -25 | 1 | 2 | 3 | 16 ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ flat out mediump int var;
+ void main()
+ {
+ ${VERTEX_SETUP}
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ ${FRAGMENT_DECLARATIONS}
+ flat in int var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2
+ version 310 es
+ desc "varying of type ivec2"
+ values
+ {
+ input ivec2 in0 = [ ivec2(-1, 1) | ivec2(-25, 25) | ivec2(1, 1) | ivec2(2, 3) | ivec2(16, 17) ];
+ output ivec2 out0 = [ ivec2(-1, 1) | ivec2(-25, 25) | ivec2(1, 1) | ivec2(2, 3) | ivec2(16, 17) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ flat out mediump ivec2 var;
+ void main()
+ {
+ ${VERTEX_SETUP}
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ ${FRAGMENT_DECLARATIONS}
+ flat in ivec2 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3
+ version 310 es
+ desc "varying of type ivec3"
+ values
+ {
+ input ivec3 in0 = [ ivec3(-1, 1, -2) | ivec3(-25, 25, -3) | ivec3(1, 1, 1) | ivec3(2, 3, 4) | ivec3(16, 17, 18) ];
+ output ivec3 out0 = [ ivec3(-1, 1, -2) | ivec3(-25, 25, -3) | ivec3(1, 1, 1) | ivec3(2, 3, 4) | ivec3(16, 17, 18) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ flat out mediump ivec3 var;
+ void main()
+ {
+ ${VERTEX_SETUP}
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ ${FRAGMENT_DECLARATIONS}
+ flat in ivec3 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4
+ version 310 es
+ desc "varying of type ivec4"
+ values
+ {
+ input ivec4 in0 = [ ivec4(-1, 1, -2, 2) | ivec4(-25, 25, -3, 3) | ivec4(1, 1, 1, 1) | ivec4(2, 3, 4, 5) | ivec4(16, 17, 18, 19) ];
+ output ivec4 out0 = [ ivec4(-1, 1, -2, 2) | ivec4(-25, 25, -3, 3) | ivec4(1, 1, 1, 1) | ivec4(2, 3, 4, 5) | ivec4(16, 17, 18, 19) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ flat out mediump ivec4 var;
+ void main()
+ {
+ ${VERTEX_SETUP}
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ ${FRAGMENT_DECLARATIONS}
+ flat in ivec4 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case uint
+ version 310 es
+ desc "varying of type int"
+ values
+ {
+ input uint in0 = [ 1 | 2 | 3 | 16 ];
+ output uint out0 = [ 1 | 2 | 3 | 16 ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ flat out mediump uint var;
+ void main()
+ {
+ ${VERTEX_SETUP}
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ ${FRAGMENT_DECLARATIONS}
+ flat in uint var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2
+ version 310 es
+ desc "varying of type uvec2"
+ values
+ {
+ input uvec2 in0 = [ uvec2(1, 1) | uvec2(25, 25) | uvec2(1, 1) | uvec2(2, 3) | uvec2(16, 17) ];
+ output uvec2 out0 = [ uvec2(1, 1) | uvec2(25, 25) | uvec2(1, 1) | uvec2(2, 3) | uvec2(16, 17) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ flat out mediump uvec2 var;
+ void main()
+ {
+ ${VERTEX_SETUP}
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ ${FRAGMENT_DECLARATIONS}
+ flat in uvec2 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3
+ version 310 es
+ desc "varying of type uvec3"
+ values
+ {
+ input uvec3 in0 = [ uvec3(1, 1, 2) | uvec3(25, 25, 3) | uvec3(1, 1, 1) | uvec3(2, 3, 4) | uvec3(16, 17, 18) ];
+ output uvec3 out0 = [ uvec3(1, 1, 2) | uvec3(25, 25, 3) | uvec3(1, 1, 1) | uvec3(2, 3, 4) | uvec3(16, 17, 18) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ flat out mediump uvec3 var;
+ void main()
+ {
+ ${VERTEX_SETUP}
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ ${FRAGMENT_DECLARATIONS}
+ flat in uvec3 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4
+ version 310 es
+ desc "varying of type uvec4"
+ values
+ {
+ input uvec4 in0 = [ uvec4(1, 1, 2, 2) | uvec4(25, 25, 3, 3) | uvec4(1, 1, 1, 1) | uvec4(2, 3, 4, 5) | uvec4(16, 17, 18, 19) ];
+ output uvec4 out0 = [ uvec4(1, 1, 2, 2) | uvec4(25, 25, 3, 3) | uvec4(1, 1, 1, 1) | uvec4(2, 3, 4, 5) | uvec4(16, 17, 18, 19) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ flat out mediump uvec4 var;
+ void main()
+ {
+ ${VERTEX_SETUP}
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ ${FRAGMENT_DECLARATIONS}
+ flat in uvec4 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+ end
+
+ group struct "Structure varyings"
+ case float
+ version 310 es
+ desc "varying of type float inside struct"
+ values
+ {
+ input float in0 = [ -1.25 | -25.65 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ output float out0 = [ -1.25 | -25.65 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump float a; };
+ out S var;
+ void main()
+ {
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump float a; };
+ in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case vec2
+ version 310 es
+ desc "varying of type vec2 inside struct"
+ values
+ {
+ input vec2 in0 = [ vec2(-1.25, 1.25) | vec2(-25.65, -7.25) | vec2(0.0, 1.0) | vec2(2.25, 2.25) | vec2(3.4, 9.5) | vec2(16.0, 32.0) ];
+ output vec2 out0 = [ vec2(-1.25, 1.25) | vec2(-25.65, -7.25) | vec2(0.0, 1.0) | vec2(2.25, 2.25) | vec2(3.4, 9.5) | vec2(16.0, 32.0) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump vec2 a; };
+ out S var;
+ void main()
+ {
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump vec2 a; };
+ in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case vec3
+ version 310 es
+ desc "varying of type vec3 inside struct"
+ values
+ {
+ input vec3 in0 = [ vec3(-1.25, 1.25, -9.5) | vec3(-25.65, -7.25, 14.21) | vec3(0.0, 1.0, -1.0) | vec3(2.25, 2.25, 22.5) | vec3(3.4, 9.5, 19.5) | vec3(16.0, 32.0, -64.0) ];
+ output vec3 out0 = [ vec3(-1.25, 1.25, -9.5) | vec3(-25.65, -7.25, 14.21) | vec3(0.0, 1.0, -1.0) | vec3(2.25, 2.25, 22.5) | vec3(3.4, 9.5, 19.5) | vec3(16.0, 32.0, -64.0) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump vec3 a; };
+ out S var;
+ void main()
+ {
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump vec3 a; };
+ in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case vec4
+ version 310 es
+ desc "varying of type vec4 inside struct"
+ values
+ {
+ input vec4 in0 = [ vec4(-1.25, 1.25, -9.5, -12.2) | vec4(-25.65, -7.25, 14.21, -77.7) | vec4(0.0, 1.0, -1.0, 2.0) | vec4(2.25, 2.25, 22.5, 225.0) | vec4(3.4, 9.5, 19.5, 29.5) | vec4(16.0, 32.0, -64.0, -128.0) ];
+ output vec4 out0 = [ vec4(-1.25, 1.25, -9.5, -12.2) | vec4(-25.65, -7.25, 14.21, -77.7) | vec4(0.0, 1.0, -1.0, 2.0) | vec4(2.25, 2.25, 22.5, 225.0) | vec4(3.4, 9.5, 19.5, 29.5) | vec4(16.0, 32.0, -64.0, -128.0) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump vec4 a; };
+ out S var;
+ void main()
+ {
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump vec4 a; };
+ in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case mat2
+ version 310 es
+ desc "varying of type mat2 inside struct"
+ values
+ {
+ input mat2 in0 = [ mat2(1.0, 1.0, 1.0, 1.0) | mat2(-1.25, 1.25, -9.5, -12.2) | mat2(-25.65, -7.25, 14.21, -77.7) | mat2(0.0, 1.0, -1.0, 2.0) | mat2(2.25, 2.25, 22.5, 225.0) | mat2(3.4, 9.5, 19.5, 29.5) | mat2(16.0, 32.0, -64.0, -128.0) ];
+ output mat2 out0 = [ mat2(1.0, 1.0, 1.0, 1.0) | mat2(-1.25, 1.25, -9.5, -12.2) | mat2(-25.65, -7.25, 14.21, -77.7) | mat2(0.0, 1.0, -1.0, 2.0) | mat2(2.25, 2.25, 22.5, 225.0) | mat2(3.4, 9.5, 19.5, 29.5) | mat2(16.0, 32.0, -64.0, -128.0) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump mat2 a; };
+ out S var;
+ void main()
+ {
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump mat2 a; };
+ in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x3
+ version 310 es
+ desc "varying of type mat2x3 inside struct"
+ values
+ {
+ input mat2x3 in0 = [ mat2x3(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25) ];
+ output mat2x3 out0 = [ mat2x3(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump mat2x3 a; };
+ out S var;
+ void main()
+ {
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump mat2x3 a; };
+ in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case mat2x4
+ version 310 es
+ desc "varying of type mat2x4 inside struct"
+ values
+ {
+ input mat2x4 in0 = [ mat2x4(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7) ];
+ output mat2x4 out0 = [ mat2x4(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump mat2x4 a; };
+ out S var;
+ void main()
+ {
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump mat2x4 a; };
+ in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x2
+ version 310 es
+ desc "varying of type mat3x2 inside struct"
+ values
+ {
+ input mat3x2 in0 = [ mat3x2(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25) ];
+ output mat3x2 out0 = [ mat3x2(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump mat3x2 a; };
+ out S var;
+ void main()
+ {
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump mat3x2 a; };
+ in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case mat3
+ version 310 es
+ desc "varying of type mat3 inside struct"
+ values
+ {
+ input mat3 in0 = [ mat3(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7, 9.9) | mat3(0.0, 1.0, -1.0, 2.0, 2.25, 2.25, 22.5, 225.0, -9.9) | mat3(3.4, 9.5, 19.5, 29.5, 16.0, 32.0, -64.0, -128.0, 256.0) ];
+ output mat3 out0 = [ mat3(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7, 9.9) | mat3(0.0, 1.0, -1.0, 2.0, 2.25, 2.25, 22.5, 225.0, -9.9) | mat3(3.4, 9.5, 19.5, 29.5, 16.0, 32.0, -64.0, -128.0, 256.0) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump mat3 a; };
+ out S var;
+ void main()
+ {
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump mat3 a; };
+ in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case mat3x4
+ version 310 es
+ desc "varying of type mat3x4 inside struct"
+ values
+ {
+ input mat3x4 in0 = [ mat3x4(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7, 0.0, 1.0, -1.0, 2.0) ];
+ output mat3x4 out0 = [ mat3x4(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7, 0.0, 1.0, -1.0, 2.0) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump mat3x4 a; };
+ out S var;
+ void main()
+ {
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump mat3x4 a; };
+ in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x2
+ version 310 es
+ desc "varying of type mat4x2 inside struct"
+ values
+ {
+ input mat4x2 in0 = [ mat4x2(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7) ];
+ output mat4x2 out0 = [ mat4x2(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump mat4x2 a; };
+ out S var;
+ void main()
+ {
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump mat4x2 a; };
+ in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case mat4x3
+ version 310 es
+ desc "varying of type mat4x3 inside struct"
+ values
+ {
+ input mat4x3 in0 = [ mat4x3(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7, 0.0, 1.0, -1.0, 2.0) ];
+ output mat4x3 out0 = [ mat4x3(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7, 0.0, 1.0, -1.0, 2.0) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump mat4x3 a; };
+ out S var;
+ void main()
+ {
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump mat4x3 a; };
+ in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case mat4
+ version 310 es
+ desc "varying of type mat4 inside struct"
+ values
+ {
+ input mat4 in0 = [ mat4(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7, 0.0, 1.0, -1.0, 2.0, 2.25, 2.25, 22.5, 225.0) ];
+ output mat4 out0 = [ mat4(-1.25, 1.25, -9.5, -12.2, -25.65, -7.25, 14.21, -77.7, 0.0, 1.0, -1.0, 2.0, 2.25, 2.25, 22.5, 225.0) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump mat4 a; };
+ out S var;
+ void main()
+ {
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump mat4 a; };
+ in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case int
+ version 310 es
+ desc "varying of type int inside struct"
+ values
+ {
+ input int in0 = [ -1 | -25 | 1 | 2 | 3 | 16 ];
+ output int out0 = [ -1 | -25 | 1 | 2 | 3 | 16 ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump int a; };
+ flat out S var;
+ void main()
+ {
+ ${VERTEX_SETUP}
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump int a; };
+ flat in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case ivec2
+ version 310 es
+ desc "varying of type ivec2 inside struct"
+ values
+ {
+ input ivec2 in0 = [ ivec2(-1, 1) | ivec2(-25, 25) | ivec2(1, 1) | ivec2(2, 3) | ivec2(16, 17) ];
+ output ivec2 out0 = [ ivec2(-1, 1) | ivec2(-25, 25) | ivec2(1, 1) | ivec2(2, 3) | ivec2(16, 17) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump ivec2 a; };
+ flat out S var;
+ void main()
+ {
+ ${VERTEX_SETUP}
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump ivec2 a; };
+ flat in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case ivec3
+ version 310 es
+ desc "varying of type ivec3 inside struct"
+ values
+ {
+ input ivec3 in0 = [ ivec3(-1, 1, -2) | ivec3(-25, 25, -3) | ivec3(1, 1, 1) | ivec3(2, 3, 4) | ivec3(16, 17, 18) ];
+ output ivec3 out0 = [ ivec3(-1, 1, -2) | ivec3(-25, 25, -3) | ivec3(1, 1, 1) | ivec3(2, 3, 4) | ivec3(16, 17, 18) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump ivec3 a; };
+ flat out S var;
+ void main()
+ {
+ ${VERTEX_SETUP}
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump ivec3 a; };
+ flat in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case ivec4
+ version 310 es
+ desc "varying of type ivec4 inside struct"
+ values
+ {
+ input ivec4 in0 = [ ivec4(-1, 1, -2, 2) | ivec4(-25, 25, -3, 3) | ivec4(1, 1, 1, 1) | ivec4(2, 3, 4, 5) | ivec4(16, 17, 18, 19) ];
+ output ivec4 out0 = [ ivec4(-1, 1, -2, 2) | ivec4(-25, 25, -3, 3) | ivec4(1, 1, 1, 1) | ivec4(2, 3, 4, 5) | ivec4(16, 17, 18, 19) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump ivec4 a; };
+ flat out S var;
+ void main()
+ {
+ ${VERTEX_SETUP}
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump ivec4 a; };
+ flat in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case uint
+ version 310 es
+ desc "varying of type uint in struct"
+ values
+ {
+ input uint in0 = [ 1 | 2 | 3 | 16 ];
+ output uint out0 = [ 1 | 2 | 3 | 16 ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump uint a; };
+ flat out S var;
+ void main()
+ {
+ ${VERTEX_SETUP}
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump uint a; };
+ flat in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case uvec2
+ version 310 es
+ desc "varying of type uvec2 inside struct"
+ values
+ {
+ input uvec2 in0 = [ uvec2(1, 1) | uvec2(25, 25) | uvec2(1, 1) | uvec2(2, 3) | uvec2(16, 17) ];
+ output uvec2 out0 = [ uvec2(1, 1) | uvec2(25, 25) | uvec2(1, 1) | uvec2(2, 3) | uvec2(16, 17) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump uvec2 a; };
+ flat out S var;
+ void main()
+ {
+ ${VERTEX_SETUP}
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump uvec2 a; };
+ flat in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case uvec3
+ version 310 es
+ desc "varying of type uvec3 inside struct"
+ values
+ {
+ input uvec3 in0 = [ uvec3(1, 1, 2) | uvec3(25, 25, 3) | uvec3(1, 1, 1) | uvec3(2, 3, 4) | uvec3(16, 17, 18) ];
+ output uvec3 out0 = [ uvec3(1, 1, 2) | uvec3(25, 25, 3) | uvec3(1, 1, 1) | uvec3(2, 3, 4) | uvec3(16, 17, 18) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump uvec3 a; };
+ flat out S var;
+ void main()
+ {
+ ${VERTEX_SETUP}
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump uvec3 a; };
+ flat in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case uvec4
+ version 310 es
+ desc "varying of type uvec4 inside struct"
+ values
+ {
+ input uvec4 in0 = [ uvec4(1, 1, 2, 2) | uvec4(25, 25, 3, 3) | uvec4(1, 1, 1, 1) | uvec4(2, 3, 4, 5) | uvec4(16, 17, 18, 19) ];
+ output uvec4 out0 = [ uvec4(1, 1, 2, 2) | uvec4(25, 25, 3, 3) | uvec4(1, 1, 1, 1) | uvec4(2, 3, 4, 5) | uvec4(16, 17, 18, 19) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump uvec4 a; };
+ flat out S var;
+ void main()
+ {
+ ${VERTEX_SETUP}
+ var.a = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump uvec4 a; };
+ flat in S var;
+ void main()
+ {
+ out0 = var.a;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case float_vec3
+ version 310 es
+ desc "varyings of type float and vec3 inside struct"
+ values
+ {
+ input float in0 = [ -1.25 | -25.65 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ output float out0 = [ -1.25 | -25.65 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ input vec3 in1 = [ vec3(-1.25, 1.25, -9.5) | vec3(-25.65, -7.25, 14.21) | vec3(0.0, 1.0, -1.0) | vec3(2.25, 2.25, 22.5) | vec3(3.4, 9.5, 19.5) | vec3(16.0, 32.0, -64.0) ];
+ output vec3 out1 = [ vec3(-1.25, 1.25, -9.5) | vec3(-25.65, -7.25, 14.21) | vec3(0.0, 1.0, -1.0) | vec3(2.25, 2.25, 22.5) | vec3(3.4, 9.5, 19.5) | vec3(16.0, 32.0, -64.0) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump float a; highp vec3 b; };
+ out S var;
+ void main()
+ {
+ var.a = in0;
+ var.b = in1;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump float a; highp vec3 b; };
+ in S var;
+ void main()
+ {
+ out0 = var.a;
+ out1 = var.b;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case float_uvec2_vec3
+ version 310 es
+ desc "varyings of type float and vec3 inside struct"
+ values
+ {
+ input float in0 = [ -1.25 | -25.65 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ output float out0 = [ -1.25 | -25.65 | 1.0 | 2.25 | 3.4 | 16.0 ];
+ input uvec2 in1 = [ uvec2(1, 1) | uvec2(25, 25) | uvec2(1, 1) | uvec2(2, 3) | uvec2(16, 17) | uvec2(8, 7) ];
+ output uvec2 out1 = [ uvec2(1, 1) | uvec2(25, 25) | uvec2(1, 1) | uvec2(2, 3) | uvec2(16, 17) | uvec2(8, 7) ];
+ input vec3 in2 = [ vec3(-1.25, 1.25, -9.5) | vec3(-25.65, -7.25, 14.21) | vec3(0.0, 1.0, -1.0) | vec3(2.25, 2.25, 22.5) | vec3(3.4, 9.5, 19.5) | vec3(16.0, 32.0, -64.0) ];
+ output vec3 out2 = [ vec3(-1.25, 1.25, -9.5) | vec3(-25.65, -7.25, 14.21) | vec3(0.0, 1.0, -1.0) | vec3(2.25, 2.25, 22.5) | vec3(3.4, 9.5, 19.5) | vec3(16.0, 32.0, -64.0) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ struct S { mediump float a; highp uvec2 b; highp vec3 c; };
+ flat out S var;
+ void main()
+ {
+ ${VERTEX_SETUP}
+ var.a = in0;
+ var.b = in1;
+ var.c = in2;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ struct S { mediump float a; highp uvec2 b; highp vec3 c; };
+ flat in S var;
+ void main()
+ {
+ out0 = var.a;
+ out1 = var.b;
+ out2 = var.c;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+ end
+
+ group interpolation "Varying interpolation modes"
+ case smooth
+ version 310 es
+ desc "varying of type vec4"
+ values
+ {
+ input vec4 in0 = [ vec4(-1.25, 1.25, -9.5, -12.2) | vec4(-25.65, -7.25, 14.21, -77.7) | vec4(0.0, 1.0, -1.0, 2.0) | vec4(2.25, 2.25, 22.5, 225.0) | vec4(3.4, 9.5, 19.5, 29.5) | vec4(16.0, 32.0, -64.0, -128.0) ];
+ output vec4 out0 = [ vec4(-1.25, 1.25, -9.5, -12.2) | vec4(-25.65, -7.25, 14.21, -77.7) | vec4(0.0, 1.0, -1.0, 2.0) | vec4(2.25, 2.25, 22.5, 225.0) | vec4(3.4, 9.5, 19.5, 29.5) | vec4(16.0, 32.0, -64.0, -128.0) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ smooth out mediump vec4 var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ smooth in vec4 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case centroid
+ version 310 es
+ desc "varying of type vec4"
+ values
+ {
+ input vec4 in0 = [ vec4(-1.25, 1.25, -9.5, -12.2) | vec4(-25.65, -7.25, 14.21, -77.7) | vec4(0.0, 1.0, -1.0, 2.0) | vec4(2.25, 2.25, 22.5, 225.0) | vec4(3.4, 9.5, 19.5, 29.5) | vec4(16.0, 32.0, -64.0, -128.0) ];
+ output vec4 out0 = [ vec4(-1.25, 1.25, -9.5, -12.2) | vec4(-25.65, -7.25, 14.21, -77.7) | vec4(0.0, 1.0, -1.0, 2.0) | vec4(2.25, 2.25, 22.5, 225.0) | vec4(3.4, 9.5, 19.5, 29.5) | vec4(16.0, 32.0, -64.0, -128.0) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ centroid out mediump vec4 var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ centroid in vec4 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+
+ case flat
+ version 310 es
+ desc "varying of type vec4"
+ values
+ {
+ input vec4 in0 = [ vec4(-1.25, 1.25, -9.5, -12.2) | vec4(-25.65, -7.25, 14.21, -77.7) | vec4(0.0, 1.0, -1.0, 2.0) | vec4(2.25, 2.25, 22.5, 225.0) | vec4(3.4, 9.5, 19.5, 29.5) | vec4(16.0, 32.0, -64.0, -128.0) ];
+ output vec4 out0 = [ vec4(-1.25, 1.25, -9.5, -12.2) | vec4(-25.65, -7.25, 14.21, -77.7) | vec4(0.0, 1.0, -1.0, 2.0) | vec4(2.25, 2.25, 22.5, 225.0) | vec4(3.4, 9.5, 19.5, 29.5) | vec4(16.0, 32.0, -64.0, -128.0) ];
+ }
+ vertex ""
+ #version 310 es
+ ${VERTEX_DECLARATIONS}
+ flat out mediump vec4 var;
+ void main()
+ {
+ var = in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ flat in vec4 var;
+ void main()
+ {
+ out0 = var;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+ end
+
+ group usage "Varying usage in shaders"
+ case readback_1
+ version 310 es
+ desc "read back (an already written) varying in the vertex shader"
+ values
+ {
+ input float in0 = [ 1.0 | 0.0 | -2.0 | 10.0 ];
+ output float out0 = [ 3.0 | 0.0 | -6.0 | 30.0 ];
+ }
+ vertex ""
+ #version 310 es
+ precision mediump float;
+ ${VERTEX_DECLARATIONS}
+ out float var1;
+ out float var2;
+
+ void main()
+ {
+ var1 = in0;
+ var2 = var1 + in0;
+ ${VERTEX_OUTPUT}
+ }
+ ""
+ fragment ""
+ #version 310 es
+ precision mediump float;
+ ${FRAGMENT_DECLARATIONS}
+ in float var1;
+ in float var2;
+
+ void main()
+ {
+ out0 = var1 + var2;
+ ${FRAGMENT_OUTPUT}
+ }
+ ""
+ end
+ end
+end
--- /dev/null
+group valid "Valid scoping and name redeclaration cases"
+
+ case local_variable_hides_global_variable
+ version 310 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ int a = -1;
+
+ void main()
+ {
+ ${SETUP}
+ int a = in0;
+
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case block_variable_hides_local_variable
+ version 310 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ ${SETUP}
+ int a = in0;
+ {
+ int a = -1;
+ }
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case block_variable_hides_global_variable
+ version 310 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ int a = -1;
+
+ void main()
+ {
+ ${SETUP}
+ {
+ int a = in0;
+
+ out0 = a;
+ }
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case for_init_statement_variable_hides_local_variable
+ version 310 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ ${SETUP}
+ int a = in0;
+ for (int a = 0; a < 10; a++)
+ {
+ }
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case while_condition_variable_hides_local_variable
+ version 310 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ ${SETUP}
+ int a = in0;
+ int i = 0;
+ while (bool a = (i < 1))
+ {
+ i++;
+ }
+ out0 = a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case for_init_statement_variable_hides_global_variable
+ version 310 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ int a = 5;
+
+ void main()
+ {
+ ${SETUP}
+ for (int a = 0; a < 10; a++)
+ {
+ }
+ out0 = in0 + a - 5;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case while_condition_variable_hides_global_variable
+ version 310 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ int a = 5;
+
+ void main()
+ {
+ ${SETUP}
+ int i = 0;
+ while (bool a = (i < 1))
+ {
+ i++;
+ }
+ out0 = in0 + a - 5;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case variable_in_if_hides_global_variable
+ version 310 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ int a = 1;
+
+ void main()
+ {
+ ${SETUP}
+ if (true)
+ int a = 42;
+ out0 = a*in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case variable_from_outer_scope_visible_in_initializer
+ version 310 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+ void main()
+ {
+ ${SETUP}
+ int a = in0;
+ {
+ int a = a+5, b = a-5;
+ out0 = b;
+ a = 42;
+ }
+ out0 = out0 + a - in0;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case local_int_variable_hides_struct_type
+ version 310 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ struct S { int val; };
+
+ void main()
+ {
+ ${SETUP}
+ int S = S(in0).val;
+ out0 = S;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case local_struct_variable_hides_struct_type
+ version 310 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ struct S { int val; };
+
+ void main()
+ {
+ ${SETUP}
+ S S = S(in0);
+ out0 = S.val;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case local_variable_hides_function
+ version 310 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ int foo (int x) { return x; }
+
+ void main()
+ {
+ ${SETUP}
+ int foo = in0;
+ out0 = foo;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case function_parameter_hides_global_variable
+ version 310 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ int a = -1;
+
+ int func (int a) { return a; }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case function_parameter_hides_struct_type
+ version 310 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ struct S { int x; };
+
+ int func (int S) { return S; }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case function_parameter_hides_function
+ version 310 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ int func (int func) { return func; }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case local_variable_in_inner_scope_hides_function_parameter
+ version 310 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+ int func (int inp, int x) { { int x = 5; return inp + x - 5; } }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0, 42);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case redeclare_function
+ version 310 es
+ values
+ {
+ input int in0 = [ 1 | 2 | 3 ];
+ output int out0 = [ 1 | 2 | 3 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+ ${DECLARATIONS}
+
+ int func (int x);
+ int func (int);
+ int func (int inp) { return inp; }
+
+ void main()
+ {
+ ${SETUP}
+ out0 = func(in0);
+ ${OUTPUT}
+ }
+ ""
+ end
+
+end
--- /dev/null
+# WARNING: This file is auto-generated. Do NOT modify it manually, but rather
+# modify the generating script file. Otherwise changes will be lost!
+
+group vector_swizzles "Vector Swizzles"
+
+ case mediump_vec2_x
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_xx
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(-0.5, -0.5) | vec2(-32.0, -32.0) | vec2(-0.75, -0.75) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_xy
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_yx
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.5, 0.0) | vec2(1.25, 1.0) | vec2(-2.25, -0.5) | vec2(64.0, -32.0) | vec2(-0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_yxy
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec3 out0 = [ vec3(0.5, 0.0, 0.5) | vec3(1.25, 1.0, 1.25) | vec3(-2.25, -0.5, -2.25) | vec3(64.0, -32.0, 64.0) | vec3(-0.0322580645161, -0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yxy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_xyxx
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.0, 0.0) | vec4(1.0, 1.25, 1.0, 1.0) | vec4(-0.5, -2.25, -0.5, -0.5) | vec4(-32.0, 64.0, -32.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.75, -0.75) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_yyyy
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec4 out0 = [ vec4(0.5, 0.5, 0.5, 0.5) | vec4(1.25, 1.25, 1.25, 1.25) | vec4(-2.25, -2.25, -2.25, -2.25) | vec4(64.0, 64.0, 64.0, 64.0) | vec4(-0.0322580645161, -0.0322580645161, -0.0322580645161, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyyy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_s
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_ss
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(-0.5, -0.5) | vec2(-32.0, -32.0) | vec2(-0.75, -0.75) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_st
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.st;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_ts
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.5, 0.0) | vec2(1.25, 1.0) | vec2(-2.25, -0.5) | vec2(64.0, -32.0) | vec2(-0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_tst
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec3 out0 = [ vec3(0.5, 0.0, 0.5) | vec3(1.25, 1.0, 1.25) | vec3(-2.25, -0.5, -2.25) | vec3(64.0, -32.0, 64.0) | vec3(-0.0322580645161, -0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tst;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_stss
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.0, 0.0) | vec4(1.0, 1.25, 1.0, 1.0) | vec4(-0.5, -2.25, -0.5, -0.5) | vec4(-32.0, 64.0, -32.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.75, -0.75) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_tttt
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec4 out0 = [ vec4(0.5, 0.5, 0.5, 0.5) | vec4(1.25, 1.25, 1.25, 1.25) | vec4(-2.25, -2.25, -2.25, -2.25) | vec4(64.0, 64.0, 64.0, 64.0) | vec4(-0.0322580645161, -0.0322580645161, -0.0322580645161, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tttt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_r
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_rr
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.0, 0.0) | vec2(1.0, 1.0) | vec2(-0.5, -0.5) | vec2(-32.0, -32.0) | vec2(-0.75, -0.75) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_rg
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_gr
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec2 out0 = [ vec2(0.5, 0.0) | vec2(1.25, 1.0) | vec2(-2.25, -0.5) | vec2(64.0, -32.0) | vec2(-0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_grg
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec3 out0 = [ vec3(0.5, 0.0, 0.5) | vec3(1.25, 1.0, 1.25) | vec3(-2.25, -0.5, -2.25) | vec3(64.0, -32.0, 64.0) | vec3(-0.0322580645161, -0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.grg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_rgrr
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.0, 0.0) | vec4(1.0, 1.25, 1.0, 1.0) | vec4(-0.5, -2.25, -0.5, -0.5) | vec4(-32.0, 64.0, -32.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.75, -0.75) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec2_gggg
+ version 310 es
+ values
+ {
+ input vec2 in0 = [ vec2(0.0, 0.5) | vec2(1.0, 1.25) | vec2(-0.5, -2.25) | vec2(-32.0, 64.0) | vec2(-0.75, -0.0322580645161) ];
+ output vec4 out0 = [ vec4(0.5, 0.5, 0.5, 0.5) | vec4(1.25, 1.25, 1.25, 1.25) | vec4(-2.25, -2.25, -2.25, -2.25) | vec4(64.0, 64.0, 64.0, 64.0) | vec4(-0.0322580645161, -0.0322580645161, -0.0322580645161, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gggg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_x
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_z
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output float out0 = [ 0.75 | 1.125 | -4.875 | -51.0 | 0.0526315789474 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.z;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_xz
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec2 out0 = [ vec2(0.0, 0.75) | vec2(1.0, 1.125) | vec2(-0.5, -4.875) | vec2(-32.0, -51.0) | vec2(-0.75, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_zz
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec2 out0 = [ vec2(0.75, 0.75) | vec2(1.125, 1.125) | vec2(-4.875, -4.875) | vec2(-51.0, -51.0) | vec2(0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_xyz
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_zyx
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.5, 0.0) | vec3(1.125, 1.25, 1.0) | vec3(-4.875, -2.25, -0.5) | vec3(-51.0, 64.0, -32.0) | vec3(0.0526315789474, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_xxx
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(-0.5, -0.5, -0.5) | vec3(-32.0, -32.0, -32.0) | vec3(-0.75, -0.75, -0.75) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_zzz
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.75, 0.75) | vec3(1.125, 1.125, 1.125) | vec3(-4.875, -4.875, -4.875) | vec3(-51.0, -51.0, -51.0) | vec3(0.0526315789474, 0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_zzy
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.75, 0.5) | vec3(1.125, 1.125, 1.25) | vec3(-4.875, -4.875, -2.25) | vec3(-51.0, -51.0, 64.0) | vec3(0.0526315789474, 0.0526315789474, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_yxy
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.5, 0.0, 0.5) | vec3(1.25, 1.0, 1.25) | vec3(-2.25, -0.5, -2.25) | vec3(64.0, -32.0, 64.0) | vec3(-0.0322580645161, -0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yxy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_xzx
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.75, 0.0) | vec3(1.0, 1.125, 1.0) | vec3(-0.5, -4.875, -0.5) | vec3(-32.0, -51.0, -32.0) | vec3(-0.75, 0.0526315789474, -0.75) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xzx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_xyyx
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.5, 0.0) | vec4(1.0, 1.25, 1.25, 1.0) | vec4(-0.5, -2.25, -2.25, -0.5) | vec4(-32.0, 64.0, 64.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_zzzz
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec4 out0 = [ vec4(0.75, 0.75, 0.75, 0.75) | vec4(1.125, 1.125, 1.125, 1.125) | vec4(-4.875, -4.875, -4.875, -4.875) | vec4(-51.0, -51.0, -51.0, -51.0) | vec4(0.0526315789474, 0.0526315789474, 0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzzz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_s
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_p
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output float out0 = [ 0.75 | 1.125 | -4.875 | -51.0 | 0.0526315789474 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.p;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_sp
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec2 out0 = [ vec2(0.0, 0.75) | vec2(1.0, 1.125) | vec2(-0.5, -4.875) | vec2(-32.0, -51.0) | vec2(-0.75, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_pp
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec2 out0 = [ vec2(0.75, 0.75) | vec2(1.125, 1.125) | vec2(-4.875, -4.875) | vec2(-51.0, -51.0) | vec2(0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_stp
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_pts
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.5, 0.0) | vec3(1.125, 1.25, 1.0) | vec3(-4.875, -2.25, -0.5) | vec3(-51.0, 64.0, -32.0) | vec3(0.0526315789474, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_sss
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(-0.5, -0.5, -0.5) | vec3(-32.0, -32.0, -32.0) | vec3(-0.75, -0.75, -0.75) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_ppp
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.75, 0.75) | vec3(1.125, 1.125, 1.125) | vec3(-4.875, -4.875, -4.875) | vec3(-51.0, -51.0, -51.0) | vec3(0.0526315789474, 0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_ppt
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.75, 0.5) | vec3(1.125, 1.125, 1.25) | vec3(-4.875, -4.875, -2.25) | vec3(-51.0, -51.0, 64.0) | vec3(0.0526315789474, 0.0526315789474, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_tst
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.5, 0.0, 0.5) | vec3(1.25, 1.0, 1.25) | vec3(-2.25, -0.5, -2.25) | vec3(64.0, -32.0, 64.0) | vec3(-0.0322580645161, -0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tst;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_sps
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.75, 0.0) | vec3(1.0, 1.125, 1.0) | vec3(-0.5, -4.875, -0.5) | vec3(-32.0, -51.0, -32.0) | vec3(-0.75, 0.0526315789474, -0.75) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sps;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_stts
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.5, 0.0) | vec4(1.0, 1.25, 1.25, 1.0) | vec4(-0.5, -2.25, -2.25, -0.5) | vec4(-32.0, 64.0, 64.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_pppp
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec4 out0 = [ vec4(0.75, 0.75, 0.75, 0.75) | vec4(1.125, 1.125, 1.125, 1.125) | vec4(-4.875, -4.875, -4.875, -4.875) | vec4(-51.0, -51.0, -51.0, -51.0) | vec4(0.0526315789474, 0.0526315789474, 0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pppp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_r
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_b
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output float out0 = [ 0.75 | 1.125 | -4.875 | -51.0 | 0.0526315789474 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.b;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_rb
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec2 out0 = [ vec2(0.0, 0.75) | vec2(1.0, 1.125) | vec2(-0.5, -4.875) | vec2(-32.0, -51.0) | vec2(-0.75, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_bb
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec2 out0 = [ vec2(0.75, 0.75) | vec2(1.125, 1.125) | vec2(-4.875, -4.875) | vec2(-51.0, -51.0) | vec2(0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_rgb
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_bgr
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.5, 0.0) | vec3(1.125, 1.25, 1.0) | vec3(-4.875, -2.25, -0.5) | vec3(-51.0, 64.0, -32.0) | vec3(0.0526315789474, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bgr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_rrr
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.0, 0.0) | vec3(1.0, 1.0, 1.0) | vec3(-0.5, -0.5, -0.5) | vec3(-32.0, -32.0, -32.0) | vec3(-0.75, -0.75, -0.75) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_bbb
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.75, 0.75) | vec3(1.125, 1.125, 1.125) | vec3(-4.875, -4.875, -4.875) | vec3(-51.0, -51.0, -51.0) | vec3(0.0526315789474, 0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_bbg
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.75, 0.75, 0.5) | vec3(1.125, 1.125, 1.25) | vec3(-4.875, -4.875, -2.25) | vec3(-51.0, -51.0, 64.0) | vec3(0.0526315789474, 0.0526315789474, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_grg
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.5, 0.0, 0.5) | vec3(1.25, 1.0, 1.25) | vec3(-2.25, -0.5, -2.25) | vec3(64.0, -32.0, 64.0) | vec3(-0.0322580645161, -0.75, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.grg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_rbr
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec3 out0 = [ vec3(0.0, 0.75, 0.0) | vec3(1.0, 1.125, 1.0) | vec3(-0.5, -4.875, -0.5) | vec3(-32.0, -51.0, -32.0) | vec3(-0.75, 0.0526315789474, -0.75) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rbr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_rggr
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.5, 0.0) | vec4(1.0, 1.25, 1.25, 1.0) | vec4(-0.5, -2.25, -2.25, -0.5) | vec4(-32.0, 64.0, 64.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rggr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec3_bbbb
+ version 310 es
+ values
+ {
+ input vec3 in0 = [ vec3(0.0, 0.5, 0.75) | vec3(1.0, 1.25, 1.125) | vec3(-0.5, -2.25, -4.875) | vec3(-32.0, 64.0, -51.0) | vec3(-0.75, -0.0322580645161, 0.0526315789474) ];
+ output vec4 out0 = [ vec4(0.75, 0.75, 0.75, 0.75) | vec4(1.125, 1.125, 1.125, 1.125) | vec4(-4.875, -4.875, -4.875, -4.875) | vec4(-51.0, -51.0, -51.0, -51.0) | vec4(0.0526315789474, 0.0526315789474, 0.0526315789474, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbbb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_x
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_w
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output float out0 = [ 0.825 | 1.75 | 9.0 | 24.0 | 0.25 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.w;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_wx
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec2 out0 = [ vec2(0.825, 0.0) | vec2(1.75, 1.0) | vec2(9.0, -0.5) | vec2(24.0, -32.0) | vec2(0.25, -0.75) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_wz
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec2 out0 = [ vec2(0.825, 0.75) | vec2(1.75, 1.125) | vec2(9.0, -4.875) | vec2(24.0, -51.0) | vec2(0.25, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_www
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.825, 0.825, 0.825) | vec3(1.75, 1.75, 1.75) | vec3(9.0, 9.0, 9.0) | vec3(24.0, 24.0, 24.0) | vec3(0.25, 0.25, 0.25) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.www;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_yyw
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.5, 0.5, 0.825) | vec3(1.25, 1.25, 1.75) | vec3(-2.25, -2.25, 9.0) | vec3(64.0, 64.0, 24.0) | vec3(-0.0322580645161, -0.0322580645161, 0.25) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_wzy
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.825, 0.75, 0.5) | vec3(1.75, 1.125, 1.25) | vec3(9.0, -4.875, -2.25) | vec3(24.0, -51.0, 64.0) | vec3(0.25, 0.0526315789474, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_xyzw
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyzw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_wzyx
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.75, 0.5, 0.0) | vec4(1.75, 1.125, 1.25, 1.0) | vec4(9.0, -4.875, -2.25, -0.5) | vec4(24.0, -51.0, 64.0, -32.0) | vec4(0.25, 0.0526315789474, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_xxxx
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 0.0, 0.0) | vec4(1.0, 1.0, 1.0, 1.0) | vec4(-0.5, -0.5, -0.5, -0.5) | vec4(-32.0, -32.0, -32.0, -32.0) | vec4(-0.75, -0.75, -0.75, -0.75) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xxxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_yyyy
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.5, 0.5, 0.5, 0.5) | vec4(1.25, 1.25, 1.25, 1.25) | vec4(-2.25, -2.25, -2.25, -2.25) | vec4(64.0, 64.0, 64.0, 64.0) | vec4(-0.0322580645161, -0.0322580645161, -0.0322580645161, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyyy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_wwww
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.825, 0.825, 0.825) | vec4(1.75, 1.75, 1.75, 1.75) | vec4(9.0, 9.0, 9.0, 9.0) | vec4(24.0, 24.0, 24.0, 24.0) | vec4(0.25, 0.25, 0.25, 0.25) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wwww;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_wzzw
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.75, 0.75, 0.825) | vec4(1.75, 1.125, 1.125, 1.75) | vec4(9.0, -4.875, -4.875, 9.0) | vec4(24.0, -51.0, -51.0, 24.0) | vec4(0.25, 0.0526315789474, 0.0526315789474, 0.25) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzzw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_wwwy
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.825, 0.825, 0.5) | vec4(1.75, 1.75, 1.75, 1.25) | vec4(9.0, 9.0, 9.0, -2.25) | vec4(24.0, 24.0, 24.0, 64.0) | vec4(0.25, 0.25, 0.25, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wwwy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_xyxx
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.0, 0.0) | vec4(1.0, 1.25, 1.0, 1.0) | vec4(-0.5, -2.25, -0.5, -0.5) | vec4(-32.0, 64.0, -32.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.75, -0.75) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_zzwz
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.75, 0.75, 0.825, 0.75) | vec4(1.125, 1.125, 1.75, 1.125) | vec4(-4.875, -4.875, 9.0, -4.875) | vec4(-51.0, -51.0, 24.0, -51.0) | vec4(0.0526315789474, 0.0526315789474, 0.25, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzwz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_s
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_q
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output float out0 = [ 0.825 | 1.75 | 9.0 | 24.0 | 0.25 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.q;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_qs
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec2 out0 = [ vec2(0.825, 0.0) | vec2(1.75, 1.0) | vec2(9.0, -0.5) | vec2(24.0, -32.0) | vec2(0.25, -0.75) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qs;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_qp
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec2 out0 = [ vec2(0.825, 0.75) | vec2(1.75, 1.125) | vec2(9.0, -4.875) | vec2(24.0, -51.0) | vec2(0.25, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_qqq
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.825, 0.825, 0.825) | vec3(1.75, 1.75, 1.75) | vec3(9.0, 9.0, 9.0) | vec3(24.0, 24.0, 24.0) | vec3(0.25, 0.25, 0.25) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_ttq
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.5, 0.5, 0.825) | vec3(1.25, 1.25, 1.75) | vec3(-2.25, -2.25, 9.0) | vec3(64.0, 64.0, 24.0) | vec3(-0.0322580645161, -0.0322580645161, 0.25) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ttq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_qpt
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.825, 0.75, 0.5) | vec3(1.75, 1.125, 1.25) | vec3(9.0, -4.875, -2.25) | vec3(24.0, -51.0, 64.0) | vec3(0.25, 0.0526315789474, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qpt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_stpq
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stpq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_qpts
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.75, 0.5, 0.0) | vec4(1.75, 1.125, 1.25, 1.0) | vec4(9.0, -4.875, -2.25, -0.5) | vec4(24.0, -51.0, 64.0, -32.0) | vec4(0.25, 0.0526315789474, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qpts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_ssss
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 0.0, 0.0) | vec4(1.0, 1.0, 1.0, 1.0) | vec4(-0.5, -0.5, -0.5, -0.5) | vec4(-32.0, -32.0, -32.0, -32.0) | vec4(-0.75, -0.75, -0.75, -0.75) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ssss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_tttt
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.5, 0.5, 0.5, 0.5) | vec4(1.25, 1.25, 1.25, 1.25) | vec4(-2.25, -2.25, -2.25, -2.25) | vec4(64.0, 64.0, 64.0, 64.0) | vec4(-0.0322580645161, -0.0322580645161, -0.0322580645161, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tttt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_qqqq
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.825, 0.825, 0.825) | vec4(1.75, 1.75, 1.75, 1.75) | vec4(9.0, 9.0, 9.0, 9.0) | vec4(24.0, 24.0, 24.0, 24.0) | vec4(0.25, 0.25, 0.25, 0.25) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqqq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_qppq
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.75, 0.75, 0.825) | vec4(1.75, 1.125, 1.125, 1.75) | vec4(9.0, -4.875, -4.875, 9.0) | vec4(24.0, -51.0, -51.0, 24.0) | vec4(0.25, 0.0526315789474, 0.0526315789474, 0.25) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qppq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_qqqt
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.825, 0.825, 0.5) | vec4(1.75, 1.75, 1.75, 1.25) | vec4(9.0, 9.0, 9.0, -2.25) | vec4(24.0, 24.0, 24.0, 64.0) | vec4(0.25, 0.25, 0.25, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqqt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_stss
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.0, 0.0) | vec4(1.0, 1.25, 1.0, 1.0) | vec4(-0.5, -2.25, -0.5, -0.5) | vec4(-32.0, 64.0, -32.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.75, -0.75) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_ppqp
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.75, 0.75, 0.825, 0.75) | vec4(1.125, 1.125, 1.75, 1.125) | vec4(-4.875, -4.875, 9.0, -4.875) | vec4(-51.0, -51.0, 24.0, -51.0) | vec4(0.0526315789474, 0.0526315789474, 0.25, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppqp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_r
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output float out0 = [ 0.0 | 1.0 | -0.5 | -32.0 | -0.75 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_a
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output float out0 = [ 0.825 | 1.75 | 9.0 | 24.0 | 0.25 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_ar
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec2 out0 = [ vec2(0.825, 0.0) | vec2(1.75, 1.0) | vec2(9.0, -0.5) | vec2(24.0, -32.0) | vec2(0.25, -0.75) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ar;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_ab
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec2 out0 = [ vec2(0.825, 0.75) | vec2(1.75, 1.125) | vec2(9.0, -4.875) | vec2(24.0, -51.0) | vec2(0.25, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ab;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_aaa
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.825, 0.825, 0.825) | vec3(1.75, 1.75, 1.75) | vec3(9.0, 9.0, 9.0) | vec3(24.0, 24.0, 24.0) | vec3(0.25, 0.25, 0.25) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaa;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_gga
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.5, 0.5, 0.825) | vec3(1.25, 1.25, 1.75) | vec3(-2.25, -2.25, 9.0) | vec3(64.0, 64.0, 24.0) | vec3(-0.0322580645161, -0.0322580645161, 0.25) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gga;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_abg
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec3 out0 = [ vec3(0.825, 0.75, 0.5) | vec3(1.75, 1.125, 1.25) | vec3(9.0, -4.875, -2.25) | vec3(24.0, -51.0, 64.0) | vec3(0.25, 0.0526315789474, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_rgba
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgba;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_abgr
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.75, 0.5, 0.0) | vec4(1.75, 1.125, 1.25, 1.0) | vec4(9.0, -4.875, -2.25, -0.5) | vec4(24.0, -51.0, 64.0, -32.0) | vec4(0.25, 0.0526315789474, -0.0322580645161, -0.75) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abgr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_rrrr
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.0, 0.0, 0.0) | vec4(1.0, 1.0, 1.0, 1.0) | vec4(-0.5, -0.5, -0.5, -0.5) | vec4(-32.0, -32.0, -32.0, -32.0) | vec4(-0.75, -0.75, -0.75, -0.75) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rrrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_gggg
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.5, 0.5, 0.5, 0.5) | vec4(1.25, 1.25, 1.25, 1.25) | vec4(-2.25, -2.25, -2.25, -2.25) | vec4(64.0, 64.0, 64.0, 64.0) | vec4(-0.0322580645161, -0.0322580645161, -0.0322580645161, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gggg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_aaaa
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.825, 0.825, 0.825) | vec4(1.75, 1.75, 1.75, 1.75) | vec4(9.0, 9.0, 9.0, 9.0) | vec4(24.0, 24.0, 24.0, 24.0) | vec4(0.25, 0.25, 0.25, 0.25) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaaa;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_abba
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.75, 0.75, 0.825) | vec4(1.75, 1.125, 1.125, 1.75) | vec4(9.0, -4.875, -4.875, 9.0) | vec4(24.0, -51.0, -51.0, 24.0) | vec4(0.25, 0.0526315789474, 0.0526315789474, 0.25) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abba;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_aaag
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.825, 0.825, 0.825, 0.5) | vec4(1.75, 1.75, 1.75, 1.25) | vec4(9.0, 9.0, 9.0, -2.25) | vec4(24.0, 24.0, 24.0, 64.0) | vec4(0.25, 0.25, 0.25, -0.0322580645161) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaag;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_rgrr
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.0, 0.5, 0.0, 0.0) | vec4(1.0, 1.25, 1.0, 1.0) | vec4(-0.5, -2.25, -0.5, -0.5) | vec4(-32.0, 64.0, -32.0, -32.0) | vec4(-0.75, -0.0322580645161, -0.75, -0.75) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_vec4_bbab
+ version 310 es
+ values
+ {
+ input vec4 in0 = [ vec4(0.0, 0.5, 0.75, 0.825) | vec4(1.0, 1.25, 1.125, 1.75) | vec4(-0.5, -2.25, -4.875, 9.0) | vec4(-32.0, 64.0, -51.0, 24.0) | vec4(-0.75, -0.0322580645161, 0.0526315789474, 0.25) ];
+ output vec4 out0 = [ vec4(0.75, 0.75, 0.825, 0.75) | vec4(1.125, 1.125, 1.75, 1.125) | vec4(-4.875, -4.875, 9.0, -4.875) | vec4(-51.0, -51.0, 24.0, -51.0) | vec4(0.0526315789474, 0.0526315789474, 0.25, 0.0526315789474) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbab;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_x
+ version 310 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_xx
+ version 310 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, 0) | ivec2(-32, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_xy
+ version 310 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_yx
+ version 310 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(-2, 0) | ivec2(64, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_yxy
+ version 310 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, 0, -2) | ivec3(64, -32, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yxy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_xyxx
+ version 310 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, 0, 0) | ivec4(-32, 64, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_yyyy
+ version 310 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-2, -2, -2, -2) | ivec4(64, 64, 64, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyyy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_s
+ version 310 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_ss
+ version 310 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, 0) | ivec2(-32, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_st
+ version 310 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.st;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_ts
+ version 310 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(-2, 0) | ivec2(64, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_tst
+ version 310 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, 0, -2) | ivec3(64, -32, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tst;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_stss
+ version 310 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, 0, 0) | ivec4(-32, 64, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_tttt
+ version 310 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-2, -2, -2, -2) | ivec4(64, 64, 64, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tttt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_r
+ version 310 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_rr
+ version 310 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, 0) | ivec2(-32, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_rg
+ version 310 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_gr
+ version 310 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(-2, 0) | ivec2(64, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_grg
+ version 310 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, 0, -2) | ivec3(64, -32, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.grg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_rgrr
+ version 310 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, 0, 0) | ivec4(-32, 64, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec2_gggg
+ version 310 es
+ values
+ {
+ input ivec2 in0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -2) | ivec2(-32, 64) | ivec2(0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-2, -2, -2, -2) | ivec4(64, 64, 64, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gggg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_x
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_z
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output int out0 = [ 0 | 1 | -4 | -51 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.z;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_xz
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -4) | ivec2(-32, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_zz
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(-4, -4) | ivec2(-51, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_xyz
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_zyx
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -2, 0) | ivec3(-51, 64, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_xxx
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, 0, 0) | ivec3(-32, -32, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_zzz
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -4, -4) | ivec3(-51, -51, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_zzy
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -4, -2) | ivec3(-51, -51, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_yxy
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, 0, -2) | ivec3(64, -32, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yxy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_xzx
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -4, 0) | ivec3(-32, -51, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xzx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_xyyx
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -2, 0) | ivec4(-32, 64, 64, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_zzzz
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-4, -4, -4, -4) | ivec4(-51, -51, -51, -51) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzzz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_s
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_p
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output int out0 = [ 0 | 1 | -4 | -51 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.p;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_sp
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -4) | ivec2(-32, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_pp
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(-4, -4) | ivec2(-51, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_stp
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_pts
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -2, 0) | ivec3(-51, 64, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_sss
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, 0, 0) | ivec3(-32, -32, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_ppp
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -4, -4) | ivec3(-51, -51, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_ppt
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -4, -2) | ivec3(-51, -51, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_tst
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, 0, -2) | ivec3(64, -32, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tst;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_sps
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -4, 0) | ivec3(-32, -51, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sps;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_stts
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -2, 0) | ivec4(-32, 64, 64, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_pppp
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-4, -4, -4, -4) | ivec4(-51, -51, -51, -51) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pppp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_r
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_b
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output int out0 = [ 0 | 1 | -4 | -51 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.b;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_rb
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(0, -4) | ivec2(-32, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_bb
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(-4, -4) | ivec2(-51, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_rgb
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_bgr
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -2, 0) | ivec3(-51, 64, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bgr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_rrr
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, 0, 0) | ivec3(-32, -32, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_bbb
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -4, -4) | ivec3(-51, -51, -51) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_bbg
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-4, -4, -2) | ivec3(-51, -51, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_grg
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, 0, -2) | ivec3(64, -32, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.grg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_rbr
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -4, 0) | ivec3(-32, -51, -32) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rbr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_rggr
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -2, 0) | ivec4(-32, 64, 64, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rggr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec3_bbbb
+ version 310 es
+ values
+ {
+ input ivec3 in0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(0, -2, -4) | ivec3(-32, 64, -51) | ivec3(0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-4, -4, -4, -4) | ivec4(-51, -51, -51, -51) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbbb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_x
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_w
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 9 | 24 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.w;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_wx
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(9, 0) | ivec2(24, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_wz
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(9, -4) | ivec2(24, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_www
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(9, 9, 9) | ivec3(24, 24, 24) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.www;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_yyw
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, -2, 9) | ivec3(64, 64, 24) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_wzy
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(9, -4, -2) | ivec3(24, -51, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_xyzw
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyzw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_wzyx
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, -4, -2, 0) | ivec4(24, -51, 64, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_xxxx
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) | ivec4(-32, -32, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xxxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_yyyy
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-2, -2, -2, -2) | ivec4(64, 64, 64, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyyy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_wwww
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, 9, 9, 9) | ivec4(24, 24, 24, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wwww;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_wzzw
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, -4, -4, 9) | ivec4(24, -51, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzzw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_wwwy
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, 9, 9, -2) | ivec4(24, 24, 24, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wwwy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_xyxx
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, 0, 0) | ivec4(-32, 64, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_zzwz
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-4, -4, 9, -4) | ivec4(-51, -51, 24, -51) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzwz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_s
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_q
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 9 | 24 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.q;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_qs
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(9, 0) | ivec2(24, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qs;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_qp
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(9, -4) | ivec2(24, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_qqq
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(9, 9, 9) | ivec3(24, 24, 24) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_ttq
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, -2, 9) | ivec3(64, 64, 24) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ttq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_qpt
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(9, -4, -2) | ivec3(24, -51, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qpt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_stpq
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stpq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_qpts
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, -4, -2, 0) | ivec4(24, -51, 64, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qpts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_ssss
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) | ivec4(-32, -32, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ssss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_tttt
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-2, -2, -2, -2) | ivec4(64, 64, 64, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tttt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_qqqq
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, 9, 9, 9) | ivec4(24, 24, 24, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqqq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_qppq
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, -4, -4, 9) | ivec4(24, -51, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qppq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_qqqt
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, 9, 9, -2) | ivec4(24, 24, 24, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqqt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_stss
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, 0, 0) | ivec4(-32, 64, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_ppqp
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-4, -4, 9, -4) | ivec4(-51, -51, 24, -51) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppqp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_r
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 0 | -32 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_a
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output int out0 = [ 0 | 1 | 9 | 24 | 0 ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_ar
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(9, 0) | ivec2(24, -32) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ar;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_ab
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec2 out0 = [ ivec2(0, 0) | ivec2(1, 1) | ivec2(9, -4) | ivec2(24, -51) | ivec2(0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ab;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_aaa
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(9, 9, 9) | ivec3(24, 24, 24) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaa;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_gga
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(-2, -2, 9) | ivec3(64, 64, 24) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gga;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_abg
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec3 out0 = [ ivec3(0, 0, 0) | ivec3(1, 1, 1) | ivec3(9, -4, -2) | ivec3(24, -51, 64) | ivec3(0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_rgba
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgba;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_abgr
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, -4, -2, 0) | ivec4(24, -51, 64, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abgr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_rrrr
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, 0, 0, 0) | ivec4(-32, -32, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rrrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_gggg
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-2, -2, -2, -2) | ivec4(64, 64, 64, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gggg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_aaaa
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, 9, 9, 9) | ivec4(24, 24, 24, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaaa;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_abba
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, -4, -4, 9) | ivec4(24, -51, -51, 24) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abba;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_aaag
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(9, 9, 9, -2) | ivec4(24, 24, 24, 64) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaag;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_rgrr
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, 0, 0) | ivec4(-32, 64, -32, -32) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_ivec4_bbab
+ version 310 es
+ values
+ {
+ input ivec4 in0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(0, -2, -4, 9) | ivec4(-32, 64, -51, 24) | ivec4(0, 0, 0, 0) ];
+ output ivec4 out0 = [ ivec4(0, 0, 0, 0) | ivec4(1, 1, 1, 1) | ivec4(-4, -4, 9, -4) | ivec4(-51, -51, 24, -51) | ivec4(0, 0, 0, 0) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbab;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_x
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_xx
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_xy
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_yx
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(false, true) | bvec2(false, false) | bvec2(true, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_yxy
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec3 out0 = [ bvec3(false, true, false) | bvec3(false, false, false) | bvec3(true, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yxy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_xyxx
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_yyyy
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyyy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_s
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_ss
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_st
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.st;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_ts
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(false, true) | bvec2(false, false) | bvec2(true, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_tst
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec3 out0 = [ bvec3(false, true, false) | bvec3(false, false, false) | bvec3(true, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tst;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_stss
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_tttt
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tttt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_r
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_rr
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_rg
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_gr
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec2 out0 = [ bvec2(false, true) | bvec2(false, false) | bvec2(true, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_grg
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec3 out0 = [ bvec3(false, true, false) | bvec3(false, false, false) | bvec3(true, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.grg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_rgrr
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec2_gggg
+ version 310 es
+ values
+ {
+ input bvec2 in0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, true) | bvec2(true, true) | bvec2(false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gggg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_x
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_z
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bool out0 = [ false | false | false | true | false ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.z;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_xz
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_zz
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_xyz
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_zyx
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, true) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_xxx
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_zzz
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_zzy
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_yxy
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, true, false) | bvec3(false, false, false) | bvec3(true, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yxy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_xzx
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xzx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_xyyx
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, false) | bvec4(false, true, true, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_zzzz
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzzz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_s
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_p
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bool out0 = [ false | false | false | true | false ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.p;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_sp
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_pp
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_stp
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_pts
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, true) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_sss
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_ppp
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_ppt
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_tst
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, true, false) | bvec3(false, false, false) | bvec3(true, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tst;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_sps
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.sps;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_stts
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, false) | bvec4(false, true, true, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_pppp
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.pppp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_r
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_b
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bool out0 = [ false | false | false | true | false ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.b;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_rb
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_bb
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec2 out0 = [ bvec2(false, false) | bvec2(false, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_rgb
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_bgr
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, true) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bgr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_rrr
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_bbb
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_bbg
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, false) | bvec3(false, false, false) | bvec3(false, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_grg
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, true, false) | bvec3(false, false, false) | bvec3(true, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.grg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_rbr
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, true) | bvec3(false, false, false) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rbr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_rggr
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, false) | bvec4(false, true, true, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rggr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec3_bbbb
+ version 310 es
+ values
+ {
+ input bvec3 in0 = [ bvec3(true, false, false) | bvec3(false, false, false) | bvec3(false, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbbb;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_x
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.x;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_w
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bool out0 = [ true | true | false | true | false ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.w;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_wx
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_wz
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_www
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(true, true, true) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.www;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_yyw
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, true) | bvec3(false, false, true) | bvec3(true, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_wzy
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(true, false, false) | bvec3(false, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_xyzw
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyzw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_wzyx
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(true, false, false, false) | bvec4(false, false, true, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzyx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_xxxx
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xxxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_yyyy
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.yyyy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_wwww
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wwww;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_wzzw
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(true, false, false, true) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wzzw;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_wwwy
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, false) | bvec4(true, true, true, false) | bvec4(false, false, false, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.wwwy;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_xyxx
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.xyxx;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_zzwz
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, true, false) | bvec4(false, false, true, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.zzwz;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_s
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.s;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_q
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bool out0 = [ true | true | false | true | false ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.q;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_qs
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qs;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_qp
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_qqq
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(true, true, true) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_ttq
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, true) | bvec3(false, false, true) | bvec3(true, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ttq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_qpt
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(true, false, false) | bvec3(false, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qpt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_stpq
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stpq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_qpts
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(true, false, false, false) | bvec4(false, false, true, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qpts;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_ssss
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ssss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_tttt
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.tttt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_qqqq
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqqq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_qppq
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(true, false, false, true) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qppq;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_qqqt
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, false) | bvec4(true, true, true, false) | bvec4(false, false, false, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.qqqt;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_stss
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.stss;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_ppqp
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, true, false) | bvec4(false, false, true, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ppqp;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_r
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bool out0 = [ true | false | false | true | false ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.r;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_a
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bool out0 = [ true | true | false | true | false ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.a;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_ar
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, true) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ar;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_ab
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec2 out0 = [ bvec2(true, false) | bvec2(true, false) | bvec2(false, false) | bvec2(true, true) | bvec2(false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.ab;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_aaa
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, true, true) | bvec3(true, true, true) | bvec3(false, false, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaa;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_gga
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(false, false, true) | bvec3(false, false, true) | bvec3(true, true, false) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gga;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_abg
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec3 out0 = [ bvec3(true, false, false) | bvec3(true, false, false) | bvec3(false, false, true) | bvec3(true, true, true) | bvec3(false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_rgba
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgba;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_abgr
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(true, false, false, false) | bvec4(false, false, true, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abgr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_rrrr
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rrrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_gggg
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, false, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.gggg;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_aaaa
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaaa;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_abba
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, false, true) | bvec4(true, false, false, true) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.abba;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_aaag
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, true, true, false) | bvec4(true, true, true, false) | bvec4(false, false, false, true) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.aaag;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_rgrr
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(true, false, true, true) | bvec4(false, false, false, false) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.rgrr;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+ case mediump_bvec4_bbab
+ version 310 es
+ values
+ {
+ input bvec4 in0 = [ bvec4(true, false, false, true) | bvec4(false, false, false, true) | bvec4(false, true, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ output bvec4 out0 = [ bvec4(false, false, true, false) | bvec4(false, false, true, false) | bvec4(false, false, false, false) | bvec4(true, true, true, true) | bvec4(false, false, false, false) ];
+ }
+
+ both ""
+ #version 310 es
+ precision mediump float;
+
+ ${DECLARATIONS}
+
+ void main()
+ {
+ ${SETUP}
+ out0 = in0.bbab;
+ ${OUTPUT}
+ }
+ ""
+ end
+
+
+end # vector_swizzles
--- /dev/null
+# vk - Vulkan utilites
+
+set(VKUTIL_SRCS
+ vkApiVersion.cpp
+ vkApiVersion.hpp
+ vkBuilderUtil.cpp
+ vkBuilderUtil.hpp
+ vkDefs.cpp
+ vkDefs.hpp
+ vkRef.cpp
+ vkRef.hpp
+ vkRefUtil.cpp
+ vkRefUtil.hpp
+ vkPlatform.cpp
+ vkPlatform.hpp
+ vkPrograms.cpp
+ vkPrograms.hpp
+ vkStrUtil.cpp
+ vkStrUtil.hpp
+ vkQueryUtil.cpp
+ vkQueryUtil.hpp
+ vkMemUtil.cpp
+ vkMemUtil.hpp
+ vkDeviceUtil.cpp
+ vkDeviceUtil.hpp
+ vkGlslToSpirV.cpp
+ vkGlslToSpirV.hpp
+ vkSpirVAsm.hpp
+ vkSpirVAsm.cpp
+ vkSpirVProgram.hpp
+ vkSpirVProgram.cpp
+ vkBinaryRegistry.cpp
+ vkBinaryRegistry.hpp
+ vkNullDriver.cpp
+ vkNullDriver.hpp
+ vkImageUtil.cpp
+ vkImageUtil.hpp
+ vkTypeUtil.cpp
+ vkTypeUtil.hpp
+ )
+
+set(VKUTIL_LIBS
+ glutil
+ tcutil
+ )
+
+if (DEQP_HAVE_GLSLANG)
+ include_directories(${GLSLANG_INCLUDE_PATH})
+ add_definitions(-DDEQP_HAVE_GLSLANG=1)
+
+ # \note Code interfacing with glslang needs to include third-party headers
+ # that cause all sorts of warnings to appear.
+ if (DE_COMPILER_IS_GCC OR DE_COMPILER_IS_CLANG)
+ set_source_files_properties(
+ FILES vkGlslToSpirV.cpp
+ PROPERTIES COMPILE_FLAGS "${DE_3RD_PARTY_CXX_FLAGS} -std=c++11")
+ endif ()
+
+ set(VKUTIL_LIBS ${VKUTIL_LIBS} ${GLSLANG_LIBRARY})
+endif ()
+
+if(DEQP_HAVE_SPIRV_TOOLS)
+ include_directories(${spirv-tools_SOURCE_DIR}/include)
+ include_directories(${spirv-tools_SOURCE_DIR}/external/include)
+
+ add_definitions(-DDEQP_HAVE_SPIRV_TOOLS=1)
+ set(VKUTIL_LIBS ${VKUTIL_LIBS} SPIRV-Tools)
+endif()
+
+add_library(vkutil STATIC ${VKUTIL_SRCS})
+target_link_libraries(vkutil ${VKUTIL_LIBS})
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Vulkan api version.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkApiVersion.hpp"
+
+namespace vk
+{
+
+ApiVersion unpackVersion (deUint32 version)
+{
+ return ApiVersion((version & 0xFFC00000) >> 22,
+ (version & 0x003FF000) >> 12,
+ version & 0x00000FFF);
+}
+
+deUint32 pack (const ApiVersion& version)
+{
+ DE_ASSERT((version.majorNum & ~0x3FF) == 0);
+ DE_ASSERT((version.minorNum & ~0x3FF) == 0);
+ DE_ASSERT((version.patchNum & ~0xFFF) == 0);
+
+ return (version.majorNum << 22) | (version.minorNum << 12) | version.patchNum;
+}
+
+} // vk
--- /dev/null
+#ifndef _VKAPIVERSION_HPP
+#define _VKAPIVERSION_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Vulkan api version.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkDefs.hpp"
+
+#include <ostream>
+
+namespace vk
+{
+
+struct ApiVersion
+{
+ deUint32 majorNum;
+ deUint32 minorNum;
+ deUint32 patchNum;
+
+ ApiVersion (deUint32 majorNum_,
+ deUint32 minorNum_,
+ deUint32 patchNum_)
+ : majorNum (majorNum_)
+ , minorNum (minorNum_)
+ , patchNum (patchNum_)
+ {
+ }
+};
+
+ApiVersion unpackVersion (deUint32 version);
+deUint32 pack (const ApiVersion& version);
+
+inline std::ostream& operator<< (std::ostream& s, const ApiVersion& version)
+{
+ return s << version.majorNum << "." << version.minorNum << "." << version.patchNum;
+}
+
+} // vk
+
+#endif // _VKAPIVERSION_HPP
--- /dev/null
+/* WARNING: This is auto-generated file. Do not modify, since changes will
+ * be lost! Modify the generating script instead.
+ */
+enum { VK_API_VERSION = VK_MAKE_VERSION(0, 210, 1) };
+enum { VK_MAX_PHYSICAL_DEVICE_NAME_SIZE = 256 };
+enum { VK_MAX_EXTENSION_NAME_SIZE = 256 };
+enum { VK_UUID_SIZE = 16 };
+enum { VK_MAX_MEMORY_TYPES = 32 };
+enum { VK_MAX_MEMORY_HEAPS = 16 };
+enum { VK_MAX_DESCRIPTION_SIZE = 256 };
+enum { VK_ATTACHMENT_UNUSED = (~0U) };
+
+VK_DEFINE_HANDLE (VkInstance, HANDLE_TYPE_INSTANCE);
+VK_DEFINE_HANDLE (VkPhysicalDevice, HANDLE_TYPE_PHYSICAL_DEVICE);
+VK_DEFINE_HANDLE (VkDevice, HANDLE_TYPE_DEVICE);
+VK_DEFINE_HANDLE (VkQueue, HANDLE_TYPE_QUEUE);
+VK_DEFINE_NON_DISPATCHABLE_HANDLE (VkSemaphore, HANDLE_TYPE_SEMAPHORE);
+VK_DEFINE_HANDLE (VkCommandBuffer, HANDLE_TYPE_COMMAND_BUFFER);
+VK_DEFINE_NON_DISPATCHABLE_HANDLE (VkFence, HANDLE_TYPE_FENCE);
+VK_DEFINE_NON_DISPATCHABLE_HANDLE (VkDeviceMemory, HANDLE_TYPE_DEVICE_MEMORY);
+VK_DEFINE_NON_DISPATCHABLE_HANDLE (VkBuffer, HANDLE_TYPE_BUFFER);
+VK_DEFINE_NON_DISPATCHABLE_HANDLE (VkImage, HANDLE_TYPE_IMAGE);
+VK_DEFINE_NON_DISPATCHABLE_HANDLE (VkEvent, HANDLE_TYPE_EVENT);
+VK_DEFINE_NON_DISPATCHABLE_HANDLE (VkQueryPool, HANDLE_TYPE_QUERY_POOL);
+VK_DEFINE_NON_DISPATCHABLE_HANDLE (VkBufferView, HANDLE_TYPE_BUFFER_VIEW);
+VK_DEFINE_NON_DISPATCHABLE_HANDLE (VkImageView, HANDLE_TYPE_IMAGE_VIEW);
+VK_DEFINE_NON_DISPATCHABLE_HANDLE (VkShaderModule, HANDLE_TYPE_SHADER_MODULE);
+VK_DEFINE_NON_DISPATCHABLE_HANDLE (VkPipelineCache, HANDLE_TYPE_PIPELINE_CACHE);
+VK_DEFINE_NON_DISPATCHABLE_HANDLE (VkPipelineLayout, HANDLE_TYPE_PIPELINE_LAYOUT);
+VK_DEFINE_NON_DISPATCHABLE_HANDLE (VkRenderPass, HANDLE_TYPE_RENDER_PASS);
+VK_DEFINE_NON_DISPATCHABLE_HANDLE (VkPipeline, HANDLE_TYPE_PIPELINE);
+VK_DEFINE_NON_DISPATCHABLE_HANDLE (VkDescriptorSetLayout, HANDLE_TYPE_DESCRIPTOR_SET_LAYOUT);
+VK_DEFINE_NON_DISPATCHABLE_HANDLE (VkSampler, HANDLE_TYPE_SAMPLER);
+VK_DEFINE_NON_DISPATCHABLE_HANDLE (VkDescriptorPool, HANDLE_TYPE_DESCRIPTOR_POOL);
+VK_DEFINE_NON_DISPATCHABLE_HANDLE (VkDescriptorSet, HANDLE_TYPE_DESCRIPTOR_SET);
+VK_DEFINE_NON_DISPATCHABLE_HANDLE (VkFramebuffer, HANDLE_TYPE_FRAMEBUFFER);
+VK_DEFINE_NON_DISPATCHABLE_HANDLE (VkCommandPool, HANDLE_TYPE_COMMAND_POOL);
+VK_DEFINE_NON_DISPATCHABLE_HANDLE (VkSurfaceKHR, HANDLE_TYPE_SURFACE_KHR);
+VK_DEFINE_NON_DISPATCHABLE_HANDLE (VkSwapchainKHR, HANDLE_TYPE_SWAPCHAIN_KHR);
+VK_DEFINE_NON_DISPATCHABLE_HANDLE (VkDisplayKHR, HANDLE_TYPE_DISPLAY_KHR);
+VK_DEFINE_NON_DISPATCHABLE_HANDLE (VkDisplayModeKHR, HANDLE_TYPE_DISPLAY_MODE_KHR);
+
+enum VkResult
+{
+ VK_SUCCESS = 0,
+ VK_NOT_READY = 1,
+ VK_TIMEOUT = 2,
+ VK_EVENT_SET = 3,
+ VK_EVENT_RESET = 4,
+ VK_INCOMPLETE = 5,
+ VK_ERROR_OUT_OF_HOST_MEMORY = -1,
+ VK_ERROR_OUT_OF_DEVICE_MEMORY = -2,
+ VK_ERROR_INITIALIZATION_FAILED = -3,
+ VK_ERROR_DEVICE_LOST = -4,
+ VK_ERROR_MEMORY_MAP_FAILED = -5,
+ VK_ERROR_LAYER_NOT_PRESENT = -6,
+ VK_ERROR_EXTENSION_NOT_PRESENT = -7,
+ VK_ERROR_FEATURE_NOT_PRESENT = -8,
+ VK_ERROR_INCOMPATIBLE_DRIVER = -9,
+ VK_ERROR_TOO_MANY_OBJECTS = -10,
+ VK_ERROR_FORMAT_NOT_SUPPORTED = -11,
+ VK_ERROR_SURFACE_LOST_KHR = -1000000000,
+ VK_SUBOPTIMAL_KHR = 1000001003,
+ VK_ERROR_OUT_OF_DATE_KHR = -1000001004,
+ VK_ERROR_INCOMPATIBLE_DISPLAY_KHR = -1000003001,
+ VK_ERROR_NATIVE_WINDOW_IN_USE_KHR = -1000008000,
+};
+
+enum VkStructureType
+{
+ VK_STRUCTURE_TYPE_APPLICATION_INFO = 0,
+ VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO = 1,
+ VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO = 2,
+ VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO = 3,
+ VK_STRUCTURE_TYPE_SUBMIT_INFO = 4,
+ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO = 5,
+ VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE = 6,
+ VK_STRUCTURE_TYPE_BIND_SPARSE_INFO = 7,
+ VK_STRUCTURE_TYPE_FENCE_CREATE_INFO = 8,
+ VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO = 9,
+ VK_STRUCTURE_TYPE_EVENT_CREATE_INFO = 10,
+ VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO = 11,
+ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO = 12,
+ VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO = 13,
+ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO = 14,
+ VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO = 15,
+ VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO = 16,
+ VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO = 17,
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO = 18,
+ VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO = 19,
+ VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO = 20,
+ VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO = 21,
+ VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO = 22,
+ VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO = 23,
+ VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO = 24,
+ VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO = 25,
+ VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO = 26,
+ VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO = 27,
+ VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO = 28,
+ VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO = 29,
+ VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO = 30,
+ VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO = 31,
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO = 32,
+ VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO = 33,
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO = 34,
+ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET = 35,
+ VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET = 36,
+ VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO = 37,
+ VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO = 38,
+ VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO = 39,
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO = 40,
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO = 41,
+ VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO = 42,
+ VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER = 43,
+ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER = 44,
+ VK_STRUCTURE_TYPE_MEMORY_BARRIER = 45,
+ VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO = 46,
+ VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO = 47,
+ VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR = 1000001000,
+ VK_STRUCTURE_TYPE_PRESENT_INFO_KHR = 1000001001,
+ VK_STRUCTURE_TYPE_DISPLAY_MODE_CREATE_INFO_KHR = 1000002000,
+ VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR = 1000002001,
+ VK_STRUCTURE_TYPE_DISPLAY_PRESENT_INFO_KHR = 1000003000,
+};
+
+enum VkSystemAllocationScope
+{
+ VK_SYSTEM_ALLOCATION_SCOPE_COMMAND = 0,
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT = 1,
+ VK_SYSTEM_ALLOCATION_SCOPE_CACHE = 2,
+ VK_SYSTEM_ALLOCATION_SCOPE_DEVICE = 3,
+ VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE = 4,
+
+ VK_SYSTEM_ALLOCATION_SCOPE_LAST
+};
+
+enum VkInternalAllocationType
+{
+ VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE = 0,
+
+ VK_INTERNAL_ALLOCATION_TYPE_LAST
+};
+
+enum VkFormat
+{
+ VK_FORMAT_UNDEFINED = 0,
+ VK_FORMAT_R4G4_UNORM_PACK8 = 1,
+ VK_FORMAT_R4G4B4A4_UNORM_PACK16 = 2,
+ VK_FORMAT_B4G4R4A4_UNORM_PACK16 = 3,
+ VK_FORMAT_R5G6B5_UNORM_PACK16 = 4,
+ VK_FORMAT_B5G6R5_UNORM_PACK16 = 5,
+ VK_FORMAT_R5G5B5A1_UNORM_PACK16 = 6,
+ VK_FORMAT_B5G5R5A1_UNORM_PACK16 = 7,
+ VK_FORMAT_A1R5G5B5_UNORM_PACK16 = 8,
+ VK_FORMAT_R8_UNORM = 9,
+ VK_FORMAT_R8_SNORM = 10,
+ VK_FORMAT_R8_USCALED = 11,
+ VK_FORMAT_R8_SSCALED = 12,
+ VK_FORMAT_R8_UINT = 13,
+ VK_FORMAT_R8_SINT = 14,
+ VK_FORMAT_R8_SRGB = 15,
+ VK_FORMAT_R8G8_UNORM = 16,
+ VK_FORMAT_R8G8_SNORM = 17,
+ VK_FORMAT_R8G8_USCALED = 18,
+ VK_FORMAT_R8G8_SSCALED = 19,
+ VK_FORMAT_R8G8_UINT = 20,
+ VK_FORMAT_R8G8_SINT = 21,
+ VK_FORMAT_R8G8_SRGB = 22,
+ VK_FORMAT_R8G8B8_UNORM = 23,
+ VK_FORMAT_R8G8B8_SNORM = 24,
+ VK_FORMAT_R8G8B8_USCALED = 25,
+ VK_FORMAT_R8G8B8_SSCALED = 26,
+ VK_FORMAT_R8G8B8_UINT = 27,
+ VK_FORMAT_R8G8B8_SINT = 28,
+ VK_FORMAT_R8G8B8_SRGB = 29,
+ VK_FORMAT_B8G8R8_UNORM = 30,
+ VK_FORMAT_B8G8R8_SNORM = 31,
+ VK_FORMAT_B8G8R8_USCALED = 32,
+ VK_FORMAT_B8G8R8_SSCALED = 33,
+ VK_FORMAT_B8G8R8_UINT = 34,
+ VK_FORMAT_B8G8R8_SINT = 35,
+ VK_FORMAT_B8G8R8_SRGB = 36,
+ VK_FORMAT_R8G8B8A8_UNORM = 37,
+ VK_FORMAT_R8G8B8A8_SNORM = 38,
+ VK_FORMAT_R8G8B8A8_USCALED = 39,
+ VK_FORMAT_R8G8B8A8_SSCALED = 40,
+ VK_FORMAT_R8G8B8A8_UINT = 41,
+ VK_FORMAT_R8G8B8A8_SINT = 42,
+ VK_FORMAT_R8G8B8A8_SRGB = 43,
+ VK_FORMAT_B8G8R8A8_UNORM = 44,
+ VK_FORMAT_B8G8R8A8_SNORM = 45,
+ VK_FORMAT_B8G8R8A8_USCALED = 46,
+ VK_FORMAT_B8G8R8A8_SSCALED = 47,
+ VK_FORMAT_B8G8R8A8_UINT = 48,
+ VK_FORMAT_B8G8R8A8_SINT = 49,
+ VK_FORMAT_B8G8R8A8_SRGB = 50,
+ VK_FORMAT_A8B8G8R8_UNORM_PACK32 = 51,
+ VK_FORMAT_A8B8G8R8_SNORM_PACK32 = 52,
+ VK_FORMAT_A8B8G8R8_USCALED_PACK32 = 53,
+ VK_FORMAT_A8B8G8R8_SSCALED_PACK32 = 54,
+ VK_FORMAT_A8B8G8R8_UINT_PACK32 = 55,
+ VK_FORMAT_A8B8G8R8_SINT_PACK32 = 56,
+ VK_FORMAT_A8B8G8R8_SRGB_PACK32 = 57,
+ VK_FORMAT_A2R10G10B10_UNORM_PACK32 = 58,
+ VK_FORMAT_A2R10G10B10_SNORM_PACK32 = 59,
+ VK_FORMAT_A2R10G10B10_USCALED_PACK32 = 60,
+ VK_FORMAT_A2R10G10B10_SSCALED_PACK32 = 61,
+ VK_FORMAT_A2R10G10B10_UINT_PACK32 = 62,
+ VK_FORMAT_A2R10G10B10_SINT_PACK32 = 63,
+ VK_FORMAT_A2B10G10R10_UNORM_PACK32 = 64,
+ VK_FORMAT_A2B10G10R10_SNORM_PACK32 = 65,
+ VK_FORMAT_A2B10G10R10_USCALED_PACK32 = 66,
+ VK_FORMAT_A2B10G10R10_SSCALED_PACK32 = 67,
+ VK_FORMAT_A2B10G10R10_UINT_PACK32 = 68,
+ VK_FORMAT_A2B10G10R10_SINT_PACK32 = 69,
+ VK_FORMAT_R16_UNORM = 70,
+ VK_FORMAT_R16_SNORM = 71,
+ VK_FORMAT_R16_USCALED = 72,
+ VK_FORMAT_R16_SSCALED = 73,
+ VK_FORMAT_R16_UINT = 74,
+ VK_FORMAT_R16_SINT = 75,
+ VK_FORMAT_R16_SFLOAT = 76,
+ VK_FORMAT_R16G16_UNORM = 77,
+ VK_FORMAT_R16G16_SNORM = 78,
+ VK_FORMAT_R16G16_USCALED = 79,
+ VK_FORMAT_R16G16_SSCALED = 80,
+ VK_FORMAT_R16G16_UINT = 81,
+ VK_FORMAT_R16G16_SINT = 82,
+ VK_FORMAT_R16G16_SFLOAT = 83,
+ VK_FORMAT_R16G16B16_UNORM = 84,
+ VK_FORMAT_R16G16B16_SNORM = 85,
+ VK_FORMAT_R16G16B16_USCALED = 86,
+ VK_FORMAT_R16G16B16_SSCALED = 87,
+ VK_FORMAT_R16G16B16_UINT = 88,
+ VK_FORMAT_R16G16B16_SINT = 89,
+ VK_FORMAT_R16G16B16_SFLOAT = 90,
+ VK_FORMAT_R16G16B16A16_UNORM = 91,
+ VK_FORMAT_R16G16B16A16_SNORM = 92,
+ VK_FORMAT_R16G16B16A16_USCALED = 93,
+ VK_FORMAT_R16G16B16A16_SSCALED = 94,
+ VK_FORMAT_R16G16B16A16_UINT = 95,
+ VK_FORMAT_R16G16B16A16_SINT = 96,
+ VK_FORMAT_R16G16B16A16_SFLOAT = 97,
+ VK_FORMAT_R32_UINT = 98,
+ VK_FORMAT_R32_SINT = 99,
+ VK_FORMAT_R32_SFLOAT = 100,
+ VK_FORMAT_R32G32_UINT = 101,
+ VK_FORMAT_R32G32_SINT = 102,
+ VK_FORMAT_R32G32_SFLOAT = 103,
+ VK_FORMAT_R32G32B32_UINT = 104,
+ VK_FORMAT_R32G32B32_SINT = 105,
+ VK_FORMAT_R32G32B32_SFLOAT = 106,
+ VK_FORMAT_R32G32B32A32_UINT = 107,
+ VK_FORMAT_R32G32B32A32_SINT = 108,
+ VK_FORMAT_R32G32B32A32_SFLOAT = 109,
+ VK_FORMAT_R64_UINT = 110,
+ VK_FORMAT_R64_SINT = 111,
+ VK_FORMAT_R64_SFLOAT = 112,
+ VK_FORMAT_R64G64_UINT = 113,
+ VK_FORMAT_R64G64_SINT = 114,
+ VK_FORMAT_R64G64_SFLOAT = 115,
+ VK_FORMAT_R64G64B64_UINT = 116,
+ VK_FORMAT_R64G64B64_SINT = 117,
+ VK_FORMAT_R64G64B64_SFLOAT = 118,
+ VK_FORMAT_R64G64B64A64_UINT = 119,
+ VK_FORMAT_R64G64B64A64_SINT = 120,
+ VK_FORMAT_R64G64B64A64_SFLOAT = 121,
+ VK_FORMAT_B10G11R11_UFLOAT_PACK32 = 122,
+ VK_FORMAT_E5B9G9R9_UFLOAT_PACK32 = 123,
+ VK_FORMAT_D16_UNORM = 124,
+ VK_FORMAT_X8_D24_UNORM_PACK32 = 125,
+ VK_FORMAT_D32_SFLOAT = 126,
+ VK_FORMAT_S8_UINT = 127,
+ VK_FORMAT_D16_UNORM_S8_UINT = 128,
+ VK_FORMAT_D24_UNORM_S8_UINT = 129,
+ VK_FORMAT_D32_SFLOAT_S8_UINT = 130,
+ VK_FORMAT_BC1_RGB_UNORM_BLOCK = 131,
+ VK_FORMAT_BC1_RGB_SRGB_BLOCK = 132,
+ VK_FORMAT_BC1_RGBA_UNORM_BLOCK = 133,
+ VK_FORMAT_BC1_RGBA_SRGB_BLOCK = 134,
+ VK_FORMAT_BC2_UNORM_BLOCK = 135,
+ VK_FORMAT_BC2_SRGB_BLOCK = 136,
+ VK_FORMAT_BC3_UNORM_BLOCK = 137,
+ VK_FORMAT_BC3_SRGB_BLOCK = 138,
+ VK_FORMAT_BC4_UNORM_BLOCK = 139,
+ VK_FORMAT_BC4_SNORM_BLOCK = 140,
+ VK_FORMAT_BC5_UNORM_BLOCK = 141,
+ VK_FORMAT_BC5_SNORM_BLOCK = 142,
+ VK_FORMAT_BC6H_UFLOAT_BLOCK = 143,
+ VK_FORMAT_BC6H_SFLOAT_BLOCK = 144,
+ VK_FORMAT_BC7_UNORM_BLOCK = 145,
+ VK_FORMAT_BC7_SRGB_BLOCK = 146,
+ VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK = 147,
+ VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK = 148,
+ VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK = 149,
+ VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK = 150,
+ VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK = 151,
+ VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK = 152,
+ VK_FORMAT_EAC_R11_UNORM_BLOCK = 153,
+ VK_FORMAT_EAC_R11_SNORM_BLOCK = 154,
+ VK_FORMAT_EAC_R11G11_UNORM_BLOCK = 155,
+ VK_FORMAT_EAC_R11G11_SNORM_BLOCK = 156,
+ VK_FORMAT_ASTC_4x4_UNORM_BLOCK = 157,
+ VK_FORMAT_ASTC_4x4_SRGB_BLOCK = 158,
+ VK_FORMAT_ASTC_5x4_UNORM_BLOCK = 159,
+ VK_FORMAT_ASTC_5x4_SRGB_BLOCK = 160,
+ VK_FORMAT_ASTC_5x5_UNORM_BLOCK = 161,
+ VK_FORMAT_ASTC_5x5_SRGB_BLOCK = 162,
+ VK_FORMAT_ASTC_6x5_UNORM_BLOCK = 163,
+ VK_FORMAT_ASTC_6x5_SRGB_BLOCK = 164,
+ VK_FORMAT_ASTC_6x6_UNORM_BLOCK = 165,
+ VK_FORMAT_ASTC_6x6_SRGB_BLOCK = 166,
+ VK_FORMAT_ASTC_8x5_UNORM_BLOCK = 167,
+ VK_FORMAT_ASTC_8x5_SRGB_BLOCK = 168,
+ VK_FORMAT_ASTC_8x6_UNORM_BLOCK = 169,
+ VK_FORMAT_ASTC_8x6_SRGB_BLOCK = 170,
+ VK_FORMAT_ASTC_8x8_UNORM_BLOCK = 171,
+ VK_FORMAT_ASTC_8x8_SRGB_BLOCK = 172,
+ VK_FORMAT_ASTC_10x5_UNORM_BLOCK = 173,
+ VK_FORMAT_ASTC_10x5_SRGB_BLOCK = 174,
+ VK_FORMAT_ASTC_10x6_UNORM_BLOCK = 175,
+ VK_FORMAT_ASTC_10x6_SRGB_BLOCK = 176,
+ VK_FORMAT_ASTC_10x8_UNORM_BLOCK = 177,
+ VK_FORMAT_ASTC_10x8_SRGB_BLOCK = 178,
+ VK_FORMAT_ASTC_10x10_UNORM_BLOCK = 179,
+ VK_FORMAT_ASTC_10x10_SRGB_BLOCK = 180,
+ VK_FORMAT_ASTC_12x10_UNORM_BLOCK = 181,
+ VK_FORMAT_ASTC_12x10_SRGB_BLOCK = 182,
+ VK_FORMAT_ASTC_12x12_UNORM_BLOCK = 183,
+ VK_FORMAT_ASTC_12x12_SRGB_BLOCK = 184,
+
+ VK_FORMAT_LAST
+};
+
+enum VkImageType
+{
+ VK_IMAGE_TYPE_1D = 0,
+ VK_IMAGE_TYPE_2D = 1,
+ VK_IMAGE_TYPE_3D = 2,
+
+ VK_IMAGE_TYPE_LAST
+};
+
+enum VkImageTiling
+{
+ VK_IMAGE_TILING_OPTIMAL = 0,
+ VK_IMAGE_TILING_LINEAR = 1,
+
+ VK_IMAGE_TILING_LAST
+};
+
+enum VkPhysicalDeviceType
+{
+ VK_PHYSICAL_DEVICE_TYPE_OTHER = 0,
+ VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU = 1,
+ VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU = 2,
+ VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU = 3,
+ VK_PHYSICAL_DEVICE_TYPE_CPU = 4,
+
+ VK_PHYSICAL_DEVICE_TYPE_LAST
+};
+
+enum VkQueryType
+{
+ VK_QUERY_TYPE_OCCLUSION = 0,
+ VK_QUERY_TYPE_PIPELINE_STATISTICS = 1,
+ VK_QUERY_TYPE_TIMESTAMP = 2,
+
+ VK_QUERY_TYPE_LAST
+};
+
+enum VkSharingMode
+{
+ VK_SHARING_MODE_EXCLUSIVE = 0,
+ VK_SHARING_MODE_CONCURRENT = 1,
+
+ VK_SHARING_MODE_LAST
+};
+
+enum VkImageLayout
+{
+ VK_IMAGE_LAYOUT_UNDEFINED = 0,
+ VK_IMAGE_LAYOUT_GENERAL = 1,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL = 2,
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL = 3,
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL = 4,
+ VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL = 5,
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL = 6,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL = 7,
+ VK_IMAGE_LAYOUT_PREINITIALIZED = 8,
+ VK_IMAGE_LAYOUT_PRESENT_SRC_KHR = 1000001002,
+};
+
+enum VkImageViewType
+{
+ VK_IMAGE_VIEW_TYPE_1D = 0,
+ VK_IMAGE_VIEW_TYPE_2D = 1,
+ VK_IMAGE_VIEW_TYPE_3D = 2,
+ VK_IMAGE_VIEW_TYPE_CUBE = 3,
+ VK_IMAGE_VIEW_TYPE_1D_ARRAY = 4,
+ VK_IMAGE_VIEW_TYPE_2D_ARRAY = 5,
+ VK_IMAGE_VIEW_TYPE_CUBE_ARRAY = 6,
+
+ VK_IMAGE_VIEW_TYPE_LAST
+};
+
+enum VkComponentSwizzle
+{
+ VK_COMPONENT_SWIZZLE_IDENTITY = 0,
+ VK_COMPONENT_SWIZZLE_ZERO = 1,
+ VK_COMPONENT_SWIZZLE_ONE = 2,
+ VK_COMPONENT_SWIZZLE_R = 3,
+ VK_COMPONENT_SWIZZLE_G = 4,
+ VK_COMPONENT_SWIZZLE_B = 5,
+ VK_COMPONENT_SWIZZLE_A = 6,
+
+ VK_COMPONENT_SWIZZLE_LAST
+};
+
+enum VkVertexInputRate
+{
+ VK_VERTEX_INPUT_RATE_VERTEX = 0,
+ VK_VERTEX_INPUT_RATE_INSTANCE = 1,
+
+ VK_VERTEX_INPUT_RATE_LAST
+};
+
+enum VkPrimitiveTopology
+{
+ VK_PRIMITIVE_TOPOLOGY_POINT_LIST = 0,
+ VK_PRIMITIVE_TOPOLOGY_LINE_LIST = 1,
+ VK_PRIMITIVE_TOPOLOGY_LINE_STRIP = 2,
+ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST = 3,
+ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP = 4,
+ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN = 5,
+ VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY = 6,
+ VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY = 7,
+ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY = 8,
+ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY = 9,
+ VK_PRIMITIVE_TOPOLOGY_PATCH_LIST = 10,
+
+ VK_PRIMITIVE_TOPOLOGY_LAST
+};
+
+enum VkPolygonMode
+{
+ VK_POLYGON_MODE_FILL = 0,
+ VK_POLYGON_MODE_LINE = 1,
+ VK_POLYGON_MODE_POINT = 2,
+
+ VK_POLYGON_MODE_LAST
+};
+
+enum VkFrontFace
+{
+ VK_FRONT_FACE_COUNTER_CLOCKWISE = 0,
+ VK_FRONT_FACE_CLOCKWISE = 1,
+
+ VK_FRONT_FACE_LAST
+};
+
+enum VkCompareOp
+{
+ VK_COMPARE_OP_NEVER = 0,
+ VK_COMPARE_OP_LESS = 1,
+ VK_COMPARE_OP_EQUAL = 2,
+ VK_COMPARE_OP_LESS_OR_EQUAL = 3,
+ VK_COMPARE_OP_GREATER = 4,
+ VK_COMPARE_OP_NOT_EQUAL = 5,
+ VK_COMPARE_OP_GREATER_OR_EQUAL = 6,
+ VK_COMPARE_OP_ALWAYS = 7,
+
+ VK_COMPARE_OP_LAST
+};
+
+enum VkStencilOp
+{
+ VK_STENCIL_OP_KEEP = 0,
+ VK_STENCIL_OP_ZERO = 1,
+ VK_STENCIL_OP_REPLACE = 2,
+ VK_STENCIL_OP_INCREMENT_AND_CLAMP = 3,
+ VK_STENCIL_OP_DECREMENT_AND_CLAMP = 4,
+ VK_STENCIL_OP_INVERT = 5,
+ VK_STENCIL_OP_INCREMENT_AND_WRAP = 6,
+ VK_STENCIL_OP_DECREMENT_AND_WRAP = 7,
+
+ VK_STENCIL_OP_LAST
+};
+
+enum VkLogicOp
+{
+ VK_LOGIC_OP_CLEAR = 0,
+ VK_LOGIC_OP_AND = 1,
+ VK_LOGIC_OP_AND_REVERSE = 2,
+ VK_LOGIC_OP_COPY = 3,
+ VK_LOGIC_OP_AND_INVERTED = 4,
+ VK_LOGIC_OP_NO_OP = 5,
+ VK_LOGIC_OP_XOR = 6,
+ VK_LOGIC_OP_OR = 7,
+ VK_LOGIC_OP_NOR = 8,
+ VK_LOGIC_OP_EQUIVALENT = 9,
+ VK_LOGIC_OP_INVERT = 10,
+ VK_LOGIC_OP_OR_REVERSE = 11,
+ VK_LOGIC_OP_COPY_INVERTED = 12,
+ VK_LOGIC_OP_OR_INVERTED = 13,
+ VK_LOGIC_OP_NAND = 14,
+ VK_LOGIC_OP_SET = 15,
+
+ VK_LOGIC_OP_LAST
+};
+
+enum VkBlendFactor
+{
+ VK_BLEND_FACTOR_ZERO = 0,
+ VK_BLEND_FACTOR_ONE = 1,
+ VK_BLEND_FACTOR_SRC_COLOR = 2,
+ VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR = 3,
+ VK_BLEND_FACTOR_DST_COLOR = 4,
+ VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR = 5,
+ VK_BLEND_FACTOR_SRC_ALPHA = 6,
+ VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA = 7,
+ VK_BLEND_FACTOR_DST_ALPHA = 8,
+ VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA = 9,
+ VK_BLEND_FACTOR_CONSTANT_COLOR = 10,
+ VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR = 11,
+ VK_BLEND_FACTOR_CONSTANT_ALPHA = 12,
+ VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA = 13,
+ VK_BLEND_FACTOR_SRC_ALPHA_SATURATE = 14,
+ VK_BLEND_FACTOR_SRC1_COLOR = 15,
+ VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR = 16,
+ VK_BLEND_FACTOR_SRC1_ALPHA = 17,
+ VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA = 18,
+
+ VK_BLEND_FACTOR_LAST
+};
+
+enum VkBlendOp
+{
+ VK_BLEND_OP_ADD = 0,
+ VK_BLEND_OP_SUBTRACT = 1,
+ VK_BLEND_OP_REVERSE_SUBTRACT = 2,
+ VK_BLEND_OP_MIN = 3,
+ VK_BLEND_OP_MAX = 4,
+
+ VK_BLEND_OP_LAST
+};
+
+enum VkDynamicState
+{
+ VK_DYNAMIC_STATE_VIEWPORT = 0,
+ VK_DYNAMIC_STATE_SCISSOR = 1,
+ VK_DYNAMIC_STATE_LINE_WIDTH = 2,
+ VK_DYNAMIC_STATE_DEPTH_BIAS = 3,
+ VK_DYNAMIC_STATE_BLEND_CONSTANTS = 4,
+ VK_DYNAMIC_STATE_DEPTH_BOUNDS = 5,
+ VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK = 6,
+ VK_DYNAMIC_STATE_STENCIL_WRITE_MASK = 7,
+ VK_DYNAMIC_STATE_STENCIL_REFERENCE = 8,
+
+ VK_DYNAMIC_STATE_LAST
+};
+
+enum VkFilter
+{
+ VK_FILTER_NEAREST = 0,
+ VK_FILTER_LINEAR = 1,
+
+ VK_FILTER_LAST
+};
+
+enum VkSamplerMipmapMode
+{
+ VK_SAMPLER_MIPMAP_MODE_BASE = 0,
+ VK_SAMPLER_MIPMAP_MODE_NEAREST = 1,
+ VK_SAMPLER_MIPMAP_MODE_LINEAR = 2,
+
+ VK_SAMPLER_MIPMAP_MODE_LAST
+};
+
+enum VkSamplerAddressMode
+{
+ VK_SAMPLER_ADDRESS_MODE_REPEAT = 0,
+ VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT = 1,
+ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE = 2,
+ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER = 3,
+ VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE = 4,
+
+ VK_SAMPLER_ADDRESS_MODE_LAST
+};
+
+enum VkBorderColor
+{
+ VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK = 0,
+ VK_BORDER_COLOR_INT_TRANSPARENT_BLACK = 1,
+ VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK = 2,
+ VK_BORDER_COLOR_INT_OPAQUE_BLACK = 3,
+ VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE = 4,
+ VK_BORDER_COLOR_INT_OPAQUE_WHITE = 5,
+
+ VK_BORDER_COLOR_LAST
+};
+
+enum VkDescriptorType
+{
+ VK_DESCRIPTOR_TYPE_SAMPLER = 0,
+ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER = 1,
+ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE = 2,
+ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE = 3,
+ VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER = 4,
+ VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER = 5,
+ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER = 6,
+ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER = 7,
+ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC = 8,
+ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC = 9,
+ VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT = 10,
+
+ VK_DESCRIPTOR_TYPE_LAST
+};
+
+enum VkAttachmentLoadOp
+{
+ VK_ATTACHMENT_LOAD_OP_LOAD = 0,
+ VK_ATTACHMENT_LOAD_OP_CLEAR = 1,
+ VK_ATTACHMENT_LOAD_OP_DONT_CARE = 2,
+
+ VK_ATTACHMENT_LOAD_OP_LAST
+};
+
+enum VkAttachmentStoreOp
+{
+ VK_ATTACHMENT_STORE_OP_STORE = 0,
+ VK_ATTACHMENT_STORE_OP_DONT_CARE = 1,
+
+ VK_ATTACHMENT_STORE_OP_LAST
+};
+
+enum VkPipelineBindPoint
+{
+ VK_PIPELINE_BIND_POINT_GRAPHICS = 0,
+ VK_PIPELINE_BIND_POINT_COMPUTE = 1,
+
+ VK_PIPELINE_BIND_POINT_LAST
+};
+
+enum VkCommandBufferLevel
+{
+ VK_COMMAND_BUFFER_LEVEL_PRIMARY = 0,
+ VK_COMMAND_BUFFER_LEVEL_SECONDARY = 1,
+
+ VK_COMMAND_BUFFER_LEVEL_LAST
+};
+
+enum VkIndexType
+{
+ VK_INDEX_TYPE_UINT16 = 0,
+ VK_INDEX_TYPE_UINT32 = 1,
+
+ VK_INDEX_TYPE_LAST
+};
+
+enum VkSubpassContents
+{
+ VK_SUBPASS_CONTENTS_INLINE = 0,
+ VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS = 1,
+
+ VK_SUBPASS_CONTENTS_LAST
+};
+
+enum VkColorSpaceKHR
+{
+ VK_COLORSPACE_SRGB_NONLINEAR_KHR = 0,
+
+ VK_COLOR_SPACE_K_H_R_LAST
+};
+
+enum VkPresentModeKHR
+{
+ VK_PRESENT_MODE_IMMEDIATE_KHR = 0,
+ VK_PRESENT_MODE_MAILBOX_KHR = 1,
+ VK_PRESENT_MODE_FIFO_KHR = 2,
+ VK_PRESENT_MODE_FIFO_RELAXED_KHR = 3,
+
+ VK_PRESENT_MODE_K_H_R_LAST
+};
+
+enum VkFormatFeatureFlagBits
+{
+ VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT = 0x00000001,
+ VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT = 0x00000002,
+ VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT = 0x00000004,
+ VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT = 0x00000008,
+ VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT = 0x00000010,
+ VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT = 0x00000020,
+ VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT = 0x00000040,
+ VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT = 0x00000080,
+ VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT = 0x00000100,
+ VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000200,
+ VK_FORMAT_FEATURE_BLIT_SRC_BIT = 0x00000400,
+ VK_FORMAT_FEATURE_BLIT_DST_BIT = 0x00000800,
+};
+typedef deUint32 VkFormatFeatureFlags;
+
+enum VkImageUsageFlagBits
+{
+ VK_IMAGE_USAGE_TRANSFER_SRC_BIT = 0x00000001,
+ VK_IMAGE_USAGE_TRANSFER_DST_BIT = 0x00000002,
+ VK_IMAGE_USAGE_SAMPLED_BIT = 0x00000004,
+ VK_IMAGE_USAGE_STORAGE_BIT = 0x00000008,
+ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT = 0x00000010,
+ VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000020,
+ VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT = 0x00000040,
+ VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT = 0x00000080,
+};
+typedef deUint32 VkImageUsageFlags;
+
+enum VkImageCreateFlagBits
+{
+ VK_IMAGE_CREATE_SPARSE_BINDING_BIT = 0x00000001,
+ VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT = 0x00000002,
+ VK_IMAGE_CREATE_SPARSE_ALIASED_BIT = 0x00000004,
+ VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT = 0x00000008,
+ VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT = 0x00000010,
+};
+typedef deUint32 VkImageCreateFlags;
+
+enum VkSampleCountFlagBits
+{
+ VK_SAMPLE_COUNT_1_BIT = 0x00000001,
+ VK_SAMPLE_COUNT_2_BIT = 0x00000002,
+ VK_SAMPLE_COUNT_4_BIT = 0x00000004,
+ VK_SAMPLE_COUNT_8_BIT = 0x00000008,
+ VK_SAMPLE_COUNT_16_BIT = 0x00000010,
+ VK_SAMPLE_COUNT_32_BIT = 0x00000020,
+ VK_SAMPLE_COUNT_64_BIT = 0x00000040,
+};
+typedef deUint32 VkSampleCountFlags;
+
+enum VkQueueFlagBits
+{
+ VK_QUEUE_GRAPHICS_BIT = 0x00000001,
+ VK_QUEUE_COMPUTE_BIT = 0x00000002,
+ VK_QUEUE_TRANSFER_BIT = 0x00000004,
+ VK_QUEUE_SPARSE_BINDING_BIT = 0x00000008,
+};
+typedef deUint32 VkQueueFlags;
+
+enum VkMemoryPropertyFlagBits
+{
+ VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT = 0x00000001,
+ VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT = 0x00000002,
+ VK_MEMORY_PROPERTY_HOST_COHERENT_BIT = 0x00000004,
+ VK_MEMORY_PROPERTY_HOST_CACHED_BIT = 0x00000008,
+ VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT = 0x00000010,
+};
+typedef deUint32 VkMemoryPropertyFlags;
+
+enum VkMemoryHeapFlagBits
+{
+ VK_MEMORY_HEAP_DEVICE_LOCAL_BIT = 0x00000001,
+};
+typedef deUint32 VkMemoryHeapFlags;
+
+enum VkImageAspectFlagBits
+{
+ VK_IMAGE_ASPECT_COLOR_BIT = 0x00000001,
+ VK_IMAGE_ASPECT_DEPTH_BIT = 0x00000002,
+ VK_IMAGE_ASPECT_STENCIL_BIT = 0x00000004,
+ VK_IMAGE_ASPECT_METADATA_BIT = 0x00000008,
+};
+typedef deUint32 VkImageAspectFlags;
+
+enum VkSparseImageFormatFlagBits
+{
+ VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT = 0x00000001,
+ VK_SPARSE_IMAGE_FORMAT_ALIGNED_MIP_SIZE_BIT = 0x00000002,
+ VK_SPARSE_IMAGE_FORMAT_NONSTANDARD_BLOCK_SIZE_BIT = 0x00000004,
+};
+typedef deUint32 VkSparseImageFormatFlags;
+
+enum VkSparseMemoryBindFlagBits
+{
+ VK_SPARSE_MEMORY_BIND_METADATA_BIT = 0x00000001,
+};
+typedef deUint32 VkSparseMemoryBindFlags;
+
+enum VkFenceCreateFlagBits
+{
+ VK_FENCE_CREATE_SIGNALED_BIT = 0x00000001,
+};
+typedef deUint32 VkFenceCreateFlags;
+
+enum VkQueryPipelineStatisticFlagBits
+{
+ VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT = 0x00000001,
+ VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT = 0x00000002,
+ VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT = 0x00000004,
+ VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_INVOCATIONS_BIT = 0x00000008,
+ VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_PRIMITIVES_BIT = 0x00000010,
+ VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT = 0x00000020,
+ VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT = 0x00000040,
+ VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT = 0x00000080,
+ VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT = 0x00000100,
+ VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT = 0x00000200,
+ VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT = 0x00000400,
+};
+typedef deUint32 VkQueryPipelineStatisticFlags;
+
+enum VkQueryResultFlagBits
+{
+ VK_QUERY_RESULT_DEFAULT = 0,
+ VK_QUERY_RESULT_64_BIT = 0x00000001,
+ VK_QUERY_RESULT_WAIT_BIT = 0x00000002,
+ VK_QUERY_RESULT_WITH_AVAILABILITY_BIT = 0x00000004,
+ VK_QUERY_RESULT_PARTIAL_BIT = 0x00000008,
+};
+typedef deUint32 VkQueryResultFlags;
+
+enum VkBufferCreateFlagBits
+{
+ VK_BUFFER_CREATE_SPARSE_BINDING_BIT = 0x00000001,
+ VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT = 0x00000002,
+ VK_BUFFER_CREATE_SPARSE_ALIASED_BIT = 0x00000004,
+};
+typedef deUint32 VkBufferCreateFlags;
+
+enum VkBufferUsageFlagBits
+{
+ VK_BUFFER_USAGE_TRANSFER_SRC_BIT = 0x00000001,
+ VK_BUFFER_USAGE_TRANSFER_DST_BIT = 0x00000002,
+ VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT = 0x00000004,
+ VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT = 0x00000008,
+ VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT = 0x00000010,
+ VK_BUFFER_USAGE_STORAGE_BUFFER_BIT = 0x00000020,
+ VK_BUFFER_USAGE_INDEX_BUFFER_BIT = 0x00000040,
+ VK_BUFFER_USAGE_VERTEX_BUFFER_BIT = 0x00000080,
+ VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT = 0x00000100,
+};
+typedef deUint32 VkBufferUsageFlags;
+
+enum VkPipelineCreateFlagBits
+{
+ VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT = 0x00000001,
+ VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT = 0x00000002,
+ VK_PIPELINE_CREATE_DERIVATIVE_BIT = 0x00000004,
+};
+typedef deUint32 VkPipelineCreateFlags;
+
+enum VkShaderStageFlagBits
+{
+ VK_SHADER_STAGE_VERTEX_BIT = 0x00000001,
+ VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT = 0x00000002,
+ VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT = 0x00000004,
+ VK_SHADER_STAGE_GEOMETRY_BIT = 0x00000008,
+ VK_SHADER_STAGE_FRAGMENT_BIT = 0x00000010,
+ VK_SHADER_STAGE_COMPUTE_BIT = 0x00000020,
+ VK_SHADER_STAGE_ALL_GRAPHICS = 0x1F,
+ VK_SHADER_STAGE_ALL = 0x7FFFFFFF,
+};
+typedef deUint32 VkShaderStageFlags;
+
+enum VkCullModeFlagBits
+{
+ VK_CULL_MODE_NONE = 0,
+ VK_CULL_MODE_FRONT_BIT = 0x00000001,
+ VK_CULL_MODE_BACK_BIT = 0x00000002,
+ VK_CULL_MODE_FRONT_AND_BACK = 0x3,
+};
+typedef deUint32 VkCullModeFlags;
+
+enum VkColorComponentFlagBits
+{
+ VK_COLOR_COMPONENT_R_BIT = 0x00000001,
+ VK_COLOR_COMPONENT_G_BIT = 0x00000002,
+ VK_COLOR_COMPONENT_B_BIT = 0x00000004,
+ VK_COLOR_COMPONENT_A_BIT = 0x00000008,
+};
+typedef deUint32 VkColorComponentFlags;
+
+enum VkDescriptorPoolCreateFlagBits
+{
+ VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT = 0x00000001,
+};
+typedef deUint32 VkDescriptorPoolCreateFlags;
+
+enum VkAttachmentDescriptionFlagBits
+{
+ VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT = 0x00000001,
+};
+typedef deUint32 VkAttachmentDescriptionFlags;
+
+enum VkPipelineStageFlagBits
+{
+ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT = 0x00000001,
+ VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT = 0x00000002,
+ VK_PIPELINE_STAGE_VERTEX_INPUT_BIT = 0x00000004,
+ VK_PIPELINE_STAGE_VERTEX_SHADER_BIT = 0x00000008,
+ VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT = 0x00000010,
+ VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT = 0x00000020,
+ VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT = 0x00000040,
+ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT = 0x00000080,
+ VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT = 0x00000100,
+ VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT = 0x00000200,
+ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT = 0x00000400,
+ VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT = 0x00000800,
+ VK_PIPELINE_STAGE_TRANSFER_BIT = 0x00001000,
+ VK_PIPELINE_STAGE_HOST_BIT = 0x00002000,
+ VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT = 0x00004000,
+ VK_PIPELINE_STAGE_ALL_COMMANDS_BIT = 0x00008000,
+};
+typedef deUint32 VkPipelineStageFlags;
+
+enum VkAccessFlagBits
+{
+ VK_ACCESS_INDIRECT_COMMAND_READ_BIT = 0x00000001,
+ VK_ACCESS_INDEX_READ_BIT = 0x00000002,
+ VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT = 0x00000004,
+ VK_ACCESS_UNIFORM_READ_BIT = 0x00000008,
+ VK_ACCESS_INPUT_ATTACHMENT_READ_BIT = 0x00000010,
+ VK_ACCESS_SHADER_READ_BIT = 0x00000020,
+ VK_ACCESS_SHADER_WRITE_BIT = 0x00000040,
+ VK_ACCESS_COLOR_ATTACHMENT_READ_BIT = 0x00000080,
+ VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT = 0x00000100,
+ VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT = 0x00000200,
+ VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT = 0x00000400,
+ VK_ACCESS_TRANSFER_READ_BIT = 0x00000800,
+ VK_ACCESS_TRANSFER_WRITE_BIT = 0x00001000,
+ VK_ACCESS_HOST_READ_BIT = 0x00002000,
+ VK_ACCESS_HOST_WRITE_BIT = 0x00004000,
+ VK_ACCESS_MEMORY_READ_BIT = 0x00008000,
+ VK_ACCESS_MEMORY_WRITE_BIT = 0x00010000,
+};
+typedef deUint32 VkAccessFlags;
+
+enum VkDependencyFlagBits
+{
+ VK_DEPENDENCY_BY_REGION_BIT = 0x00000001,
+};
+typedef deUint32 VkDependencyFlags;
+
+enum VkCommandPoolCreateFlagBits
+{
+ VK_COMMAND_POOL_CREATE_TRANSIENT_BIT = 0x00000001,
+ VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT = 0x00000002,
+};
+typedef deUint32 VkCommandPoolCreateFlags;
+
+enum VkCommandPoolResetFlagBits
+{
+ VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT = 0x00000001,
+};
+typedef deUint32 VkCommandPoolResetFlags;
+
+enum VkCommandBufferUsageFlagBits
+{
+ VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT = 0x00000001,
+ VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT = 0x00000002,
+ VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT = 0x00000004,
+};
+typedef deUint32 VkCommandBufferUsageFlags;
+
+enum VkQueryControlFlagBits
+{
+ VK_QUERY_CONTROL_PRECISE_BIT = 0x00000001,
+};
+typedef deUint32 VkQueryControlFlags;
+
+enum VkCommandBufferResetFlagBits
+{
+ VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT = 0x00000001,
+};
+typedef deUint32 VkCommandBufferResetFlags;
+
+enum VkStencilFaceFlagBits
+{
+ VK_STENCIL_FACE_NONE = 0,
+ VK_STENCIL_FACE_FRONT_BIT = 0x00000001,
+ VK_STENCIL_FACE_BACK_BIT = 0x00000002,
+ VK_STENCIL_FRONT_AND_BACK = 0x3,
+};
+typedef deUint32 VkStencilFaceFlags;
+
+enum VkSurfaceTransformFlagBitsKHR
+{
+ VK_SURFACE_TRANSFORM_NONE_BIT_KHR = 0x00000001,
+ VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR = 0x00000002,
+ VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR = 0x00000004,
+ VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR = 0x00000008,
+ VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR = 0x00000010,
+ VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR = 0x00000020,
+ VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR = 0x00000040,
+ VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR = 0x00000080,
+ VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR = 0x00000100,
+};
+typedef deUint32 VkSurfaceTransformFlagsKHR;
+
+enum VkCompositeAlphaFlagBitsKHR
+{
+ VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR = 0x00000001,
+ VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR = 0x00000002,
+ VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR = 0x00000004,
+ VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR = 0x00000008,
+};
+typedef deUint32 VkCompositeAlphaFlagsKHR;
+
+enum VkDisplayPlaneAlphaFlagBitsKHR
+{
+ VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR = 0x00000001,
+ VK_DISPLAY_PLANE_ALPHA_GLOBAL_BIT_KHR = 0x00000002,
+ VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR = 0x00000004,
+ VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR = 0x00000008,
+};
+typedef deUint32 VkDisplayPlaneAlphaFlagsKHR;
+
+typedef deUint32 VkInstanceCreateFlags;
+
+typedef deUint32 VkDeviceCreateFlags;
+
+typedef deUint32 VkDeviceQueueCreateFlags;
+
+typedef deUint32 VkMemoryMapFlags;
+
+typedef deUint32 VkSemaphoreCreateFlags;
+
+typedef deUint32 VkEventCreateFlags;
+
+typedef deUint32 VkQueryPoolCreateFlags;
+
+typedef deUint32 VkBufferViewCreateFlags;
+
+typedef deUint32 VkImageViewCreateFlags;
+
+typedef deUint32 VkShaderModuleCreateFlags;
+
+typedef deUint32 VkPipelineCacheCreateFlags;
+
+typedef deUint32 VkPipelineShaderStageCreateFlags;
+
+typedef deUint32 VkPipelineVertexInputStateCreateFlags;
+
+typedef deUint32 VkPipelineInputAssemblyStateCreateFlags;
+
+typedef deUint32 VkPipelineTesselationStateCreateFlags;
+
+typedef deUint32 VkPipelineViewportStateCreateFlags;
+
+typedef deUint32 VkPipelineRasterizationStateCreateFlags;
+
+typedef deUint32 VkPipelineMultisampleStateCreateFlags;
+
+typedef deUint32 VkPipelineDepthStencilStateCreateFlags;
+
+typedef deUint32 VkPipelineColorBlendStateCreateFlags;
+
+typedef deUint32 VkPipelineDynamicStateCreateFlags;
+
+typedef deUint32 VkPipelineLayoutCreateFlags;
+
+typedef deUint32 VkSamplerCreateFlags;
+
+typedef deUint32 VkDescriptorSetLayoutCreateFlags;
+
+typedef deUint32 VkDescriptorPoolResetFlags;
+
+typedef deUint32 VkFramebufferCreateFlags;
+
+typedef deUint32 VkRenderPassCreateFlags;
+
+typedef deUint32 VkSubpassDescriptionFlags;
+
+typedef deUint32 VkSwapchainCreateFlagsKHR;
+
+typedef deUint32 VkDisplayModeCreateFlagsKHR;
+
+typedef deUint32 VkDisplaySurfaceCreateFlagsKHR;
+
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Program binary registry.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkBinaryRegistry.hpp"
+#include "tcuResource.hpp"
+#include "tcuFormatUtil.hpp"
+#include "deFilePath.hpp"
+#include "deStringUtil.hpp"
+#include "deString.h"
+#include "deInt32.h"
+
+#include <sstream>
+#include <fstream>
+#include <stdexcept>
+#include <limits>
+
+namespace vk
+{
+namespace BinaryRegistryDetail
+{
+
+using std::string;
+using std::vector;
+
+namespace
+{
+
+string getProgramPath (const std::string& dirName, deUint32 index)
+{
+ return de::FilePath::join(dirName, de::toString(tcu::toHex(index)) + ".spv").getPath();
+}
+
+string getIndexPath (const std::string& dirName)
+{
+ return de::FilePath::join(dirName, "index.bin").getPath();
+}
+
+void writeBinary (const std::string& dstDir, deUint32 index, const ProgramBinary& binary)
+{
+ const de::FilePath fullPath = getProgramPath(dstDir, index);
+
+ if (!de::FilePath(fullPath.getDirName()).exists())
+ de::createDirectoryAndParents(fullPath.getDirName().c_str());
+
+ {
+ std::ofstream out (fullPath.getPath(), std::ios_base::binary);
+
+ if (!out.is_open() || !out.good())
+ throw tcu::Exception("Failed to open " + string(fullPath.getPath()));
+
+ out.write((const char*)binary.getBinary(), binary.getSize());
+ out.close();
+ }
+}
+
+deUint32 binaryHash (const ProgramBinary* binary)
+{
+ return deMemoryHash(binary->getBinary(), binary->getSize());
+}
+
+deBool binaryEqual (const ProgramBinary* a, const ProgramBinary* b)
+{
+ if (a->getSize() == b->getSize())
+ return deMemoryEqual(a->getBinary(), b->getBinary(), a->getSize());
+ else
+ return DE_FALSE;
+}
+
+std::vector<deUint32> getSearchPath (const ProgramIdentifier& id)
+{
+ const std::string combinedStr = id.testCasePath + '#' + id.programName;
+ const size_t strLen = combinedStr.size();
+ const size_t numWords = strLen/4 + 1; // Must always end up with at least one 0 byte
+ vector<deUint32> words (numWords, 0u);
+
+ deMemcpy(&words[0], combinedStr.c_str(), strLen);
+
+ return words;
+}
+
+const deUint32* findBinaryIndex (BinaryIndexAccess* index, const ProgramIdentifier& id)
+{
+ const vector<deUint32> words = getSearchPath(id);
+ size_t nodeNdx = 0;
+ size_t wordNdx = 0;
+
+ for (;;)
+ {
+ const BinaryIndexNode& curNode = (*index)[nodeNdx];
+
+ if (curNode.word == words[wordNdx])
+ {
+ if (wordNdx+1 < words.size())
+ {
+ TCU_CHECK_INTERNAL((size_t)curNode.index < index->size());
+
+ nodeNdx = curNode.index;
+ wordNdx += 1;
+ }
+ else if (wordNdx+1 == words.size())
+ return &curNode.index;
+ else
+ return DE_NULL;
+ }
+ else if (curNode.word != 0)
+ {
+ nodeNdx += 1;
+
+ // Index should always be null-terminated
+ TCU_CHECK_INTERNAL(nodeNdx < index->size());
+ }
+ else
+ return DE_NULL;
+ }
+
+ return DE_NULL;
+}
+
+//! Sparse index node used for final binary index construction
+struct SparseIndexNode
+{
+ deUint32 word;
+ deUint32 index;
+ std::vector<SparseIndexNode*> children;
+
+ SparseIndexNode (deUint32 word_, deUint32 index_)
+ : word (word_)
+ , index (index_)
+ {}
+
+ SparseIndexNode (void)
+ : word (0)
+ , index (0)
+ {}
+
+ ~SparseIndexNode (void)
+ {
+ for (size_t ndx = 0; ndx < children.size(); ndx++)
+ delete children[ndx];
+ }
+};
+
+#if defined(DE_DEBUG)
+bool isNullByteTerminated (deUint32 word)
+{
+ deUint8 bytes[4];
+ deMemcpy(bytes, &word, sizeof(word));
+ return bytes[3] == 0;
+}
+#endif
+
+void addToSparseIndex (SparseIndexNode* group, const deUint32* words, size_t numWords, deUint32 index)
+{
+ const deUint32 curWord = words[0];
+ SparseIndexNode* child = DE_NULL;
+
+ for (size_t childNdx = 0; childNdx < group->children.size(); childNdx++)
+ {
+ if (group->children[childNdx]->word == curWord)
+ {
+ child = group->children[childNdx];
+ break;
+ }
+ }
+
+ DE_ASSERT(numWords > 1 || !child);
+
+ if (!child)
+ {
+ group->children.reserve(group->children.size()+1);
+ group->children.push_back(new SparseIndexNode(curWord, numWords == 1 ? index : 0));
+
+ child = group->children.back();
+ }
+
+ if (numWords > 1)
+ addToSparseIndex(child, words+1, numWords-1, index);
+ else
+ DE_ASSERT(isNullByteTerminated(curWord));
+}
+
+// Prepares sparse index for finalization. Ensures that child with word = 0 is moved
+// to the end, or one is added if there is no such child already.
+void normalizeSparseIndex (SparseIndexNode* group)
+{
+ int zeroChildPos = -1;
+
+ for (size_t childNdx = 0; childNdx < group->children.size(); childNdx++)
+ {
+ normalizeSparseIndex(group->children[childNdx]);
+
+ if (group->children[childNdx]->word == 0)
+ {
+ DE_ASSERT(zeroChildPos < 0);
+ zeroChildPos = (int)childNdx;
+ }
+ }
+
+ if (zeroChildPos >= 0)
+ {
+ // Move child with word = 0 to last
+ while (zeroChildPos != (int)group->children.size()-1)
+ {
+ std::swap(group->children[zeroChildPos], group->children[zeroChildPos+1]);
+ zeroChildPos += 1;
+ }
+ }
+ else if (!group->children.empty())
+ {
+ group->children.reserve(group->children.size()+1);
+ group->children.push_back(new SparseIndexNode(0, 0));
+ }
+}
+
+deUint32 getIndexSize (const SparseIndexNode* group)
+{
+ size_t numNodes = group->children.size();
+
+ for (size_t childNdx = 0; childNdx < group->children.size(); childNdx++)
+ numNodes += getIndexSize(group->children[childNdx]);
+
+ DE_ASSERT(numNodes <= std::numeric_limits<deUint32>::max());
+
+ return (deUint32)numNodes;
+}
+
+deUint32 addAndCountNodes (BinaryIndexNode* index, deUint32 baseOffset, const SparseIndexNode* group)
+{
+ const deUint32 numLocalNodes = (deUint32)group->children.size();
+ deUint32 curOffset = numLocalNodes;
+
+ // Must be normalized prior to construction of final index
+ DE_ASSERT(group->children.empty() || group->children.back()->word == 0);
+
+ for (size_t childNdx = 0; childNdx < numLocalNodes; childNdx++)
+ {
+ const SparseIndexNode* child = group->children[childNdx];
+ const deUint32 subtreeSize = addAndCountNodes(index+curOffset, baseOffset+curOffset, child);
+
+ index[childNdx].word = child->word;
+
+ if (subtreeSize == 0)
+ index[childNdx].index = child->index;
+ else
+ {
+ DE_ASSERT(child->index == 0);
+ index[childNdx].index = baseOffset+curOffset;
+ }
+
+ curOffset += subtreeSize;
+ }
+
+ return curOffset;
+}
+
+void buildFinalIndex (std::vector<BinaryIndexNode>* dst, const SparseIndexNode* root)
+{
+ const deUint32 indexSize = getIndexSize(root);
+
+ DE_ASSERT(indexSize > 0);
+
+ dst->resize(indexSize);
+ addAndCountNodes(&(*dst)[0], 0, root);
+}
+
+} // anonymous
+
+// BinaryRegistryWriter
+
+DE_IMPLEMENT_POOL_HASH(BinaryHash, const ProgramBinary*, deUint32, binaryHash, binaryEqual);
+
+BinaryRegistryWriter::BinaryRegistryWriter (const std::string& dstPath)
+ : m_dstPath (dstPath)
+ , m_binaryIndexMap (DE_NULL)
+{
+ m_binaryIndexMap = BinaryHash_create(m_memPool.getRawPool());
+
+ if (!m_binaryIndexMap)
+ throw std::bad_alloc();
+}
+
+BinaryRegistryWriter::~BinaryRegistryWriter (void)
+{
+ for (BinaryVector::const_iterator binaryIter = m_compactedBinaries.begin();
+ binaryIter != m_compactedBinaries.end();
+ ++binaryIter)
+ delete *binaryIter;
+}
+
+void BinaryRegistryWriter::storeProgram (const ProgramIdentifier& id, const ProgramBinary& binary)
+{
+ const deUint32* const indexPtr = BinaryHash_find(m_binaryIndexMap, &binary);
+ deUint32 index = indexPtr ? *indexPtr : ~0u;
+
+ DE_ASSERT(binary.getFormat() == vk::PROGRAM_FORMAT_SPIRV);
+
+ if (!indexPtr)
+ {
+ ProgramBinary* const binaryClone = new ProgramBinary(binary);
+
+ try
+ {
+ index = (deUint32)m_compactedBinaries.size();
+ m_compactedBinaries.push_back(binaryClone);
+ }
+ catch (...)
+ {
+ delete binaryClone;
+ throw;
+ }
+
+ writeBinary(m_dstPath, index, binary);
+
+ if (!BinaryHash_insert(m_binaryIndexMap, binaryClone, index))
+ throw std::bad_alloc();
+ }
+
+ DE_ASSERT((size_t)index < m_compactedBinaries.size());
+
+ m_binaryIndices.push_back(BinaryIndex(id, index));
+}
+
+void BinaryRegistryWriter::writeIndex (void) const
+{
+ const de::FilePath indexPath = getIndexPath(m_dstPath);
+ std::vector<BinaryIndexNode> index;
+
+ {
+ de::UniquePtr<SparseIndexNode> sparseIndex (new SparseIndexNode());
+
+ for (size_t progNdx = 0; progNdx < m_binaryIndices.size(); progNdx++)
+ {
+ const std::vector<deUint32> searchPath = getSearchPath(m_binaryIndices[progNdx].id);
+ addToSparseIndex(sparseIndex.get(), &searchPath[0], searchPath.size(), m_binaryIndices[progNdx].index);
+ }
+
+ normalizeSparseIndex(sparseIndex.get());
+ buildFinalIndex(&index, sparseIndex.get());
+ }
+
+ // Even in empty index there is always terminating node for the root group
+ DE_ASSERT(!index.empty());
+
+ if (!de::FilePath(indexPath.getDirName()).exists())
+ de::createDirectoryAndParents(indexPath.getDirName().c_str());
+
+ {
+ std::ofstream indexOut(indexPath.getPath(), std::ios_base::binary);
+
+ if (!indexOut.is_open() || !indexOut.good())
+ throw tcu::InternalError(string("Failed to open program binary index file ") + indexPath.getPath());
+
+ indexOut.write((const char*)&index[0], index.size()*sizeof(BinaryIndexNode));
+ }
+}
+
+// BinaryRegistryReader
+
+BinaryRegistryReader::BinaryRegistryReader (const tcu::Archive& archive, const std::string& srcPath)
+ : m_archive (archive)
+ , m_srcPath (srcPath)
+{
+}
+
+BinaryRegistryReader::~BinaryRegistryReader (void)
+{
+}
+
+ProgramBinary* BinaryRegistryReader::loadProgram (const ProgramIdentifier& id) const
+{
+ if (!m_binaryIndex)
+ {
+ try
+ {
+ m_binaryIndex = BinaryIndexPtr(new BinaryIndexAccess(de::MovePtr<tcu::Resource>(m_archive.getResource(getIndexPath(m_srcPath).c_str()))));
+ }
+ catch (const tcu::ResourceError& e)
+ {
+ throw ProgramNotFoundException(id, string("Failed to open binary index (") + e.what() + ")");
+ }
+ }
+
+ {
+ const deUint32* indexPos = findBinaryIndex(m_binaryIndex.get(), id);
+
+ if (indexPos)
+ {
+ const string fullPath = getProgramPath(m_srcPath, *indexPos);
+
+ try
+ {
+ de::UniquePtr<tcu::Resource> progRes (m_archive.getResource(fullPath.c_str()));
+ const int progSize = progRes->getSize();
+ vector<deUint8> bytes (progSize);
+
+ TCU_CHECK_INTERNAL(!bytes.empty());
+
+ progRes->read(&bytes[0], progSize);
+
+ return new ProgramBinary(vk::PROGRAM_FORMAT_SPIRV, bytes.size(), &bytes[0]);
+ }
+ catch (const tcu::ResourceError& e)
+ {
+ throw ProgramNotFoundException(id, e.what());
+ }
+ }
+ else
+ throw ProgramNotFoundException(id, "Program not found in index");
+ }
+}
+
+} // BinaryRegistryDetail
+} // vk
--- /dev/null
+#ifndef _VKBINARYREGISTRY_HPP
+#define _VKBINARYREGISTRY_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Program binary registry.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkDefs.hpp"
+#include "vkPrograms.hpp"
+#include "tcuResource.hpp"
+#include "deMemPool.hpp"
+#include "dePoolHash.h"
+#include "deUniquePtr.hpp"
+
+#include <map>
+#include <vector>
+#include <stdexcept>
+
+namespace vk
+{
+namespace BinaryRegistryDetail
+{
+
+struct ProgramIdentifier
+{
+ std::string testCasePath;
+ std::string programName;
+
+ ProgramIdentifier (const std::string& testCasePath_, const std::string& programName_)
+ : testCasePath (testCasePath_)
+ , programName (programName_)
+ {
+ }
+};
+
+inline bool operator< (const ProgramIdentifier& a, const ProgramIdentifier& b)
+{
+ return (a.testCasePath < b.testCasePath) || ((a.testCasePath == b.testCasePath) && (a.programName < b.programName));
+}
+
+class ProgramNotFoundException : public tcu::ResourceError
+{
+public:
+ ProgramNotFoundException (const ProgramIdentifier& id, const std::string& reason)
+ : tcu::ResourceError("Program " + id.testCasePath + " / '" + id.programName + "' not found: " + reason)
+ {
+ }
+};
+
+// Program Binary Index
+// --------------------
+//
+// When SPIR-V binaries are stored on disk, duplicate binaries are eliminated
+// to save a significant amount of space. Many tests use identical binaries and
+// just storing each compiled binary without de-duplication would be incredibly
+// wasteful.
+//
+// To locate binary that corresponds given ProgramIdentifier, a program binary
+// index is needed. Since that index is accessed every time a test requests shader
+// binary, it must be fast to load (to reduce statup cost), and fast to access.
+//
+// Simple trie is used to store binary indices. It is laid out as an array of
+// BinaryIndexNodes. Nodes store 4-byte pieces (words) of search string, rather
+// than just a single character. This gives more regular memory layout in exchange
+// of a little wasted storage.
+//
+// Search strings are created by splitting original string into 4-byte words and
+// appending one or more terminating 0 bytes.
+//
+// For each node where word doesn't have trailing 0 bytes (not terminated), the
+// index points into a offset of its child list. Children for each node are stored
+// consecutively, and the list is terminated by child with word = 0.
+//
+// If word contains one or more trailing 0 bytes, index denotes the binary index
+// instead of index of the child list.
+
+struct BinaryIndexNode
+{
+ deUint32 word; //!< 4 bytes of search string.
+ deUint32 index; //!< Binary index if word ends with 0 bytes, or index of first child node otherwise.
+};
+
+template<typename Element>
+class LazyResource
+{
+public:
+ LazyResource (de::MovePtr<tcu::Resource> resource);
+
+ const Element& operator[] (size_t ndx);
+ size_t size (void) const { return m_elements.size(); }
+
+private:
+ enum
+ {
+ ELEMENTS_PER_PAGE_LOG2 = 10
+ };
+
+ inline size_t getPageForElement (size_t elemNdx) const { return elemNdx >> ELEMENTS_PER_PAGE_LOG2; }
+ inline bool isPageResident (size_t pageNdx) const { return m_isPageResident[pageNdx]; }
+
+ void makePageResident (size_t pageNdx);
+
+ de::UniquePtr<tcu::Resource> m_resource;
+
+ std::vector<Element> m_elements;
+ std::vector<bool> m_isPageResident;
+};
+
+template<typename Element>
+LazyResource<Element>::LazyResource (de::MovePtr<tcu::Resource> resource)
+ : m_resource(resource)
+{
+ const size_t resSize = m_resource->getSize();
+ const size_t numElements = resSize/sizeof(Element);
+ const size_t numPages = (numElements >> ELEMENTS_PER_PAGE_LOG2) + ((numElements & ((1u<<ELEMENTS_PER_PAGE_LOG2)-1u)) == 0 ? 0 : 1);
+
+ TCU_CHECK_INTERNAL(numElements*sizeof(Element) == resSize);
+
+ m_elements.resize(numElements);
+ m_isPageResident.resize(numPages, false);
+}
+
+template<typename Element>
+const Element& LazyResource<Element>::operator[] (size_t ndx)
+{
+ const size_t pageNdx = getPageForElement(ndx);
+
+ if (ndx >= m_elements.size())
+ throw std::out_of_range("");
+
+ if (!isPageResident(pageNdx))
+ makePageResident(pageNdx);
+
+ return m_elements[ndx];
+}
+
+template<typename Element>
+void LazyResource<Element>::makePageResident (size_t pageNdx)
+{
+ const size_t pageSize = (size_t)(1<<ELEMENTS_PER_PAGE_LOG2)*sizeof(Element);
+ const size_t pageOffset = pageNdx*pageSize;
+ const size_t numBytesToRead = de::min(m_elements.size()*sizeof(Element) - pageOffset, pageSize);
+
+ DE_ASSERT(!isPageResident(pageNdx));
+
+ if ((size_t)m_resource->getPosition() != pageOffset)
+ m_resource->setPosition((int)pageOffset);
+
+ m_resource->read((deUint8*)&m_elements[pageNdx << ELEMENTS_PER_PAGE_LOG2], (int)numBytesToRead);
+ m_isPageResident[pageNdx] = true;
+}
+
+typedef LazyResource<BinaryIndexNode> BinaryIndexAccess;
+
+DE_DECLARE_POOL_HASH(BinaryHash, const ProgramBinary*, deUint32);
+
+class BinaryRegistryReader
+{
+public:
+ BinaryRegistryReader (const tcu::Archive& archive, const std::string& srcPath);
+ ~BinaryRegistryReader (void);
+
+ ProgramBinary* loadProgram (const ProgramIdentifier& id) const;
+
+private:
+ typedef de::MovePtr<BinaryIndexAccess> BinaryIndexPtr;
+
+ const tcu::Archive& m_archive;
+ const std::string m_srcPath;
+
+ mutable BinaryIndexPtr m_binaryIndex;
+};
+
+class BinaryRegistryWriter
+{
+public:
+ BinaryRegistryWriter (const std::string& dstPath);
+ ~BinaryRegistryWriter (void);
+
+ void storeProgram (const ProgramIdentifier& id, const ProgramBinary& binary);
+ void writeIndex (void) const;
+
+private:
+ struct BinaryIndex
+ {
+ ProgramIdentifier id;
+ deUint32 index;
+
+ BinaryIndex (const ProgramIdentifier& id_,
+ deUint32 index_)
+ : id (id_)
+ , index (index_)
+ {}
+ };
+
+ typedef std::vector<ProgramBinary*> BinaryVector;
+ typedef std::vector<BinaryIndex> BinaryIndexVector;
+
+ const std::string& m_dstPath;
+
+ de::MemPool m_memPool;
+ BinaryHash* m_binaryIndexMap; //!< ProgramBinary -> slot in m_compactedBinaries
+ BinaryVector m_compactedBinaries;
+ BinaryIndexVector m_binaryIndices; //!< ProgramIdentifier -> slot in m_compactedBinaries
+};
+
+} // BinaryRegistryDetail
+
+using BinaryRegistryDetail::BinaryRegistryReader;
+using BinaryRegistryDetail::BinaryRegistryWriter;
+using BinaryRegistryDetail::ProgramIdentifier;
+using BinaryRegistryDetail::ProgramNotFoundException;
+
+} // vk
+
+#endif // _VKBINARYREGISTRY_HPP
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Vulkan object builder utilities.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkBuilderUtil.hpp"
+
+#include "vkRefUtil.hpp"
+
+namespace vk
+{
+
+// DescriptorSetLayoutBuilder
+
+DescriptorSetLayoutBuilder::DescriptorSetLayoutBuilder (void)
+{
+}
+
+DescriptorSetLayoutBuilder& DescriptorSetLayoutBuilder::addBinding (VkDescriptorType descriptorType,
+ deUint32 descriptorCount,
+ VkShaderStageFlags stageFlags,
+ const VkSampler* pImmutableSamplers)
+{
+ const VkDescriptorSetLayoutBinding binding =
+ {
+ (deUint32)m_bindings.size(), // binding
+ descriptorType, // descriptorType
+ descriptorCount, // descriptorCount
+ stageFlags, // stageFlags
+ pImmutableSamplers, // pImmutableSamplers
+ };
+ m_bindings.push_back(binding);
+ return *this;
+}
+
+Move<VkDescriptorSetLayout> DescriptorSetLayoutBuilder::build (const DeviceInterface& vk, VkDevice device) const
+{
+ const VkDescriptorSetLayoutBinding* const bindingPtr = (m_bindings.empty()) ? (DE_NULL) : (&m_bindings[0]);
+ const VkDescriptorSetLayoutCreateInfo createInfo =
+ {
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
+ DE_NULL,
+ (VkDescriptorSetLayoutCreateFlags)0, // flags
+ (deUint32)m_bindings.size(), // bindingCount
+ bindingPtr, // pBinding
+ };
+
+ return createDescriptorSetLayout(vk, device, &createInfo);
+}
+
+// DescriptorPoolBuilder
+
+DescriptorPoolBuilder::DescriptorPoolBuilder (void)
+{
+}
+
+DescriptorPoolBuilder& DescriptorPoolBuilder::addType (VkDescriptorType type, deUint32 numDescriptors)
+{
+ if (numDescriptors == 0u)
+ {
+ // nothing to do
+ return *this;
+ }
+ else
+ {
+ for (size_t ndx = 0; ndx < m_counts.size(); ++ndx)
+ {
+ if (m_counts[ndx].type == type)
+ {
+ // augment existing requirement
+ m_counts[ndx].descriptorCount += numDescriptors;
+ return *this;
+ }
+ }
+
+ {
+ // new requirement
+ const VkDescriptorPoolSize typeCount =
+ {
+ type, // type
+ numDescriptors, // numDescriptors
+ };
+
+ m_counts.push_back(typeCount);
+ return *this;
+ }
+ }
+}
+
+Move<VkDescriptorPool> DescriptorPoolBuilder::build (const DeviceInterface& vk, VkDevice device, VkDescriptorPoolCreateFlags flags, deUint32 maxSets) const
+{
+ const VkDescriptorPoolSize* const typeCountPtr = (m_counts.empty()) ? (DE_NULL) : (&m_counts[0]);
+ const VkDescriptorPoolCreateInfo createInfo =
+ {
+ VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
+ DE_NULL,
+ flags,
+ maxSets,
+ (deUint32)m_counts.size(), // poolSizeCount
+ typeCountPtr, // pPoolSizes
+ };
+
+ return createDescriptorPool(vk, device, &createInfo);
+}
+
+// DescriptorSetUpdateBuilder
+
+DescriptorSetUpdateBuilder::DescriptorSetUpdateBuilder (void)
+{
+}
+
+DescriptorSetUpdateBuilder& DescriptorSetUpdateBuilder::write (VkDescriptorSet destSet,
+ deUint32 destBinding,
+ deUint32 destArrayElement,
+ deUint32 count,
+ VkDescriptorType descriptorType,
+ const VkDescriptorImageInfo* pImageInfo,
+ const VkDescriptorBufferInfo* pBufferInfo,
+ const VkBufferView* pTexelBufferView)
+{
+ const VkWriteDescriptorSet writeParams =
+ {
+ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
+ DE_NULL,
+ destSet, //!< destSet
+ destBinding, //!< destBinding
+ destArrayElement, //!< destArrayElement
+ count, //!< count
+ descriptorType, //!< descriptorType
+ pImageInfo,
+ pBufferInfo,
+ pTexelBufferView
+ };
+ m_writes.push_back(writeParams);
+ return *this;
+}
+
+DescriptorSetUpdateBuilder& DescriptorSetUpdateBuilder::copy (VkDescriptorSet srcSet,
+ deUint32 srcBinding,
+ deUint32 srcArrayElement,
+ VkDescriptorSet destSet,
+ deUint32 destBinding,
+ deUint32 destArrayElement,
+ deUint32 count)
+{
+ const VkCopyDescriptorSet copyParams =
+ {
+ VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET,
+ DE_NULL,
+ srcSet, //!< srcSet
+ srcBinding, //!< srcBinding
+ srcArrayElement, //!< srcArrayElement
+ destSet, //!< destSet
+ destBinding, //!< destBinding
+ destArrayElement, //!< destArrayElement
+ count, //!< count
+ };
+ m_copies.push_back(copyParams);
+ return *this;
+}
+
+void DescriptorSetUpdateBuilder::update (const DeviceInterface& vk, VkDevice device) const
+{
+ const VkWriteDescriptorSet* const writePtr = (m_writes.empty()) ? (DE_NULL) : (&m_writes[0]);
+ const VkCopyDescriptorSet* const copyPtr = (m_copies.empty()) ? (DE_NULL) : (&m_copies[0]);
+
+ vk.updateDescriptorSets(device, (deUint32)m_writes.size(), writePtr, (deUint32)m_copies.size(), copyPtr);
+}
+
+} // vk
--- /dev/null
+#ifndef _VKBUILDERUTIL_HPP
+#define _VKBUILDERUTIL_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Vulkan object builder utilities.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkDefs.hpp"
+#include "vkRef.hpp"
+
+#include <vector>
+
+namespace vk
+{
+
+class DescriptorSetLayoutBuilder
+{
+public:
+ DescriptorSetLayoutBuilder (void);
+
+ DescriptorSetLayoutBuilder& addBinding (VkDescriptorType descriptorType,
+ deUint32 descriptorCount,
+ VkShaderStageFlags stageFlags,
+ const VkSampler* pImmutableSamplers);
+
+ Move<VkDescriptorSetLayout> build (const DeviceInterface& vk, VkDevice device) const;
+
+ // helpers
+
+ inline DescriptorSetLayoutBuilder& addSingleBinding (VkDescriptorType descriptorType,
+ VkShaderStageFlags stageFlags)
+ {
+ return addBinding(descriptorType, 1u, stageFlags, (VkSampler*)DE_NULL);
+ }
+ inline DescriptorSetLayoutBuilder& addArrayBinding (VkDescriptorType descriptorType,
+ deUint32 descriptorCount,
+ VkShaderStageFlags stageFlags)
+ {
+ return addBinding(descriptorType, descriptorCount, stageFlags, (VkSampler*)DE_NULL);
+ }
+ inline DescriptorSetLayoutBuilder& addSingleSamplerBinding (VkDescriptorType descriptorType,
+ VkShaderStageFlags stageFlags,
+ const VkSampler* immutableSampler) //!< \note: Using pointer to sampler to clarify that handle is not
+ //!< copied and argument lifetime is expected to cover build()
+ //!< call.
+ {
+ return addBinding(descriptorType, 1u, stageFlags, immutableSampler);
+ }
+ inline DescriptorSetLayoutBuilder& addArraySamplerBinding (VkDescriptorType descriptorType,
+ deUint32 descriptorCount,
+ VkShaderStageFlags stageFlags,
+ const VkSampler* pImmutableSamplers)
+ {
+ return addBinding(descriptorType, descriptorCount, stageFlags, pImmutableSamplers);
+ }
+
+private:
+ DescriptorSetLayoutBuilder (const DescriptorSetLayoutBuilder&); // delete
+ DescriptorSetLayoutBuilder& operator= (const DescriptorSetLayoutBuilder&); // delete
+
+ std::vector<VkDescriptorSetLayoutBinding> m_bindings;
+};
+
+class DescriptorPoolBuilder
+{
+public:
+ DescriptorPoolBuilder (void);
+
+ DescriptorPoolBuilder& addType (VkDescriptorType type, deUint32 numDescriptors = 1u);
+ Move<VkDescriptorPool> build (const DeviceInterface& vk, VkDevice device, VkDescriptorPoolCreateFlags flags, deUint32 maxSets) const;
+
+private:
+ DescriptorPoolBuilder (const DescriptorPoolBuilder&); // delete
+ DescriptorPoolBuilder& operator= (const DescriptorPoolBuilder&); // delete
+
+ std::vector<VkDescriptorPoolSize> m_counts;
+};
+
+class DescriptorSetUpdateBuilder
+{
+public:
+ class Location
+ {
+ public:
+ static inline Location binding (deUint32 binding_)
+ {
+ return Location(binding_, 0u);
+ }
+ static inline Location bindingArrayElement (deUint32 binding_, deUint32 arrayElement)
+ {
+ return Location(binding_, arrayElement);
+ }
+
+ private:
+ // \note private to force use of factory methods that have more descriptive names
+ inline Location (deUint32 binding_, deUint32 arrayElement)
+ : m_binding (binding_)
+ , m_arrayElement (arrayElement)
+ {
+ }
+
+ friend class DescriptorSetUpdateBuilder;
+
+ const deUint32 m_binding;
+ const deUint32 m_arrayElement;
+ };
+
+ DescriptorSetUpdateBuilder (void);
+
+ DescriptorSetUpdateBuilder& write (VkDescriptorSet destSet,
+ deUint32 destBinding,
+ deUint32 destArrayElement,
+ deUint32 count,
+ VkDescriptorType descriptorType,
+ const VkDescriptorImageInfo* pImageInfo,
+ const VkDescriptorBufferInfo* pBufferInfo,
+ const VkBufferView* pTexelBufferView);
+
+ DescriptorSetUpdateBuilder& copy (VkDescriptorSet srcSet,
+ deUint32 srcBinding,
+ deUint32 srcArrayElement,
+ VkDescriptorSet destSet,
+ deUint32 destBinding,
+ deUint32 destArrayElement,
+ deUint32 count);
+
+ void update (const DeviceInterface& vk, VkDevice device) const;
+
+ // helpers
+
+ inline DescriptorSetUpdateBuilder& writeSingle (VkDescriptorSet destSet,
+ const Location& destLocation,
+ VkDescriptorType descriptorType,
+ const VkDescriptorImageInfo* pImageInfo)
+ {
+ return write(destSet, destLocation.m_binding, destLocation.m_arrayElement, 1u, descriptorType, pImageInfo, DE_NULL, DE_NULL);
+ }
+
+ inline DescriptorSetUpdateBuilder& writeSingle (VkDescriptorSet destSet,
+ const Location& destLocation,
+ VkDescriptorType descriptorType,
+ const VkDescriptorBufferInfo* pBufferInfo)
+ {
+ return write(destSet, destLocation.m_binding, destLocation.m_arrayElement, 1u, descriptorType, DE_NULL, pBufferInfo, DE_NULL);
+ }
+
+ inline DescriptorSetUpdateBuilder& writeSingle (VkDescriptorSet destSet,
+ const Location& destLocation,
+ VkDescriptorType descriptorType,
+ const VkBufferView* pTexelBufferView)
+ {
+ return write(destSet, destLocation.m_binding, destLocation.m_arrayElement, 1u, descriptorType, DE_NULL, DE_NULL, pTexelBufferView);
+ }
+
+ inline DescriptorSetUpdateBuilder& writeArray (VkDescriptorSet destSet,
+ const Location& destLocation,
+ VkDescriptorType descriptorType,
+ deUint32 numDescriptors,
+ const VkDescriptorImageInfo* pImageInfo)
+ {
+ return write(destSet, destLocation.m_binding, destLocation.m_arrayElement, numDescriptors, descriptorType, pImageInfo, DE_NULL, DE_NULL);
+ }
+
+ inline DescriptorSetUpdateBuilder& writeArray (VkDescriptorSet destSet,
+ const Location& destLocation,
+ VkDescriptorType descriptorType,
+ deUint32 numDescriptors,
+ const VkDescriptorBufferInfo* pBufferInfo)
+ {
+ return write(destSet, destLocation.m_binding, destLocation.m_arrayElement, numDescriptors, descriptorType, DE_NULL, pBufferInfo, DE_NULL);
+ }
+
+ inline DescriptorSetUpdateBuilder& writeArray (VkDescriptorSet destSet,
+ const Location& destLocation,
+ VkDescriptorType descriptorType,
+ deUint32 numDescriptors,
+ const VkBufferView* pTexelBufferView)
+ {
+ return write(destSet, destLocation.m_binding, destLocation.m_arrayElement, numDescriptors, descriptorType, DE_NULL, DE_NULL, pTexelBufferView);
+ }
+
+ inline DescriptorSetUpdateBuilder& copySingle (VkDescriptorSet srcSet,
+ const Location& srcLocation,
+ VkDescriptorSet destSet,
+ const Location& destLocation)
+ {
+ return copy(srcSet, srcLocation.m_binding, srcLocation.m_arrayElement, destSet, destLocation.m_binding, destLocation.m_arrayElement, 1u);
+ }
+
+ inline DescriptorSetUpdateBuilder& copyArray (VkDescriptorSet srcSet,
+ const Location& srcLocation,
+ VkDescriptorSet destSet,
+ const Location& destLocation,
+ deUint32 count)
+ {
+ return copy(srcSet, srcLocation.m_binding, srcLocation.m_arrayElement, destSet, destLocation.m_binding, destLocation.m_arrayElement, count);
+ }
+
+private:
+ DescriptorSetUpdateBuilder (const DescriptorSetUpdateBuilder&); // delete
+ DescriptorSetUpdateBuilder& operator= (const DescriptorSetUpdateBuilder&); // delete
+
+ std::vector<VkDescriptorImageInfo> m_imageInfos;
+ std::vector<VkDescriptorBufferInfo> m_bufferInfos;
+ std::vector<VkBufferView> m_texelBufferViews;
+
+ std::vector<VkWriteDescriptorSet> m_writes;
+ std::vector<VkCopyDescriptorSet> m_copies;
+};
+
+} // vk
+
+#endif // _VKBUILDERUTIL_HPP
--- /dev/null
+/* WARNING: This is auto-generated file. Do not modify, since changes will
+ * be lost! Modify the generating script instead.
+ */
+virtual void destroyDevice (VkDevice device, const VkAllocationCallbacks* pAllocator) const;
+virtual void getDeviceQueue (VkDevice device, deUint32 queueFamilyIndex, deUint32 queueIndex, VkQueue* pQueue) const;
+virtual VkResult queueSubmit (VkQueue queue, deUint32 submitCount, const VkSubmitInfo* pSubmits, VkFence fence) const;
+virtual VkResult queueWaitIdle (VkQueue queue) const;
+virtual VkResult deviceWaitIdle (VkDevice device) const;
+virtual VkResult allocateMemory (VkDevice device, const VkMemoryAllocateInfo* pAllocateInfo, const VkAllocationCallbacks* pAllocator, VkDeviceMemory* pMemory) const;
+virtual void freeMemory (VkDevice device, VkDeviceMemory memory, const VkAllocationCallbacks* pAllocator) const;
+virtual VkResult mapMemory (VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData) const;
+virtual void unmapMemory (VkDevice device, VkDeviceMemory memory) const;
+virtual VkResult flushMappedMemoryRanges (VkDevice device, deUint32 memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges) const;
+virtual VkResult invalidateMappedMemoryRanges (VkDevice device, deUint32 memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges) const;
+virtual void getDeviceMemoryCommitment (VkDevice device, VkDeviceMemory memory, VkDeviceSize* pCommittedMemoryInBytes) const;
+virtual VkResult bindBufferMemory (VkDevice device, VkBuffer buffer, VkDeviceMemory memory, VkDeviceSize memoryOffset) const;
+virtual VkResult bindImageMemory (VkDevice device, VkImage image, VkDeviceMemory memory, VkDeviceSize memoryOffset) const;
+virtual void getBufferMemoryRequirements (VkDevice device, VkBuffer buffer, VkMemoryRequirements* pMemoryRequirements) const;
+virtual void getImageMemoryRequirements (VkDevice device, VkImage image, VkMemoryRequirements* pMemoryRequirements) const;
+virtual void getImageSparseMemoryRequirements (VkDevice device, VkImage image, deUint32* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements* pSparseMemoryRequirements) const;
+virtual void getPhysicalDeviceSparseImageFormatProperties (VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling, deUint32* pPropertyCount, VkSparseImageFormatProperties* pProperties) const;
+virtual VkResult queueBindSparse (VkQueue queue, deUint32 bindInfoCount, const VkBindSparseInfo* pBindInfo, VkFence fence) const;
+virtual VkResult createFence (VkDevice device, const VkFenceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence) const;
+virtual void destroyFence (VkDevice device, VkFence fence, const VkAllocationCallbacks* pAllocator) const;
+virtual VkResult resetFences (VkDevice device, deUint32 fenceCount, const VkFence* pFences) const;
+virtual VkResult getFenceStatus (VkDevice device, VkFence fence) const;
+virtual VkResult waitForFences (VkDevice device, deUint32 fenceCount, const VkFence* pFences, VkBool32 waitAll, deUint64 timeout) const;
+virtual VkResult createSemaphore (VkDevice device, const VkSemaphoreCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSemaphore* pSemaphore) const;
+virtual void destroySemaphore (VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks* pAllocator) const;
+virtual VkResult createEvent (VkDevice device, const VkEventCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkEvent* pEvent) const;
+virtual void destroyEvent (VkDevice device, VkEvent event, const VkAllocationCallbacks* pAllocator) const;
+virtual VkResult getEventStatus (VkDevice device, VkEvent event) const;
+virtual VkResult setEvent (VkDevice device, VkEvent event) const;
+virtual VkResult resetEvent (VkDevice device, VkEvent event) const;
+virtual VkResult createQueryPool (VkDevice device, const VkQueryPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkQueryPool* pQueryPool) const;
+virtual void destroyQueryPool (VkDevice device, VkQueryPool queryPool, const VkAllocationCallbacks* pAllocator) const;
+virtual VkResult getQueryPoolResults (VkDevice device, VkQueryPool queryPool, deUint32 startQuery, deUint32 queryCount, deUintptr dataSize, void* pData, VkDeviceSize stride, VkQueryResultFlags flags) const;
+virtual VkResult createBuffer (VkDevice device, const VkBufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBuffer* pBuffer) const;
+virtual void destroyBuffer (VkDevice device, VkBuffer buffer, const VkAllocationCallbacks* pAllocator) const;
+virtual VkResult createBufferView (VkDevice device, const VkBufferViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBufferView* pView) const;
+virtual void destroyBufferView (VkDevice device, VkBufferView bufferView, const VkAllocationCallbacks* pAllocator) const;
+virtual VkResult createImage (VkDevice device, const VkImageCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImage* pImage) const;
+virtual void destroyImage (VkDevice device, VkImage image, const VkAllocationCallbacks* pAllocator) const;
+virtual void getImageSubresourceLayout (VkDevice device, VkImage image, const VkImageSubresource* pSubresource, VkSubresourceLayout* pLayout) const;
+virtual VkResult createImageView (VkDevice device, const VkImageViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImageView* pView) const;
+virtual void destroyImageView (VkDevice device, VkImageView imageView, const VkAllocationCallbacks* pAllocator) const;
+virtual VkResult createShaderModule (VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule) const;
+virtual void destroyShaderModule (VkDevice device, VkShaderModule shaderModule, const VkAllocationCallbacks* pAllocator) const;
+virtual VkResult createPipelineCache (VkDevice device, const VkPipelineCacheCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineCache* pPipelineCache) const;
+virtual void destroyPipelineCache (VkDevice device, VkPipelineCache pipelineCache, const VkAllocationCallbacks* pAllocator) const;
+virtual VkResult getPipelineCacheData (VkDevice device, VkPipelineCache pipelineCache, deUintptr* pDataSize, void* pData) const;
+virtual VkResult mergePipelineCaches (VkDevice device, VkPipelineCache dstCache, deUint32 srcCacheCount, const VkPipelineCache* pSrcCaches) const;
+virtual VkResult createGraphicsPipelines (VkDevice device, VkPipelineCache pipelineCache, deUint32 createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines) const;
+virtual VkResult createComputePipelines (VkDevice device, VkPipelineCache pipelineCache, deUint32 createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines) const;
+virtual void destroyPipeline (VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks* pAllocator) const;
+virtual VkResult createPipelineLayout (VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout) const;
+virtual void destroyPipelineLayout (VkDevice device, VkPipelineLayout pipelineLayout, const VkAllocationCallbacks* pAllocator) const;
+virtual VkResult createSampler (VkDevice device, const VkSamplerCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSampler* pSampler) const;
+virtual void destroySampler (VkDevice device, VkSampler sampler, const VkAllocationCallbacks* pAllocator) const;
+virtual VkResult createDescriptorSetLayout (VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorSetLayout* pSetLayout) const;
+virtual void destroyDescriptorSetLayout (VkDevice device, VkDescriptorSetLayout descriptorSetLayout, const VkAllocationCallbacks* pAllocator) const;
+virtual VkResult createDescriptorPool (VkDevice device, const VkDescriptorPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorPool* pDescriptorPool) const;
+virtual void destroyDescriptorPool (VkDevice device, VkDescriptorPool descriptorPool, const VkAllocationCallbacks* pAllocator) const;
+virtual VkResult resetDescriptorPool (VkDevice device, VkDescriptorPool descriptorPool, VkDescriptorPoolResetFlags flags) const;
+virtual VkResult allocateDescriptorSets (VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets) const;
+virtual VkResult freeDescriptorSets (VkDevice device, VkDescriptorPool descriptorPool, deUint32 descriptorSetCount, const VkDescriptorSet* pDescriptorSets) const;
+virtual void updateDescriptorSets (VkDevice device, deUint32 descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites, deUint32 descriptorCopyCount, const VkCopyDescriptorSet* pDescriptorCopies) const;
+virtual VkResult createFramebuffer (VkDevice device, const VkFramebufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkFramebuffer* pFramebuffer) const;
+virtual void destroyFramebuffer (VkDevice device, VkFramebuffer framebuffer, const VkAllocationCallbacks* pAllocator) const;
+virtual VkResult createRenderPass (VkDevice device, const VkRenderPassCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass) const;
+virtual void destroyRenderPass (VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks* pAllocator) const;
+virtual void getRenderAreaGranularity (VkDevice device, VkRenderPass renderPass, VkExtent2D* pGranularity) const;
+virtual VkResult createCommandPool (VkDevice device, const VkCommandPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCommandPool* pCommandPool) const;
+virtual void destroyCommandPool (VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks* pAllocator) const;
+virtual VkResult resetCommandPool (VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags) const;
+virtual VkResult allocateCommandBuffers (VkDevice device, const VkCommandBufferAllocateInfo* pAllocateInfo, VkCommandBuffer* pCommandBuffers) const;
+virtual void freeCommandBuffers (VkDevice device, VkCommandPool commandPool, deUint32 commandBufferCount, const VkCommandBuffer* pCommandBuffers) const;
+virtual VkResult beginCommandBuffer (VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo* pBeginInfo) const;
+virtual VkResult endCommandBuffer (VkCommandBuffer commandBuffer) const;
+virtual VkResult resetCommandBuffer (VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags) const;
+virtual void cmdBindPipeline (VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline) const;
+virtual void cmdSetViewport (VkCommandBuffer commandBuffer, deUint32 viewportCount, const VkViewport* pViewports) const;
+virtual void cmdSetScissor (VkCommandBuffer commandBuffer, deUint32 scissorCount, const VkRect2D* pScissors) const;
+virtual void cmdSetLineWidth (VkCommandBuffer commandBuffer, float lineWidth) const;
+virtual void cmdSetDepthBias (VkCommandBuffer commandBuffer, float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor) const;
+virtual void cmdSetBlendConstants (VkCommandBuffer commandBuffer, const float blendConstants[4]) const;
+virtual void cmdSetDepthBounds (VkCommandBuffer commandBuffer, float minDepthBounds, float maxDepthBounds) const;
+virtual void cmdSetStencilCompareMask (VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, deUint32 compareMask) const;
+virtual void cmdSetStencilWriteMask (VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, deUint32 writeMask) const;
+virtual void cmdSetStencilReference (VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, deUint32 reference) const;
+virtual void cmdBindDescriptorSets (VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, deUint32 firstSet, deUint32 descriptorSetCount, const VkDescriptorSet* pDescriptorSets, deUint32 dynamicOffsetCount, const deUint32* pDynamicOffsets) const;
+virtual void cmdBindIndexBuffer (VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType) const;
+virtual void cmdBindVertexBuffers (VkCommandBuffer commandBuffer, deUint32 startBinding, deUint32 bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets) const;
+virtual void cmdDraw (VkCommandBuffer commandBuffer, deUint32 vertexCount, deUint32 instanceCount, deUint32 firstVertex, deUint32 firstInstance) const;
+virtual void cmdDrawIndexed (VkCommandBuffer commandBuffer, deUint32 indexCount, deUint32 instanceCount, deUint32 firstIndex, deInt32 vertexOffset, deUint32 firstInstance) const;
+virtual void cmdDrawIndirect (VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, deUint32 drawCount, deUint32 stride) const;
+virtual void cmdDrawIndexedIndirect (VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, deUint32 drawCount, deUint32 stride) const;
+virtual void cmdDispatch (VkCommandBuffer commandBuffer, deUint32 x, deUint32 y, deUint32 z) const;
+virtual void cmdDispatchIndirect (VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) const;
+virtual void cmdCopyBuffer (VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, deUint32 regionCount, const VkBufferCopy* pRegions) const;
+virtual void cmdCopyImage (VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, deUint32 regionCount, const VkImageCopy* pRegions) const;
+virtual void cmdBlitImage (VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, deUint32 regionCount, const VkImageBlit* pRegions, VkFilter filter) const;
+virtual void cmdCopyBufferToImage (VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage, VkImageLayout dstImageLayout, deUint32 regionCount, const VkBufferImageCopy* pRegions) const;
+virtual void cmdCopyImageToBuffer (VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkBuffer dstBuffer, deUint32 regionCount, const VkBufferImageCopy* pRegions) const;
+virtual void cmdUpdateBuffer (VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const deUint32* pData) const;
+virtual void cmdFillBuffer (VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, deUint32 data) const;
+virtual void cmdClearColorImage (VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearColorValue* pColor, deUint32 rangeCount, const VkImageSubresourceRange* pRanges) const;
+virtual void cmdClearDepthStencilImage (VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearDepthStencilValue* pDepthStencil, deUint32 rangeCount, const VkImageSubresourceRange* pRanges) const;
+virtual void cmdClearAttachments (VkCommandBuffer commandBuffer, deUint32 attachmentCount, const VkClearAttachment* pAttachments, deUint32 rectCount, const VkClearRect* pRects) const;
+virtual void cmdResolveImage (VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, deUint32 regionCount, const VkImageResolve* pRegions) const;
+virtual void cmdSetEvent (VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) const;
+virtual void cmdResetEvent (VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) const;
+virtual void cmdWaitEvents (VkCommandBuffer commandBuffer, deUint32 eventCount, const VkEvent* pEvents, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, deUint32 memoryBarrierCount, const void* const* ppMemoryBarriers) const;
+virtual void cmdPipelineBarrier (VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, deUint32 memoryBarrierCount, const void* const* ppMemoryBarriers) const;
+virtual void cmdBeginQuery (VkCommandBuffer commandBuffer, VkQueryPool queryPool, deUint32 entry, VkQueryControlFlags flags) const;
+virtual void cmdEndQuery (VkCommandBuffer commandBuffer, VkQueryPool queryPool, deUint32 entry) const;
+virtual void cmdResetQueryPool (VkCommandBuffer commandBuffer, VkQueryPool queryPool, deUint32 startQuery, deUint32 queryCount) const;
+virtual void cmdWriteTimestamp (VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkQueryPool queryPool, deUint32 entry) const;
+virtual void cmdCopyQueryPoolResults (VkCommandBuffer commandBuffer, VkQueryPool queryPool, deUint32 startQuery, deUint32 queryCount, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags) const;
+virtual void cmdPushConstants (VkCommandBuffer commandBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, deUint32 offset, deUint32 size, const void* pValues) const;
+virtual void cmdBeginRenderPass (VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, VkSubpassContents contents) const;
+virtual void cmdNextSubpass (VkCommandBuffer commandBuffer, VkSubpassContents contents) const;
+virtual void cmdEndRenderPass (VkCommandBuffer commandBuffer) const;
+virtual void cmdExecuteCommands (VkCommandBuffer commandBuffer, deUint32 commandBuffersCount, const VkCommandBuffer* pCommandBuffers) const;
--- /dev/null
+/* WARNING: This is auto-generated file. Do not modify, since changes will
+ * be lost! Modify the generating script instead.
+ */
+virtual void destroyInstance (VkInstance instance, const VkAllocationCallbacks* pAllocator) const;
+virtual VkResult enumeratePhysicalDevices (VkInstance instance, deUint32* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices) const;
+virtual void getPhysicalDeviceFeatures (VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures* pFeatures) const;
+virtual void getPhysicalDeviceFormatProperties (VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties* pFormatProperties) const;
+virtual VkResult getPhysicalDeviceImageFormatProperties (VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties* pImageFormatProperties) const;
+virtual void getPhysicalDeviceProperties (VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties* pProperties) const;
+virtual void getPhysicalDeviceQueueFamilyProperties (VkPhysicalDevice physicalDevice, deUint32* pQueueFamilyPropertyCount, VkQueueFamilyProperties* pQueueFamilyProperties) const;
+virtual void getPhysicalDeviceMemoryProperties (VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties* pMemoryProperties) const;
+virtual PFN_vkVoidFunction getDeviceProcAddr (VkDevice device, const char* pName) const;
+virtual VkResult createDevice (VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice) const;
+virtual VkResult enumerateDeviceExtensionProperties (VkPhysicalDevice physicalDevice, const char* pLayerName, deUint32* pPropertyCount, VkExtensionProperties* pProperties) const;
+virtual VkResult enumerateDeviceLayerProperties (VkPhysicalDevice physicalDevice, deUint32* pPropertyCount, VkLayerProperties* pProperties) const;
--- /dev/null
+/* WARNING: This is auto-generated file. Do not modify, since changes will
+ * be lost! Modify the generating script instead.
+ */
+virtual VkResult createInstance (const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance) const;
+virtual PFN_vkVoidFunction getInstanceProcAddr (VkInstance instance, const char* pName) const;
+virtual VkResult enumerateInstanceExtensionProperties (const char* pLayerName, deUint32* pPropertyCount, VkExtensionProperties* pProperties) const;
+virtual VkResult enumerateInstanceLayerProperties (deUint32* pPropertyCount, VkLayerProperties* pProperties) const;
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Vulkan utilites.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkDefs.hpp"
+#include "vkStrUtil.hpp"
+
+#include <sstream>
+
+DE_STATIC_ASSERT(sizeof(vk::VkImageType) == sizeof(deUint32));
+DE_STATIC_ASSERT(sizeof(vk::VkResult) == sizeof(deUint32));
+DE_STATIC_ASSERT(sizeof(vk::VkDevice) == sizeof(void*));
+DE_STATIC_ASSERT(sizeof(vk::VkBuffer) == sizeof(deUint64));
+
+namespace vk
+{
+
+static bool isOutOfMemoryError (VkResult result)
+{
+ return result == VK_ERROR_OUT_OF_DEVICE_MEMORY ||
+ result == VK_ERROR_OUT_OF_HOST_MEMORY;
+}
+
+Error::Error (VkResult error, const char* message, const char* expr, const char* file, int line)
+ : tcu::TestError (message, expr, file, line)
+ , m_error (error)
+{
+}
+
+Error::Error (VkResult error, const std::string& message)
+ : tcu::TestError (message)
+ , m_error (error)
+{
+}
+
+Error::~Error (void) throw()
+{
+}
+
+OutOfMemoryError::OutOfMemoryError (VkResult error, const char* message, const char* expr, const char* file, int line)
+ : tcu::ResourceError(message, expr, file, line)
+ , m_error (error)
+{
+ DE_ASSERT(isOutOfMemoryError(error));
+}
+
+OutOfMemoryError::OutOfMemoryError (VkResult error, const std::string& message)
+ : tcu::ResourceError(message)
+ , m_error (error)
+{
+ DE_ASSERT(isOutOfMemoryError(error));
+}
+
+OutOfMemoryError::~OutOfMemoryError (void) throw()
+{
+}
+
+void checkResult (VkResult result, const char* msg, const char* file, int line)
+{
+ if (result != VK_SUCCESS)
+ {
+ std::ostringstream msgStr;
+ if (msg)
+ msgStr << msg << ": ";
+
+ msgStr << getResultStr(result);
+
+ if (isOutOfMemoryError(result))
+ throw OutOfMemoryError(result, msgStr.str().c_str(), DE_NULL, file, line);
+ else
+ throw Error(result, msgStr.str().c_str(), DE_NULL, file, line);
+ }
+}
+
+} // vk
--- /dev/null
+#ifndef _VKDEFS_HPP
+#define _VKDEFS_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Vulkan utilites.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+
+#if (DE_OS == DE_OS_ANDROID)
+# include <sys/cdefs.h>
+# if !defined(__NDK_FPABI__)
+# define __NDK_FPABI__
+# endif
+# define VKAPI_ATTR __NDK_FPABI__
+#else
+# define VKAPI_ATTR
+#endif
+
+#if (DE_OS == DE_OS_WIN32) && ((_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED))
+# define VKAPI_CALL __stdcall
+#else
+# define VKAPI_CALL
+#endif
+
+#define VK_DEFINE_HANDLE(NAME, TYPE) typedef struct NAME##_s* NAME
+#define VK_DEFINE_NON_DISPATCHABLE_HANDLE(NAME, TYPE) typedef Handle<TYPE> NAME
+
+#define VK_MAKE_VERSION(MAJOR, MINOR, PATCH) ((MAJOR << 22) | (MINOR << 12) | PATCH)
+#define VK_BIT(NUM) (1<<NUM)
+
+#define VK_CHECK(EXPR) vk::checkResult((EXPR), #EXPR, __FILE__, __LINE__)
+#define VK_CHECK_MSG(EXPR, MSG) vk::checkResult((EXPR), MSG, __FILE__, __LINE__)
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Vulkan utilities
+ *//*--------------------------------------------------------------------*/
+namespace vk
+{
+
+typedef deUint64 VkDeviceSize;
+typedef deUint32 VkSampleMask;
+typedef deUint32 VkBool32;
+typedef deUint32 VkFlags;
+
+// enum HandleType { HANDLE_TYPE_INSTANCE, ... };
+#include "vkHandleType.inl"
+
+template<HandleType Type>
+class Handle
+{
+public:
+ Handle (void) {} // \note Left uninitialized on purpose
+ Handle (deUint64 internal) : m_internal(internal) {}
+
+ Handle& operator= (deUint64 internal) { m_internal = internal; return *this; }
+
+ bool operator== (const Handle<Type>& other) const { return this->m_internal == other.m_internal; }
+ bool operator!= (const Handle<Type>& other) const { return this->m_internal != other.m_internal; }
+
+ bool operator! (void) const { return !m_internal; }
+
+ deUint64 getInternal (void) const { return m_internal; }
+
+ enum { HANDLE_TYPE = Type };
+
+private:
+ deUint64 m_internal;
+};
+
+#include "vkBasicTypes.inl"
+
+enum { VK_QUEUE_FAMILY_IGNORED = 0xffffffff };
+enum { VK_NO_ATTACHMENT = 0xffffffff };
+
+enum
+{
+ VK_FALSE = 0,
+ VK_TRUE = 1
+};
+
+typedef VKAPI_ATTR void (VKAPI_CALL* PFN_vkVoidFunction) (void);
+
+typedef VKAPI_ATTR void* (VKAPI_CALL* PFN_vkAllocationFunction) (void* pUserData, size_t size, size_t alignment, VkSystemAllocationScope allocationScope);
+typedef VKAPI_ATTR void* (VKAPI_CALL* PFN_vkReallocationFunction) (void* pUserData, void* pOriginal, size_t size, size_t alignment, VkSystemAllocationScope allocationScope);
+typedef VKAPI_ATTR void (VKAPI_CALL* PFN_vkFreeFunction) (void* pUserData, void* pMem);
+typedef VKAPI_ATTR void (VKAPI_CALL* PFN_vkInternalAllocationNotification) (void* pUserData, size_t size, VkInternalAllocationType allocationType, VkSystemAllocationScope allocationScope);
+typedef VKAPI_ATTR void (VKAPI_CALL* PFN_vkInternalFreeNotification) (void* pUserData, size_t size, VkInternalAllocationType allocationType, VkSystemAllocationScope allocationScope);
+
+#include "vkStructTypes.inl"
+
+extern "C"
+{
+#include "vkFunctionPointerTypes.inl"
+}
+
+class PlatformInterface
+{
+public:
+#include "vkVirtualPlatformInterface.inl"
+
+protected:
+ PlatformInterface (void) {}
+
+private:
+ PlatformInterface (const PlatformInterface&);
+ PlatformInterface& operator= (const PlatformInterface&);
+};
+
+class InstanceInterface
+{
+public:
+#include "vkVirtualInstanceInterface.inl"
+
+protected:
+ InstanceInterface (void) {}
+
+private:
+ InstanceInterface (const InstanceInterface&);
+ InstanceInterface& operator= (const InstanceInterface&);
+};
+
+class DeviceInterface
+{
+public:
+#include "vkVirtualDeviceInterface.inl"
+
+protected:
+ DeviceInterface (void) {}
+
+private:
+ DeviceInterface (const DeviceInterface&);
+ DeviceInterface& operator= (const DeviceInterface&);
+};
+
+class Error : public tcu::TestError
+{
+public:
+ Error (VkResult error, const char* message, const char* expr, const char* file, int line);
+ Error (VkResult error, const std::string& message);
+ virtual ~Error (void) throw();
+
+ VkResult getError (void) const { return m_error; }
+
+private:
+ const VkResult m_error;
+};
+
+class OutOfMemoryError : public tcu::ResourceError
+{
+public:
+ OutOfMemoryError (VkResult error, const char* message, const char* expr, const char* file, int line);
+ OutOfMemoryError (VkResult error, const std::string& message);
+ virtual ~OutOfMemoryError (void) throw();
+
+ VkResult getError (void) const { return m_error; }
+
+private:
+ const VkResult m_error;
+};
+
+void checkResult (VkResult result, const char* message, const char* file, int line);
+
+} // vk
+
+#endif // _VKDEFS_HPP
--- /dev/null
+/* WARNING: This is auto-generated file. Do not modify, since changes will
+ * be lost! Modify the generating script instead.
+ */
+
+void DeviceDriver::destroyDevice (VkDevice device, const VkAllocationCallbacks* pAllocator) const
+{
+ m_vk.destroyDevice(device, pAllocator);
+}
+
+void DeviceDriver::getDeviceQueue (VkDevice device, deUint32 queueFamilyIndex, deUint32 queueIndex, VkQueue* pQueue) const
+{
+ m_vk.getDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
+}
+
+VkResult DeviceDriver::queueSubmit (VkQueue queue, deUint32 submitCount, const VkSubmitInfo* pSubmits, VkFence fence) const
+{
+ return m_vk.queueSubmit(queue, submitCount, pSubmits, fence);
+}
+
+VkResult DeviceDriver::queueWaitIdle (VkQueue queue) const
+{
+ return m_vk.queueWaitIdle(queue);
+}
+
+VkResult DeviceDriver::deviceWaitIdle (VkDevice device) const
+{
+ return m_vk.deviceWaitIdle(device);
+}
+
+VkResult DeviceDriver::allocateMemory (VkDevice device, const VkMemoryAllocateInfo* pAllocateInfo, const VkAllocationCallbacks* pAllocator, VkDeviceMemory* pMemory) const
+{
+ return m_vk.allocateMemory(device, pAllocateInfo, pAllocator, pMemory);
+}
+
+void DeviceDriver::freeMemory (VkDevice device, VkDeviceMemory memory, const VkAllocationCallbacks* pAllocator) const
+{
+ m_vk.freeMemory(device, memory, pAllocator);
+}
+
+VkResult DeviceDriver::mapMemory (VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData) const
+{
+ return m_vk.mapMemory(device, memory, offset, size, flags, ppData);
+}
+
+void DeviceDriver::unmapMemory (VkDevice device, VkDeviceMemory memory) const
+{
+ m_vk.unmapMemory(device, memory);
+}
+
+VkResult DeviceDriver::flushMappedMemoryRanges (VkDevice device, deUint32 memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges) const
+{
+ return m_vk.flushMappedMemoryRanges(device, memoryRangeCount, pMemoryRanges);
+}
+
+VkResult DeviceDriver::invalidateMappedMemoryRanges (VkDevice device, deUint32 memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges) const
+{
+ return m_vk.invalidateMappedMemoryRanges(device, memoryRangeCount, pMemoryRanges);
+}
+
+void DeviceDriver::getDeviceMemoryCommitment (VkDevice device, VkDeviceMemory memory, VkDeviceSize* pCommittedMemoryInBytes) const
+{
+ m_vk.getDeviceMemoryCommitment(device, memory, pCommittedMemoryInBytes);
+}
+
+VkResult DeviceDriver::bindBufferMemory (VkDevice device, VkBuffer buffer, VkDeviceMemory memory, VkDeviceSize memoryOffset) const
+{
+ return m_vk.bindBufferMemory(device, buffer, memory, memoryOffset);
+}
+
+VkResult DeviceDriver::bindImageMemory (VkDevice device, VkImage image, VkDeviceMemory memory, VkDeviceSize memoryOffset) const
+{
+ return m_vk.bindImageMemory(device, image, memory, memoryOffset);
+}
+
+void DeviceDriver::getBufferMemoryRequirements (VkDevice device, VkBuffer buffer, VkMemoryRequirements* pMemoryRequirements) const
+{
+ m_vk.getBufferMemoryRequirements(device, buffer, pMemoryRequirements);
+}
+
+void DeviceDriver::getImageMemoryRequirements (VkDevice device, VkImage image, VkMemoryRequirements* pMemoryRequirements) const
+{
+ m_vk.getImageMemoryRequirements(device, image, pMemoryRequirements);
+}
+
+void DeviceDriver::getImageSparseMemoryRequirements (VkDevice device, VkImage image, deUint32* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements* pSparseMemoryRequirements) const
+{
+ m_vk.getImageSparseMemoryRequirements(device, image, pSparseMemoryRequirementCount, pSparseMemoryRequirements);
+}
+
+void DeviceDriver::getPhysicalDeviceSparseImageFormatProperties (VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling, deUint32* pPropertyCount, VkSparseImageFormatProperties* pProperties) const
+{
+ m_vk.getPhysicalDeviceSparseImageFormatProperties(physicalDevice, format, type, samples, usage, tiling, pPropertyCount, pProperties);
+}
+
+VkResult DeviceDriver::queueBindSparse (VkQueue queue, deUint32 bindInfoCount, const VkBindSparseInfo* pBindInfo, VkFence fence) const
+{
+ return m_vk.queueBindSparse(queue, bindInfoCount, pBindInfo, fence);
+}
+
+VkResult DeviceDriver::createFence (VkDevice device, const VkFenceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence) const
+{
+ return m_vk.createFence(device, pCreateInfo, pAllocator, pFence);
+}
+
+void DeviceDriver::destroyFence (VkDevice device, VkFence fence, const VkAllocationCallbacks* pAllocator) const
+{
+ m_vk.destroyFence(device, fence, pAllocator);
+}
+
+VkResult DeviceDriver::resetFences (VkDevice device, deUint32 fenceCount, const VkFence* pFences) const
+{
+ return m_vk.resetFences(device, fenceCount, pFences);
+}
+
+VkResult DeviceDriver::getFenceStatus (VkDevice device, VkFence fence) const
+{
+ return m_vk.getFenceStatus(device, fence);
+}
+
+VkResult DeviceDriver::waitForFences (VkDevice device, deUint32 fenceCount, const VkFence* pFences, VkBool32 waitAll, deUint64 timeout) const
+{
+ return m_vk.waitForFences(device, fenceCount, pFences, waitAll, timeout);
+}
+
+VkResult DeviceDriver::createSemaphore (VkDevice device, const VkSemaphoreCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSemaphore* pSemaphore) const
+{
+ return m_vk.createSemaphore(device, pCreateInfo, pAllocator, pSemaphore);
+}
+
+void DeviceDriver::destroySemaphore (VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks* pAllocator) const
+{
+ m_vk.destroySemaphore(device, semaphore, pAllocator);
+}
+
+VkResult DeviceDriver::createEvent (VkDevice device, const VkEventCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkEvent* pEvent) const
+{
+ return m_vk.createEvent(device, pCreateInfo, pAllocator, pEvent);
+}
+
+void DeviceDriver::destroyEvent (VkDevice device, VkEvent event, const VkAllocationCallbacks* pAllocator) const
+{
+ m_vk.destroyEvent(device, event, pAllocator);
+}
+
+VkResult DeviceDriver::getEventStatus (VkDevice device, VkEvent event) const
+{
+ return m_vk.getEventStatus(device, event);
+}
+
+VkResult DeviceDriver::setEvent (VkDevice device, VkEvent event) const
+{
+ return m_vk.setEvent(device, event);
+}
+
+VkResult DeviceDriver::resetEvent (VkDevice device, VkEvent event) const
+{
+ return m_vk.resetEvent(device, event);
+}
+
+VkResult DeviceDriver::createQueryPool (VkDevice device, const VkQueryPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkQueryPool* pQueryPool) const
+{
+ return m_vk.createQueryPool(device, pCreateInfo, pAllocator, pQueryPool);
+}
+
+void DeviceDriver::destroyQueryPool (VkDevice device, VkQueryPool queryPool, const VkAllocationCallbacks* pAllocator) const
+{
+ m_vk.destroyQueryPool(device, queryPool, pAllocator);
+}
+
+VkResult DeviceDriver::getQueryPoolResults (VkDevice device, VkQueryPool queryPool, deUint32 startQuery, deUint32 queryCount, deUintptr dataSize, void* pData, VkDeviceSize stride, VkQueryResultFlags flags) const
+{
+ return m_vk.getQueryPoolResults(device, queryPool, startQuery, queryCount, dataSize, pData, stride, flags);
+}
+
+VkResult DeviceDriver::createBuffer (VkDevice device, const VkBufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBuffer* pBuffer) const
+{
+ return m_vk.createBuffer(device, pCreateInfo, pAllocator, pBuffer);
+}
+
+void DeviceDriver::destroyBuffer (VkDevice device, VkBuffer buffer, const VkAllocationCallbacks* pAllocator) const
+{
+ m_vk.destroyBuffer(device, buffer, pAllocator);
+}
+
+VkResult DeviceDriver::createBufferView (VkDevice device, const VkBufferViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBufferView* pView) const
+{
+ return m_vk.createBufferView(device, pCreateInfo, pAllocator, pView);
+}
+
+void DeviceDriver::destroyBufferView (VkDevice device, VkBufferView bufferView, const VkAllocationCallbacks* pAllocator) const
+{
+ m_vk.destroyBufferView(device, bufferView, pAllocator);
+}
+
+VkResult DeviceDriver::createImage (VkDevice device, const VkImageCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImage* pImage) const
+{
+ return m_vk.createImage(device, pCreateInfo, pAllocator, pImage);
+}
+
+void DeviceDriver::destroyImage (VkDevice device, VkImage image, const VkAllocationCallbacks* pAllocator) const
+{
+ m_vk.destroyImage(device, image, pAllocator);
+}
+
+void DeviceDriver::getImageSubresourceLayout (VkDevice device, VkImage image, const VkImageSubresource* pSubresource, VkSubresourceLayout* pLayout) const
+{
+ m_vk.getImageSubresourceLayout(device, image, pSubresource, pLayout);
+}
+
+VkResult DeviceDriver::createImageView (VkDevice device, const VkImageViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImageView* pView) const
+{
+ return m_vk.createImageView(device, pCreateInfo, pAllocator, pView);
+}
+
+void DeviceDriver::destroyImageView (VkDevice device, VkImageView imageView, const VkAllocationCallbacks* pAllocator) const
+{
+ m_vk.destroyImageView(device, imageView, pAllocator);
+}
+
+VkResult DeviceDriver::createShaderModule (VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule) const
+{
+ return m_vk.createShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
+}
+
+void DeviceDriver::destroyShaderModule (VkDevice device, VkShaderModule shaderModule, const VkAllocationCallbacks* pAllocator) const
+{
+ m_vk.destroyShaderModule(device, shaderModule, pAllocator);
+}
+
+VkResult DeviceDriver::createPipelineCache (VkDevice device, const VkPipelineCacheCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineCache* pPipelineCache) const
+{
+ return m_vk.createPipelineCache(device, pCreateInfo, pAllocator, pPipelineCache);
+}
+
+void DeviceDriver::destroyPipelineCache (VkDevice device, VkPipelineCache pipelineCache, const VkAllocationCallbacks* pAllocator) const
+{
+ m_vk.destroyPipelineCache(device, pipelineCache, pAllocator);
+}
+
+VkResult DeviceDriver::getPipelineCacheData (VkDevice device, VkPipelineCache pipelineCache, deUintptr* pDataSize, void* pData) const
+{
+ return m_vk.getPipelineCacheData(device, pipelineCache, pDataSize, pData);
+}
+
+VkResult DeviceDriver::mergePipelineCaches (VkDevice device, VkPipelineCache dstCache, deUint32 srcCacheCount, const VkPipelineCache* pSrcCaches) const
+{
+ return m_vk.mergePipelineCaches(device, dstCache, srcCacheCount, pSrcCaches);
+}
+
+VkResult DeviceDriver::createGraphicsPipelines (VkDevice device, VkPipelineCache pipelineCache, deUint32 createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines) const
+{
+ return m_vk.createGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
+}
+
+VkResult DeviceDriver::createComputePipelines (VkDevice device, VkPipelineCache pipelineCache, deUint32 createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines) const
+{
+ return m_vk.createComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
+}
+
+void DeviceDriver::destroyPipeline (VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks* pAllocator) const
+{
+ m_vk.destroyPipeline(device, pipeline, pAllocator);
+}
+
+VkResult DeviceDriver::createPipelineLayout (VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout) const
+{
+ return m_vk.createPipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
+}
+
+void DeviceDriver::destroyPipelineLayout (VkDevice device, VkPipelineLayout pipelineLayout, const VkAllocationCallbacks* pAllocator) const
+{
+ m_vk.destroyPipelineLayout(device, pipelineLayout, pAllocator);
+}
+
+VkResult DeviceDriver::createSampler (VkDevice device, const VkSamplerCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSampler* pSampler) const
+{
+ return m_vk.createSampler(device, pCreateInfo, pAllocator, pSampler);
+}
+
+void DeviceDriver::destroySampler (VkDevice device, VkSampler sampler, const VkAllocationCallbacks* pAllocator) const
+{
+ m_vk.destroySampler(device, sampler, pAllocator);
+}
+
+VkResult DeviceDriver::createDescriptorSetLayout (VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorSetLayout* pSetLayout) const
+{
+ return m_vk.createDescriptorSetLayout(device, pCreateInfo, pAllocator, pSetLayout);
+}
+
+void DeviceDriver::destroyDescriptorSetLayout (VkDevice device, VkDescriptorSetLayout descriptorSetLayout, const VkAllocationCallbacks* pAllocator) const
+{
+ m_vk.destroyDescriptorSetLayout(device, descriptorSetLayout, pAllocator);
+}
+
+VkResult DeviceDriver::createDescriptorPool (VkDevice device, const VkDescriptorPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorPool* pDescriptorPool) const
+{
+ return m_vk.createDescriptorPool(device, pCreateInfo, pAllocator, pDescriptorPool);
+}
+
+void DeviceDriver::destroyDescriptorPool (VkDevice device, VkDescriptorPool descriptorPool, const VkAllocationCallbacks* pAllocator) const
+{
+ m_vk.destroyDescriptorPool(device, descriptorPool, pAllocator);
+}
+
+VkResult DeviceDriver::resetDescriptorPool (VkDevice device, VkDescriptorPool descriptorPool, VkDescriptorPoolResetFlags flags) const
+{
+ return m_vk.resetDescriptorPool(device, descriptorPool, flags);
+}
+
+VkResult DeviceDriver::allocateDescriptorSets (VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets) const
+{
+ return m_vk.allocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
+}
+
+VkResult DeviceDriver::freeDescriptorSets (VkDevice device, VkDescriptorPool descriptorPool, deUint32 descriptorSetCount, const VkDescriptorSet* pDescriptorSets) const
+{
+ return m_vk.freeDescriptorSets(device, descriptorPool, descriptorSetCount, pDescriptorSets);
+}
+
+void DeviceDriver::updateDescriptorSets (VkDevice device, deUint32 descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites, deUint32 descriptorCopyCount, const VkCopyDescriptorSet* pDescriptorCopies) const
+{
+ m_vk.updateDescriptorSets(device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, pDescriptorCopies);
+}
+
+VkResult DeviceDriver::createFramebuffer (VkDevice device, const VkFramebufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkFramebuffer* pFramebuffer) const
+{
+ return m_vk.createFramebuffer(device, pCreateInfo, pAllocator, pFramebuffer);
+}
+
+void DeviceDriver::destroyFramebuffer (VkDevice device, VkFramebuffer framebuffer, const VkAllocationCallbacks* pAllocator) const
+{
+ m_vk.destroyFramebuffer(device, framebuffer, pAllocator);
+}
+
+VkResult DeviceDriver::createRenderPass (VkDevice device, const VkRenderPassCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass) const
+{
+ return m_vk.createRenderPass(device, pCreateInfo, pAllocator, pRenderPass);
+}
+
+void DeviceDriver::destroyRenderPass (VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks* pAllocator) const
+{
+ m_vk.destroyRenderPass(device, renderPass, pAllocator);
+}
+
+void DeviceDriver::getRenderAreaGranularity (VkDevice device, VkRenderPass renderPass, VkExtent2D* pGranularity) const
+{
+ m_vk.getRenderAreaGranularity(device, renderPass, pGranularity);
+}
+
+VkResult DeviceDriver::createCommandPool (VkDevice device, const VkCommandPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCommandPool* pCommandPool) const
+{
+ return m_vk.createCommandPool(device, pCreateInfo, pAllocator, pCommandPool);
+}
+
+void DeviceDriver::destroyCommandPool (VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks* pAllocator) const
+{
+ m_vk.destroyCommandPool(device, commandPool, pAllocator);
+}
+
+VkResult DeviceDriver::resetCommandPool (VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags) const
+{
+ return m_vk.resetCommandPool(device, commandPool, flags);
+}
+
+VkResult DeviceDriver::allocateCommandBuffers (VkDevice device, const VkCommandBufferAllocateInfo* pAllocateInfo, VkCommandBuffer* pCommandBuffers) const
+{
+ return m_vk.allocateCommandBuffers(device, pAllocateInfo, pCommandBuffers);
+}
+
+void DeviceDriver::freeCommandBuffers (VkDevice device, VkCommandPool commandPool, deUint32 commandBufferCount, const VkCommandBuffer* pCommandBuffers) const
+{
+ m_vk.freeCommandBuffers(device, commandPool, commandBufferCount, pCommandBuffers);
+}
+
+VkResult DeviceDriver::beginCommandBuffer (VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo* pBeginInfo) const
+{
+ return m_vk.beginCommandBuffer(commandBuffer, pBeginInfo);
+}
+
+VkResult DeviceDriver::endCommandBuffer (VkCommandBuffer commandBuffer) const
+{
+ return m_vk.endCommandBuffer(commandBuffer);
+}
+
+VkResult DeviceDriver::resetCommandBuffer (VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags) const
+{
+ return m_vk.resetCommandBuffer(commandBuffer, flags);
+}
+
+void DeviceDriver::cmdBindPipeline (VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline) const
+{
+ m_vk.cmdBindPipeline(commandBuffer, pipelineBindPoint, pipeline);
+}
+
+void DeviceDriver::cmdSetViewport (VkCommandBuffer commandBuffer, deUint32 viewportCount, const VkViewport* pViewports) const
+{
+ m_vk.cmdSetViewport(commandBuffer, viewportCount, pViewports);
+}
+
+void DeviceDriver::cmdSetScissor (VkCommandBuffer commandBuffer, deUint32 scissorCount, const VkRect2D* pScissors) const
+{
+ m_vk.cmdSetScissor(commandBuffer, scissorCount, pScissors);
+}
+
+void DeviceDriver::cmdSetLineWidth (VkCommandBuffer commandBuffer, float lineWidth) const
+{
+ m_vk.cmdSetLineWidth(commandBuffer, lineWidth);
+}
+
+void DeviceDriver::cmdSetDepthBias (VkCommandBuffer commandBuffer, float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor) const
+{
+ m_vk.cmdSetDepthBias(commandBuffer, depthBiasConstantFactor, depthBiasClamp, depthBiasSlopeFactor);
+}
+
+void DeviceDriver::cmdSetBlendConstants (VkCommandBuffer commandBuffer, const float blendConstants[4]) const
+{
+ m_vk.cmdSetBlendConstants(commandBuffer, blendConstants);
+}
+
+void DeviceDriver::cmdSetDepthBounds (VkCommandBuffer commandBuffer, float minDepthBounds, float maxDepthBounds) const
+{
+ m_vk.cmdSetDepthBounds(commandBuffer, minDepthBounds, maxDepthBounds);
+}
+
+void DeviceDriver::cmdSetStencilCompareMask (VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, deUint32 compareMask) const
+{
+ m_vk.cmdSetStencilCompareMask(commandBuffer, faceMask, compareMask);
+}
+
+void DeviceDriver::cmdSetStencilWriteMask (VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, deUint32 writeMask) const
+{
+ m_vk.cmdSetStencilWriteMask(commandBuffer, faceMask, writeMask);
+}
+
+void DeviceDriver::cmdSetStencilReference (VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, deUint32 reference) const
+{
+ m_vk.cmdSetStencilReference(commandBuffer, faceMask, reference);
+}
+
+void DeviceDriver::cmdBindDescriptorSets (VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, deUint32 firstSet, deUint32 descriptorSetCount, const VkDescriptorSet* pDescriptorSets, deUint32 dynamicOffsetCount, const deUint32* pDynamicOffsets) const
+{
+ m_vk.cmdBindDescriptorSets(commandBuffer, pipelineBindPoint, layout, firstSet, descriptorSetCount, pDescriptorSets, dynamicOffsetCount, pDynamicOffsets);
+}
+
+void DeviceDriver::cmdBindIndexBuffer (VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType) const
+{
+ m_vk.cmdBindIndexBuffer(commandBuffer, buffer, offset, indexType);
+}
+
+void DeviceDriver::cmdBindVertexBuffers (VkCommandBuffer commandBuffer, deUint32 startBinding, deUint32 bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets) const
+{
+ m_vk.cmdBindVertexBuffers(commandBuffer, startBinding, bindingCount, pBuffers, pOffsets);
+}
+
+void DeviceDriver::cmdDraw (VkCommandBuffer commandBuffer, deUint32 vertexCount, deUint32 instanceCount, deUint32 firstVertex, deUint32 firstInstance) const
+{
+ m_vk.cmdDraw(commandBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
+}
+
+void DeviceDriver::cmdDrawIndexed (VkCommandBuffer commandBuffer, deUint32 indexCount, deUint32 instanceCount, deUint32 firstIndex, deInt32 vertexOffset, deUint32 firstInstance) const
+{
+ m_vk.cmdDrawIndexed(commandBuffer, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
+}
+
+void DeviceDriver::cmdDrawIndirect (VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, deUint32 drawCount, deUint32 stride) const
+{
+ m_vk.cmdDrawIndirect(commandBuffer, buffer, offset, drawCount, stride);
+}
+
+void DeviceDriver::cmdDrawIndexedIndirect (VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, deUint32 drawCount, deUint32 stride) const
+{
+ m_vk.cmdDrawIndexedIndirect(commandBuffer, buffer, offset, drawCount, stride);
+}
+
+void DeviceDriver::cmdDispatch (VkCommandBuffer commandBuffer, deUint32 x, deUint32 y, deUint32 z) const
+{
+ m_vk.cmdDispatch(commandBuffer, x, y, z);
+}
+
+void DeviceDriver::cmdDispatchIndirect (VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) const
+{
+ m_vk.cmdDispatchIndirect(commandBuffer, buffer, offset);
+}
+
+void DeviceDriver::cmdCopyBuffer (VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, deUint32 regionCount, const VkBufferCopy* pRegions) const
+{
+ m_vk.cmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, regionCount, pRegions);
+}
+
+void DeviceDriver::cmdCopyImage (VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, deUint32 regionCount, const VkImageCopy* pRegions) const
+{
+ m_vk.cmdCopyImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions);
+}
+
+void DeviceDriver::cmdBlitImage (VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, deUint32 regionCount, const VkImageBlit* pRegions, VkFilter filter) const
+{
+ m_vk.cmdBlitImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions, filter);
+}
+
+void DeviceDriver::cmdCopyBufferToImage (VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage, VkImageLayout dstImageLayout, deUint32 regionCount, const VkBufferImageCopy* pRegions) const
+{
+ m_vk.cmdCopyBufferToImage(commandBuffer, srcBuffer, dstImage, dstImageLayout, regionCount, pRegions);
+}
+
+void DeviceDriver::cmdCopyImageToBuffer (VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkBuffer dstBuffer, deUint32 regionCount, const VkBufferImageCopy* pRegions) const
+{
+ m_vk.cmdCopyImageToBuffer(commandBuffer, srcImage, srcImageLayout, dstBuffer, regionCount, pRegions);
+}
+
+void DeviceDriver::cmdUpdateBuffer (VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const deUint32* pData) const
+{
+ m_vk.cmdUpdateBuffer(commandBuffer, dstBuffer, dstOffset, dataSize, pData);
+}
+
+void DeviceDriver::cmdFillBuffer (VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, deUint32 data) const
+{
+ m_vk.cmdFillBuffer(commandBuffer, dstBuffer, dstOffset, size, data);
+}
+
+void DeviceDriver::cmdClearColorImage (VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearColorValue* pColor, deUint32 rangeCount, const VkImageSubresourceRange* pRanges) const
+{
+ m_vk.cmdClearColorImage(commandBuffer, image, imageLayout, pColor, rangeCount, pRanges);
+}
+
+void DeviceDriver::cmdClearDepthStencilImage (VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearDepthStencilValue* pDepthStencil, deUint32 rangeCount, const VkImageSubresourceRange* pRanges) const
+{
+ m_vk.cmdClearDepthStencilImage(commandBuffer, image, imageLayout, pDepthStencil, rangeCount, pRanges);
+}
+
+void DeviceDriver::cmdClearAttachments (VkCommandBuffer commandBuffer, deUint32 attachmentCount, const VkClearAttachment* pAttachments, deUint32 rectCount, const VkClearRect* pRects) const
+{
+ m_vk.cmdClearAttachments(commandBuffer, attachmentCount, pAttachments, rectCount, pRects);
+}
+
+void DeviceDriver::cmdResolveImage (VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, deUint32 regionCount, const VkImageResolve* pRegions) const
+{
+ m_vk.cmdResolveImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions);
+}
+
+void DeviceDriver::cmdSetEvent (VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) const
+{
+ m_vk.cmdSetEvent(commandBuffer, event, stageMask);
+}
+
+void DeviceDriver::cmdResetEvent (VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) const
+{
+ m_vk.cmdResetEvent(commandBuffer, event, stageMask);
+}
+
+void DeviceDriver::cmdWaitEvents (VkCommandBuffer commandBuffer, deUint32 eventCount, const VkEvent* pEvents, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, deUint32 memoryBarrierCount, const void* const* ppMemoryBarriers) const
+{
+ m_vk.cmdWaitEvents(commandBuffer, eventCount, pEvents, srcStageMask, dstStageMask, memoryBarrierCount, ppMemoryBarriers);
+}
+
+void DeviceDriver::cmdPipelineBarrier (VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, deUint32 memoryBarrierCount, const void* const* ppMemoryBarriers) const
+{
+ m_vk.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount, ppMemoryBarriers);
+}
+
+void DeviceDriver::cmdBeginQuery (VkCommandBuffer commandBuffer, VkQueryPool queryPool, deUint32 entry, VkQueryControlFlags flags) const
+{
+ m_vk.cmdBeginQuery(commandBuffer, queryPool, entry, flags);
+}
+
+void DeviceDriver::cmdEndQuery (VkCommandBuffer commandBuffer, VkQueryPool queryPool, deUint32 entry) const
+{
+ m_vk.cmdEndQuery(commandBuffer, queryPool, entry);
+}
+
+void DeviceDriver::cmdResetQueryPool (VkCommandBuffer commandBuffer, VkQueryPool queryPool, deUint32 startQuery, deUint32 queryCount) const
+{
+ m_vk.cmdResetQueryPool(commandBuffer, queryPool, startQuery, queryCount);
+}
+
+void DeviceDriver::cmdWriteTimestamp (VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkQueryPool queryPool, deUint32 entry) const
+{
+ m_vk.cmdWriteTimestamp(commandBuffer, pipelineStage, queryPool, entry);
+}
+
+void DeviceDriver::cmdCopyQueryPoolResults (VkCommandBuffer commandBuffer, VkQueryPool queryPool, deUint32 startQuery, deUint32 queryCount, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags) const
+{
+ m_vk.cmdCopyQueryPoolResults(commandBuffer, queryPool, startQuery, queryCount, dstBuffer, dstOffset, stride, flags);
+}
+
+void DeviceDriver::cmdPushConstants (VkCommandBuffer commandBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, deUint32 offset, deUint32 size, const void* pValues) const
+{
+ m_vk.cmdPushConstants(commandBuffer, layout, stageFlags, offset, size, pValues);
+}
+
+void DeviceDriver::cmdBeginRenderPass (VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, VkSubpassContents contents) const
+{
+ m_vk.cmdBeginRenderPass(commandBuffer, pRenderPassBegin, contents);
+}
+
+void DeviceDriver::cmdNextSubpass (VkCommandBuffer commandBuffer, VkSubpassContents contents) const
+{
+ m_vk.cmdNextSubpass(commandBuffer, contents);
+}
+
+void DeviceDriver::cmdEndRenderPass (VkCommandBuffer commandBuffer) const
+{
+ m_vk.cmdEndRenderPass(commandBuffer);
+}
+
+void DeviceDriver::cmdExecuteCommands (VkCommandBuffer commandBuffer, deUint32 commandBuffersCount, const VkCommandBuffer* pCommandBuffers) const
+{
+ m_vk.cmdExecuteCommands(commandBuffer, commandBuffersCount, pCommandBuffers);
+}
--- /dev/null
+/* WARNING: This is auto-generated file. Do not modify, since changes will
+ * be lost! Modify the generating script instead.
+ */
+DestroyDeviceFunc destroyDevice;
+GetDeviceQueueFunc getDeviceQueue;
+QueueSubmitFunc queueSubmit;
+QueueWaitIdleFunc queueWaitIdle;
+DeviceWaitIdleFunc deviceWaitIdle;
+AllocateMemoryFunc allocateMemory;
+FreeMemoryFunc freeMemory;
+MapMemoryFunc mapMemory;
+UnmapMemoryFunc unmapMemory;
+FlushMappedMemoryRangesFunc flushMappedMemoryRanges;
+InvalidateMappedMemoryRangesFunc invalidateMappedMemoryRanges;
+GetDeviceMemoryCommitmentFunc getDeviceMemoryCommitment;
+BindBufferMemoryFunc bindBufferMemory;
+BindImageMemoryFunc bindImageMemory;
+GetBufferMemoryRequirementsFunc getBufferMemoryRequirements;
+GetImageMemoryRequirementsFunc getImageMemoryRequirements;
+GetImageSparseMemoryRequirementsFunc getImageSparseMemoryRequirements;
+GetPhysicalDeviceSparseImageFormatPropertiesFunc getPhysicalDeviceSparseImageFormatProperties;
+QueueBindSparseFunc queueBindSparse;
+CreateFenceFunc createFence;
+DestroyFenceFunc destroyFence;
+ResetFencesFunc resetFences;
+GetFenceStatusFunc getFenceStatus;
+WaitForFencesFunc waitForFences;
+CreateSemaphoreFunc createSemaphore;
+DestroySemaphoreFunc destroySemaphore;
+CreateEventFunc createEvent;
+DestroyEventFunc destroyEvent;
+GetEventStatusFunc getEventStatus;
+SetEventFunc setEvent;
+ResetEventFunc resetEvent;
+CreateQueryPoolFunc createQueryPool;
+DestroyQueryPoolFunc destroyQueryPool;
+GetQueryPoolResultsFunc getQueryPoolResults;
+CreateBufferFunc createBuffer;
+DestroyBufferFunc destroyBuffer;
+CreateBufferViewFunc createBufferView;
+DestroyBufferViewFunc destroyBufferView;
+CreateImageFunc createImage;
+DestroyImageFunc destroyImage;
+GetImageSubresourceLayoutFunc getImageSubresourceLayout;
+CreateImageViewFunc createImageView;
+DestroyImageViewFunc destroyImageView;
+CreateShaderModuleFunc createShaderModule;
+DestroyShaderModuleFunc destroyShaderModule;
+CreatePipelineCacheFunc createPipelineCache;
+DestroyPipelineCacheFunc destroyPipelineCache;
+GetPipelineCacheDataFunc getPipelineCacheData;
+MergePipelineCachesFunc mergePipelineCaches;
+CreateGraphicsPipelinesFunc createGraphicsPipelines;
+CreateComputePipelinesFunc createComputePipelines;
+DestroyPipelineFunc destroyPipeline;
+CreatePipelineLayoutFunc createPipelineLayout;
+DestroyPipelineLayoutFunc destroyPipelineLayout;
+CreateSamplerFunc createSampler;
+DestroySamplerFunc destroySampler;
+CreateDescriptorSetLayoutFunc createDescriptorSetLayout;
+DestroyDescriptorSetLayoutFunc destroyDescriptorSetLayout;
+CreateDescriptorPoolFunc createDescriptorPool;
+DestroyDescriptorPoolFunc destroyDescriptorPool;
+ResetDescriptorPoolFunc resetDescriptorPool;
+AllocateDescriptorSetsFunc allocateDescriptorSets;
+FreeDescriptorSetsFunc freeDescriptorSets;
+UpdateDescriptorSetsFunc updateDescriptorSets;
+CreateFramebufferFunc createFramebuffer;
+DestroyFramebufferFunc destroyFramebuffer;
+CreateRenderPassFunc createRenderPass;
+DestroyRenderPassFunc destroyRenderPass;
+GetRenderAreaGranularityFunc getRenderAreaGranularity;
+CreateCommandPoolFunc createCommandPool;
+DestroyCommandPoolFunc destroyCommandPool;
+ResetCommandPoolFunc resetCommandPool;
+AllocateCommandBuffersFunc allocateCommandBuffers;
+FreeCommandBuffersFunc freeCommandBuffers;
+BeginCommandBufferFunc beginCommandBuffer;
+EndCommandBufferFunc endCommandBuffer;
+ResetCommandBufferFunc resetCommandBuffer;
+CmdBindPipelineFunc cmdBindPipeline;
+CmdSetViewportFunc cmdSetViewport;
+CmdSetScissorFunc cmdSetScissor;
+CmdSetLineWidthFunc cmdSetLineWidth;
+CmdSetDepthBiasFunc cmdSetDepthBias;
+CmdSetBlendConstantsFunc cmdSetBlendConstants;
+CmdSetDepthBoundsFunc cmdSetDepthBounds;
+CmdSetStencilCompareMaskFunc cmdSetStencilCompareMask;
+CmdSetStencilWriteMaskFunc cmdSetStencilWriteMask;
+CmdSetStencilReferenceFunc cmdSetStencilReference;
+CmdBindDescriptorSetsFunc cmdBindDescriptorSets;
+CmdBindIndexBufferFunc cmdBindIndexBuffer;
+CmdBindVertexBuffersFunc cmdBindVertexBuffers;
+CmdDrawFunc cmdDraw;
+CmdDrawIndexedFunc cmdDrawIndexed;
+CmdDrawIndirectFunc cmdDrawIndirect;
+CmdDrawIndexedIndirectFunc cmdDrawIndexedIndirect;
+CmdDispatchFunc cmdDispatch;
+CmdDispatchIndirectFunc cmdDispatchIndirect;
+CmdCopyBufferFunc cmdCopyBuffer;
+CmdCopyImageFunc cmdCopyImage;
+CmdBlitImageFunc cmdBlitImage;
+CmdCopyBufferToImageFunc cmdCopyBufferToImage;
+CmdCopyImageToBufferFunc cmdCopyImageToBuffer;
+CmdUpdateBufferFunc cmdUpdateBuffer;
+CmdFillBufferFunc cmdFillBuffer;
+CmdClearColorImageFunc cmdClearColorImage;
+CmdClearDepthStencilImageFunc cmdClearDepthStencilImage;
+CmdClearAttachmentsFunc cmdClearAttachments;
+CmdResolveImageFunc cmdResolveImage;
+CmdSetEventFunc cmdSetEvent;
+CmdResetEventFunc cmdResetEvent;
+CmdWaitEventsFunc cmdWaitEvents;
+CmdPipelineBarrierFunc cmdPipelineBarrier;
+CmdBeginQueryFunc cmdBeginQuery;
+CmdEndQueryFunc cmdEndQuery;
+CmdResetQueryPoolFunc cmdResetQueryPool;
+CmdWriteTimestampFunc cmdWriteTimestamp;
+CmdCopyQueryPoolResultsFunc cmdCopyQueryPoolResults;
+CmdPushConstantsFunc cmdPushConstants;
+CmdBeginRenderPassFunc cmdBeginRenderPass;
+CmdNextSubpassFunc cmdNextSubpass;
+CmdEndRenderPassFunc cmdEndRenderPass;
+CmdExecuteCommandsFunc cmdExecuteCommands;
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Instance and device initialization utilities.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkDeviceUtil.hpp"
+#include "vkQueryUtil.hpp"
+#include "vkRefUtil.hpp"
+
+#include "tcuCommandLine.hpp"
+
+#include "qpInfo.h"
+
+#include <vector>
+
+namespace vk
+{
+
+using std::vector;
+
+Move<VkInstance> createDefaultInstance (const PlatformInterface& vkPlatform)
+{
+ const struct VkApplicationInfo appInfo =
+ {
+ VK_STRUCTURE_TYPE_APPLICATION_INFO,
+ DE_NULL,
+ "deqp", // pAppName
+ qpGetReleaseId(), // appVersion
+ "deqp", // pEngineName
+ qpGetReleaseId(), // engineVersion
+ VK_API_VERSION // apiVersion
+ };
+ const struct VkInstanceCreateInfo instanceInfo =
+ {
+ VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
+ DE_NULL,
+ (VkInstanceCreateFlags)0,
+ &appInfo,
+ 0u, // enabledLayerNameCount
+ DE_NULL, // ppEnabledLayerNames
+ 0u, // enabledExtensionNameCount;
+ DE_NULL // ppEnabledExtensionNames
+ };
+
+ return createInstance(vkPlatform, &instanceInfo);
+}
+
+VkPhysicalDevice chooseDevice (const InstanceInterface& vkInstance, VkInstance instance, const tcu::CommandLine& cmdLine)
+{
+ const vector<VkPhysicalDevice> devices = enumeratePhysicalDevices(vkInstance, instance);
+
+ if (devices.empty())
+ TCU_THROW(NotSupportedError, "No Vulkan devices available");
+
+ if (!de::inBounds(cmdLine.getVKDeviceId(), 1, (int)devices.size()+1))
+ TCU_THROW(InternalError, "Invalid --deqp-vk-device-id");
+
+ return devices[(size_t)(cmdLine.getVKDeviceId()-1)];
+}
+
+} // vk
--- /dev/null
+#ifndef _VKDEVICEUTIL_HPP
+#define _VKDEVICEUTIL_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Instance and device initialization utilities.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkDefs.hpp"
+#include "vkRef.hpp"
+
+namespace tcu
+{
+class CommandLine;
+}
+
+namespace vk
+{
+
+Move<VkInstance> createDefaultInstance (const PlatformInterface& vkPlatform);
+VkPhysicalDevice chooseDevice (const InstanceInterface& vkInstance, VkInstance instance, const tcu::CommandLine& cmdLine);
+
+} // vk
+
+#endif // _VKDEVICEUTIL_HPP
--- /dev/null
+/* WARNING: This is auto-generated file. Do not modify, since changes will
+ * be lost! Modify the generating script instead.
+ */
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* CreateInstanceFunc) (const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance);
+typedef VKAPI_ATTR void (VKAPI_CALL* DestroyInstanceFunc) (VkInstance instance, const VkAllocationCallbacks* pAllocator);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* EnumeratePhysicalDevicesFunc) (VkInstance instance, deUint32* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices);
+typedef VKAPI_ATTR void (VKAPI_CALL* GetPhysicalDeviceFeaturesFunc) (VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures* pFeatures);
+typedef VKAPI_ATTR void (VKAPI_CALL* GetPhysicalDeviceFormatPropertiesFunc) (VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties* pFormatProperties);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* GetPhysicalDeviceImageFormatPropertiesFunc) (VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties* pImageFormatProperties);
+typedef VKAPI_ATTR void (VKAPI_CALL* GetPhysicalDevicePropertiesFunc) (VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties* pProperties);
+typedef VKAPI_ATTR void (VKAPI_CALL* GetPhysicalDeviceQueueFamilyPropertiesFunc) (VkPhysicalDevice physicalDevice, deUint32* pQueueFamilyPropertyCount, VkQueueFamilyProperties* pQueueFamilyProperties);
+typedef VKAPI_ATTR void (VKAPI_CALL* GetPhysicalDeviceMemoryPropertiesFunc) (VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties* pMemoryProperties);
+typedef VKAPI_ATTR PFN_vkVoidFunction (VKAPI_CALL* GetInstanceProcAddrFunc) (VkInstance instance, const char* pName);
+typedef VKAPI_ATTR PFN_vkVoidFunction (VKAPI_CALL* GetDeviceProcAddrFunc) (VkDevice device, const char* pName);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* CreateDeviceFunc) (VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice);
+typedef VKAPI_ATTR void (VKAPI_CALL* DestroyDeviceFunc) (VkDevice device, const VkAllocationCallbacks* pAllocator);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* EnumerateInstanceExtensionPropertiesFunc) (const char* pLayerName, deUint32* pPropertyCount, VkExtensionProperties* pProperties);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* EnumerateDeviceExtensionPropertiesFunc) (VkPhysicalDevice physicalDevice, const char* pLayerName, deUint32* pPropertyCount, VkExtensionProperties* pProperties);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* EnumerateInstanceLayerPropertiesFunc) (deUint32* pPropertyCount, VkLayerProperties* pProperties);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* EnumerateDeviceLayerPropertiesFunc) (VkPhysicalDevice physicalDevice, deUint32* pPropertyCount, VkLayerProperties* pProperties);
+typedef VKAPI_ATTR void (VKAPI_CALL* GetDeviceQueueFunc) (VkDevice device, deUint32 queueFamilyIndex, deUint32 queueIndex, VkQueue* pQueue);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* QueueSubmitFunc) (VkQueue queue, deUint32 submitCount, const VkSubmitInfo* pSubmits, VkFence fence);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* QueueWaitIdleFunc) (VkQueue queue);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* DeviceWaitIdleFunc) (VkDevice device);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* AllocateMemoryFunc) (VkDevice device, const VkMemoryAllocateInfo* pAllocateInfo, const VkAllocationCallbacks* pAllocator, VkDeviceMemory* pMemory);
+typedef VKAPI_ATTR void (VKAPI_CALL* FreeMemoryFunc) (VkDevice device, VkDeviceMemory memory, const VkAllocationCallbacks* pAllocator);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* MapMemoryFunc) (VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData);
+typedef VKAPI_ATTR void (VKAPI_CALL* UnmapMemoryFunc) (VkDevice device, VkDeviceMemory memory);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* FlushMappedMemoryRangesFunc) (VkDevice device, deUint32 memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* InvalidateMappedMemoryRangesFunc) (VkDevice device, deUint32 memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges);
+typedef VKAPI_ATTR void (VKAPI_CALL* GetDeviceMemoryCommitmentFunc) (VkDevice device, VkDeviceMemory memory, VkDeviceSize* pCommittedMemoryInBytes);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* BindBufferMemoryFunc) (VkDevice device, VkBuffer buffer, VkDeviceMemory memory, VkDeviceSize memoryOffset);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* BindImageMemoryFunc) (VkDevice device, VkImage image, VkDeviceMemory memory, VkDeviceSize memoryOffset);
+typedef VKAPI_ATTR void (VKAPI_CALL* GetBufferMemoryRequirementsFunc) (VkDevice device, VkBuffer buffer, VkMemoryRequirements* pMemoryRequirements);
+typedef VKAPI_ATTR void (VKAPI_CALL* GetImageMemoryRequirementsFunc) (VkDevice device, VkImage image, VkMemoryRequirements* pMemoryRequirements);
+typedef VKAPI_ATTR void (VKAPI_CALL* GetImageSparseMemoryRequirementsFunc) (VkDevice device, VkImage image, deUint32* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements* pSparseMemoryRequirements);
+typedef VKAPI_ATTR void (VKAPI_CALL* GetPhysicalDeviceSparseImageFormatPropertiesFunc) (VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling, deUint32* pPropertyCount, VkSparseImageFormatProperties* pProperties);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* QueueBindSparseFunc) (VkQueue queue, deUint32 bindInfoCount, const VkBindSparseInfo* pBindInfo, VkFence fence);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* CreateFenceFunc) (VkDevice device, const VkFenceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence);
+typedef VKAPI_ATTR void (VKAPI_CALL* DestroyFenceFunc) (VkDevice device, VkFence fence, const VkAllocationCallbacks* pAllocator);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* ResetFencesFunc) (VkDevice device, deUint32 fenceCount, const VkFence* pFences);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* GetFenceStatusFunc) (VkDevice device, VkFence fence);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* WaitForFencesFunc) (VkDevice device, deUint32 fenceCount, const VkFence* pFences, VkBool32 waitAll, deUint64 timeout);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* CreateSemaphoreFunc) (VkDevice device, const VkSemaphoreCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSemaphore* pSemaphore);
+typedef VKAPI_ATTR void (VKAPI_CALL* DestroySemaphoreFunc) (VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks* pAllocator);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* CreateEventFunc) (VkDevice device, const VkEventCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkEvent* pEvent);
+typedef VKAPI_ATTR void (VKAPI_CALL* DestroyEventFunc) (VkDevice device, VkEvent event, const VkAllocationCallbacks* pAllocator);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* GetEventStatusFunc) (VkDevice device, VkEvent event);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* SetEventFunc) (VkDevice device, VkEvent event);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* ResetEventFunc) (VkDevice device, VkEvent event);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* CreateQueryPoolFunc) (VkDevice device, const VkQueryPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkQueryPool* pQueryPool);
+typedef VKAPI_ATTR void (VKAPI_CALL* DestroyQueryPoolFunc) (VkDevice device, VkQueryPool queryPool, const VkAllocationCallbacks* pAllocator);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* GetQueryPoolResultsFunc) (VkDevice device, VkQueryPool queryPool, deUint32 startQuery, deUint32 queryCount, deUintptr dataSize, void* pData, VkDeviceSize stride, VkQueryResultFlags flags);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* CreateBufferFunc) (VkDevice device, const VkBufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBuffer* pBuffer);
+typedef VKAPI_ATTR void (VKAPI_CALL* DestroyBufferFunc) (VkDevice device, VkBuffer buffer, const VkAllocationCallbacks* pAllocator);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* CreateBufferViewFunc) (VkDevice device, const VkBufferViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBufferView* pView);
+typedef VKAPI_ATTR void (VKAPI_CALL* DestroyBufferViewFunc) (VkDevice device, VkBufferView bufferView, const VkAllocationCallbacks* pAllocator);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* CreateImageFunc) (VkDevice device, const VkImageCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImage* pImage);
+typedef VKAPI_ATTR void (VKAPI_CALL* DestroyImageFunc) (VkDevice device, VkImage image, const VkAllocationCallbacks* pAllocator);
+typedef VKAPI_ATTR void (VKAPI_CALL* GetImageSubresourceLayoutFunc) (VkDevice device, VkImage image, const VkImageSubresource* pSubresource, VkSubresourceLayout* pLayout);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* CreateImageViewFunc) (VkDevice device, const VkImageViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImageView* pView);
+typedef VKAPI_ATTR void (VKAPI_CALL* DestroyImageViewFunc) (VkDevice device, VkImageView imageView, const VkAllocationCallbacks* pAllocator);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* CreateShaderModuleFunc) (VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule);
+typedef VKAPI_ATTR void (VKAPI_CALL* DestroyShaderModuleFunc) (VkDevice device, VkShaderModule shaderModule, const VkAllocationCallbacks* pAllocator);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* CreatePipelineCacheFunc) (VkDevice device, const VkPipelineCacheCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineCache* pPipelineCache);
+typedef VKAPI_ATTR void (VKAPI_CALL* DestroyPipelineCacheFunc) (VkDevice device, VkPipelineCache pipelineCache, const VkAllocationCallbacks* pAllocator);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* GetPipelineCacheDataFunc) (VkDevice device, VkPipelineCache pipelineCache, deUintptr* pDataSize, void* pData);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* MergePipelineCachesFunc) (VkDevice device, VkPipelineCache dstCache, deUint32 srcCacheCount, const VkPipelineCache* pSrcCaches);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* CreateGraphicsPipelinesFunc) (VkDevice device, VkPipelineCache pipelineCache, deUint32 createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* CreateComputePipelinesFunc) (VkDevice device, VkPipelineCache pipelineCache, deUint32 createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines);
+typedef VKAPI_ATTR void (VKAPI_CALL* DestroyPipelineFunc) (VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks* pAllocator);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* CreatePipelineLayoutFunc) (VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout);
+typedef VKAPI_ATTR void (VKAPI_CALL* DestroyPipelineLayoutFunc) (VkDevice device, VkPipelineLayout pipelineLayout, const VkAllocationCallbacks* pAllocator);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* CreateSamplerFunc) (VkDevice device, const VkSamplerCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSampler* pSampler);
+typedef VKAPI_ATTR void (VKAPI_CALL* DestroySamplerFunc) (VkDevice device, VkSampler sampler, const VkAllocationCallbacks* pAllocator);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* CreateDescriptorSetLayoutFunc) (VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorSetLayout* pSetLayout);
+typedef VKAPI_ATTR void (VKAPI_CALL* DestroyDescriptorSetLayoutFunc) (VkDevice device, VkDescriptorSetLayout descriptorSetLayout, const VkAllocationCallbacks* pAllocator);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* CreateDescriptorPoolFunc) (VkDevice device, const VkDescriptorPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorPool* pDescriptorPool);
+typedef VKAPI_ATTR void (VKAPI_CALL* DestroyDescriptorPoolFunc) (VkDevice device, VkDescriptorPool descriptorPool, const VkAllocationCallbacks* pAllocator);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* ResetDescriptorPoolFunc) (VkDevice device, VkDescriptorPool descriptorPool, VkDescriptorPoolResetFlags flags);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* AllocateDescriptorSetsFunc) (VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* FreeDescriptorSetsFunc) (VkDevice device, VkDescriptorPool descriptorPool, deUint32 descriptorSetCount, const VkDescriptorSet* pDescriptorSets);
+typedef VKAPI_ATTR void (VKAPI_CALL* UpdateDescriptorSetsFunc) (VkDevice device, deUint32 descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites, deUint32 descriptorCopyCount, const VkCopyDescriptorSet* pDescriptorCopies);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* CreateFramebufferFunc) (VkDevice device, const VkFramebufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkFramebuffer* pFramebuffer);
+typedef VKAPI_ATTR void (VKAPI_CALL* DestroyFramebufferFunc) (VkDevice device, VkFramebuffer framebuffer, const VkAllocationCallbacks* pAllocator);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* CreateRenderPassFunc) (VkDevice device, const VkRenderPassCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass);
+typedef VKAPI_ATTR void (VKAPI_CALL* DestroyRenderPassFunc) (VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks* pAllocator);
+typedef VKAPI_ATTR void (VKAPI_CALL* GetRenderAreaGranularityFunc) (VkDevice device, VkRenderPass renderPass, VkExtent2D* pGranularity);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* CreateCommandPoolFunc) (VkDevice device, const VkCommandPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCommandPool* pCommandPool);
+typedef VKAPI_ATTR void (VKAPI_CALL* DestroyCommandPoolFunc) (VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks* pAllocator);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* ResetCommandPoolFunc) (VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* AllocateCommandBuffersFunc) (VkDevice device, const VkCommandBufferAllocateInfo* pAllocateInfo, VkCommandBuffer* pCommandBuffers);
+typedef VKAPI_ATTR void (VKAPI_CALL* FreeCommandBuffersFunc) (VkDevice device, VkCommandPool commandPool, deUint32 commandBufferCount, const VkCommandBuffer* pCommandBuffers);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* BeginCommandBufferFunc) (VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo* pBeginInfo);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* EndCommandBufferFunc) (VkCommandBuffer commandBuffer);
+typedef VKAPI_ATTR VkResult (VKAPI_CALL* ResetCommandBufferFunc) (VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdBindPipelineFunc) (VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdSetViewportFunc) (VkCommandBuffer commandBuffer, deUint32 viewportCount, const VkViewport* pViewports);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdSetScissorFunc) (VkCommandBuffer commandBuffer, deUint32 scissorCount, const VkRect2D* pScissors);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdSetLineWidthFunc) (VkCommandBuffer commandBuffer, float lineWidth);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdSetDepthBiasFunc) (VkCommandBuffer commandBuffer, float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdSetBlendConstantsFunc) (VkCommandBuffer commandBuffer, const float blendConstants[4]);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdSetDepthBoundsFunc) (VkCommandBuffer commandBuffer, float minDepthBounds, float maxDepthBounds);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdSetStencilCompareMaskFunc) (VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, deUint32 compareMask);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdSetStencilWriteMaskFunc) (VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, deUint32 writeMask);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdSetStencilReferenceFunc) (VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, deUint32 reference);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdBindDescriptorSetsFunc) (VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, deUint32 firstSet, deUint32 descriptorSetCount, const VkDescriptorSet* pDescriptorSets, deUint32 dynamicOffsetCount, const deUint32* pDynamicOffsets);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdBindIndexBufferFunc) (VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdBindVertexBuffersFunc) (VkCommandBuffer commandBuffer, deUint32 startBinding, deUint32 bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdDrawFunc) (VkCommandBuffer commandBuffer, deUint32 vertexCount, deUint32 instanceCount, deUint32 firstVertex, deUint32 firstInstance);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdDrawIndexedFunc) (VkCommandBuffer commandBuffer, deUint32 indexCount, deUint32 instanceCount, deUint32 firstIndex, deInt32 vertexOffset, deUint32 firstInstance);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdDrawIndirectFunc) (VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, deUint32 drawCount, deUint32 stride);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdDrawIndexedIndirectFunc) (VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, deUint32 drawCount, deUint32 stride);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdDispatchFunc) (VkCommandBuffer commandBuffer, deUint32 x, deUint32 y, deUint32 z);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdDispatchIndirectFunc) (VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdCopyBufferFunc) (VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, deUint32 regionCount, const VkBufferCopy* pRegions);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdCopyImageFunc) (VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, deUint32 regionCount, const VkImageCopy* pRegions);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdBlitImageFunc) (VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, deUint32 regionCount, const VkImageBlit* pRegions, VkFilter filter);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdCopyBufferToImageFunc) (VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage, VkImageLayout dstImageLayout, deUint32 regionCount, const VkBufferImageCopy* pRegions);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdCopyImageToBufferFunc) (VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkBuffer dstBuffer, deUint32 regionCount, const VkBufferImageCopy* pRegions);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdUpdateBufferFunc) (VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const deUint32* pData);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdFillBufferFunc) (VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, deUint32 data);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdClearColorImageFunc) (VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearColorValue* pColor, deUint32 rangeCount, const VkImageSubresourceRange* pRanges);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdClearDepthStencilImageFunc) (VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearDepthStencilValue* pDepthStencil, deUint32 rangeCount, const VkImageSubresourceRange* pRanges);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdClearAttachmentsFunc) (VkCommandBuffer commandBuffer, deUint32 attachmentCount, const VkClearAttachment* pAttachments, deUint32 rectCount, const VkClearRect* pRects);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdResolveImageFunc) (VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, deUint32 regionCount, const VkImageResolve* pRegions);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdSetEventFunc) (VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdResetEventFunc) (VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdWaitEventsFunc) (VkCommandBuffer commandBuffer, deUint32 eventCount, const VkEvent* pEvents, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, deUint32 memoryBarrierCount, const void* const* ppMemoryBarriers);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdPipelineBarrierFunc) (VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, deUint32 memoryBarrierCount, const void* const* ppMemoryBarriers);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdBeginQueryFunc) (VkCommandBuffer commandBuffer, VkQueryPool queryPool, deUint32 entry, VkQueryControlFlags flags);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdEndQueryFunc) (VkCommandBuffer commandBuffer, VkQueryPool queryPool, deUint32 entry);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdResetQueryPoolFunc) (VkCommandBuffer commandBuffer, VkQueryPool queryPool, deUint32 startQuery, deUint32 queryCount);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdWriteTimestampFunc) (VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkQueryPool queryPool, deUint32 entry);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdCopyQueryPoolResultsFunc) (VkCommandBuffer commandBuffer, VkQueryPool queryPool, deUint32 startQuery, deUint32 queryCount, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdPushConstantsFunc) (VkCommandBuffer commandBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, deUint32 offset, deUint32 size, const void* pValues);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdBeginRenderPassFunc) (VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, VkSubpassContents contents);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdNextSubpassFunc) (VkCommandBuffer commandBuffer, VkSubpassContents contents);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdEndRenderPassFunc) (VkCommandBuffer commandBuffer);
+typedef VKAPI_ATTR void (VKAPI_CALL* CmdExecuteCommandsFunc) (VkCommandBuffer commandBuffer, deUint32 commandBuffersCount, const VkCommandBuffer* pCommandBuffers);
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief GLSL to SPIR-V.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkGlslToSpirV.hpp"
+#include "deArrayUtil.hpp"
+#include "deMemory.h"
+#include "deClock.h"
+#include "qpDebugOut.h"
+
+#if defined(DEQP_HAVE_GLSLANG)
+# include "deSingleton.h"
+# include "deMutex.hpp"
+
+# include "SPIRV/GlslangToSpv.h"
+# include "SPIRV/disassemble.h"
+# include "SPIRV/doc.h"
+# include "glslang/Include/InfoSink.h"
+# include "glslang/Include/ShHandle.h"
+# include "glslang/MachineIndependent/localintermediate.h"
+# include "glslang/Public/ShaderLang.h"
+
+#endif
+
+namespace vk
+{
+
+using std::string;
+using std::vector;
+
+#if defined(DEQP_HAVE_GLSLANG)
+
+namespace
+{
+
+EShLanguage getGlslangStage (glu::ShaderType type)
+{
+ static const EShLanguage stageMap[] =
+ {
+ EShLangVertex,
+ EShLangFragment,
+ EShLangGeometry,
+ EShLangTessControl,
+ EShLangTessEvaluation,
+ EShLangCompute,
+ };
+ return de::getSizedArrayElement<glu::SHADERTYPE_LAST>(stageMap, type);
+}
+
+static volatile deSingletonState s_glslangInitState = DE_SINGLETON_STATE_NOT_INITIALIZED;
+static de::Mutex s_glslangLock;
+
+void initGlslang (void*)
+{
+ // Main compiler
+ glslang::InitializeProcess();
+
+ // SPIR-V disassembly
+ spv::Parameterize();
+}
+
+void prepareGlslang (void)
+{
+ deInitSingleton(&s_glslangInitState, initGlslang, DE_NULL);
+}
+
+// \todo [2015-06-19 pyry] Specialize these per GLSL version
+
+// Fail compilation if more members are added to TLimits or TBuiltInResource
+struct LimitsSizeHelper_s { bool m0, m1, m2, m3, m4, m5, m6, m7, m8; };
+struct BuiltInResourceSizeHelper_s { int m[83]; LimitsSizeHelper_s l; };
+
+DE_STATIC_ASSERT(sizeof(TLimits) == sizeof(LimitsSizeHelper_s));
+DE_STATIC_ASSERT(sizeof(TBuiltInResource) == sizeof(BuiltInResourceSizeHelper_s));
+
+void getDefaultLimits (TLimits* limits)
+{
+ limits->nonInductiveForLoops = true;
+ limits->whileLoops = true;
+ limits->doWhileLoops = true;
+ limits->generalUniformIndexing = true;
+ limits->generalAttributeMatrixVectorIndexing = true;
+ limits->generalVaryingIndexing = true;
+ limits->generalSamplerIndexing = true;
+ limits->generalVariableIndexing = true;
+ limits->generalConstantMatrixVectorIndexing = true;
+}
+
+void getDefaultBuiltInResources (TBuiltInResource* builtin)
+{
+ getDefaultLimits(&builtin->limits);
+
+ builtin->maxLights = 32;
+ builtin->maxClipPlanes = 6;
+ builtin->maxTextureUnits = 32;
+ builtin->maxTextureCoords = 32;
+ builtin->maxVertexAttribs = 64;
+ builtin->maxVertexUniformComponents = 4096;
+ builtin->maxVaryingFloats = 64;
+ builtin->maxVertexTextureImageUnits = 32;
+ builtin->maxCombinedTextureImageUnits = 80;
+ builtin->maxTextureImageUnits = 32;
+ builtin->maxFragmentUniformComponents = 4096;
+ builtin->maxDrawBuffers = 32;
+ builtin->maxVertexUniformVectors = 128;
+ builtin->maxVaryingVectors = 8;
+ builtin->maxFragmentUniformVectors = 16;
+ builtin->maxVertexOutputVectors = 16;
+ builtin->maxFragmentInputVectors = 15;
+ builtin->minProgramTexelOffset = -8;
+ builtin->maxProgramTexelOffset = 7;
+ builtin->maxClipDistances = 8;
+ builtin->maxComputeWorkGroupCountX = 65535;
+ builtin->maxComputeWorkGroupCountY = 65535;
+ builtin->maxComputeWorkGroupCountZ = 65535;
+ builtin->maxComputeWorkGroupSizeX = 1024;
+ builtin->maxComputeWorkGroupSizeY = 1024;
+ builtin->maxComputeWorkGroupSizeZ = 64;
+ builtin->maxComputeUniformComponents = 1024;
+ builtin->maxComputeTextureImageUnits = 16;
+ builtin->maxComputeImageUniforms = 8;
+ builtin->maxComputeAtomicCounters = 8;
+ builtin->maxComputeAtomicCounterBuffers = 1;
+ builtin->maxVaryingComponents = 60;
+ builtin->maxVertexOutputComponents = 64;
+ builtin->maxGeometryInputComponents = 64;
+ builtin->maxGeometryOutputComponents = 128;
+ builtin->maxFragmentInputComponents = 128;
+ builtin->maxImageUnits = 8;
+ builtin->maxCombinedImageUnitsAndFragmentOutputs = 8;
+ builtin->maxCombinedShaderOutputResources = 8;
+ builtin->maxImageSamples = 0;
+ builtin->maxVertexImageUniforms = 0;
+ builtin->maxTessControlImageUniforms = 0;
+ builtin->maxTessEvaluationImageUniforms = 0;
+ builtin->maxGeometryImageUniforms = 0;
+ builtin->maxFragmentImageUniforms = 8;
+ builtin->maxCombinedImageUniforms = 8;
+ builtin->maxGeometryTextureImageUnits = 16;
+ builtin->maxGeometryOutputVertices = 256;
+ builtin->maxGeometryTotalOutputComponents = 1024;
+ builtin->maxGeometryUniformComponents = 1024;
+ builtin->maxGeometryVaryingComponents = 64;
+ builtin->maxTessControlInputComponents = 128;
+ builtin->maxTessControlOutputComponents = 128;
+ builtin->maxTessControlTextureImageUnits = 16;
+ builtin->maxTessControlUniformComponents = 1024;
+ builtin->maxTessControlTotalOutputComponents = 4096;
+ builtin->maxTessEvaluationInputComponents = 128;
+ builtin->maxTessEvaluationOutputComponents = 128;
+ builtin->maxTessEvaluationTextureImageUnits = 16;
+ builtin->maxTessEvaluationUniformComponents = 1024;
+ builtin->maxTessPatchComponents = 120;
+ builtin->maxPatchVertices = 32;
+ builtin->maxTessGenLevel = 64;
+ builtin->maxViewports = 16;
+ builtin->maxVertexAtomicCounters = 0;
+ builtin->maxTessControlAtomicCounters = 0;
+ builtin->maxTessEvaluationAtomicCounters = 0;
+ builtin->maxGeometryAtomicCounters = 0;
+ builtin->maxFragmentAtomicCounters = 8;
+ builtin->maxCombinedAtomicCounters = 8;
+ builtin->maxAtomicCounterBindings = 1;
+ builtin->maxVertexAtomicCounterBuffers = 0;
+ builtin->maxTessControlAtomicCounterBuffers = 0;
+ builtin->maxTessEvaluationAtomicCounterBuffers = 0;
+ builtin->maxGeometryAtomicCounterBuffers = 0;
+ builtin->maxFragmentAtomicCounterBuffers = 1;
+ builtin->maxCombinedAtomicCounterBuffers = 1;
+ builtin->maxAtomicCounterBufferSize = 16384;
+ builtin->maxTransformFeedbackBuffers = 4;
+ builtin->maxTransformFeedbackInterleavedComponents = 64;
+ builtin->maxCullDistances = 8;
+ builtin->maxCombinedClipAndCullDistances = 8;
+ builtin->maxSamples = 4;
+};
+
+} // anonymous
+
+void glslToSpirV (const glu::ProgramSources& program, std::vector<deUint8>* dst, glu::ShaderProgramInfo* buildInfo)
+{
+ TBuiltInResource builtinRes;
+
+ prepareGlslang();
+ getDefaultBuiltInResources(&builtinRes);
+
+ // \note Compiles only first found shader
+ for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++)
+ {
+ if (!program.sources[shaderType].empty())
+ {
+ const de::ScopedLock compileLock (s_glslangLock);
+ const std::string& srcText = program.sources[shaderType][0];
+ const char* srcPtrs[] = { srcText.c_str() };
+ const int srcLengths[] = { (int)srcText.size() };
+ vector<deUint32> spvBlob;
+ const EShLanguage shaderStage = getGlslangStage(glu::ShaderType(shaderType));
+ glslang::TShader shader (shaderStage);
+ glslang::TProgram program;
+
+ shader.setStrings(srcPtrs, DE_LENGTH_OF_ARRAY(srcPtrs));
+ program.addShader(&shader);
+
+ {
+ const deUint64 compileStartTime = deGetMicroseconds();
+ const int compileRes = shader.parse(&builtinRes, 110, false, EShMsgSpvRules);
+ glu::ShaderInfo shaderBuildInfo;
+
+ shaderBuildInfo.type = (glu::ShaderType)shaderType;
+ shaderBuildInfo.source = srcText;
+ shaderBuildInfo.infoLog = shader.getInfoLog(); // \todo [2015-07-13 pyry] Include debug log?
+ shaderBuildInfo.compileTimeUs = deGetMicroseconds()-compileStartTime;
+ shaderBuildInfo.compileOk = (compileRes != 0);
+
+ buildInfo->shaders.push_back(shaderBuildInfo);
+
+ if (compileRes == 0)
+ TCU_FAIL("Failed to compile shader");
+ }
+
+ {
+ const deUint64 linkStartTime = deGetMicroseconds();
+ const int linkRes = program.link(EShMsgDefault);
+
+ buildInfo->program.infoLog = program.getInfoLog(); // \todo [2015-11-05 scygan] Include debug log?
+ buildInfo->program.linkOk = (linkRes != 0);
+ buildInfo->program.linkTimeUs = deGetMicroseconds()-linkStartTime;
+
+ if (linkRes == 0)
+ TCU_FAIL("Failed to link shader");
+ }
+
+ {
+ const glslang::TIntermediate* const intermediate = program.getIntermediate(shaderStage);
+ glslang::GlslangToSpv(*intermediate, spvBlob);
+ }
+
+ dst->resize(spvBlob.size() * sizeof(deUint32));
+#if (DE_ENDIANNESS == DE_LITTLE_ENDIAN)
+ deMemcpy(&(*dst)[0], &spvBlob[0], dst->size());
+#else
+# error "Big-endian not supported"
+#endif
+
+ return;
+ }
+ }
+
+ TCU_THROW(InternalError, "Can't compile empty program");
+}
+
+void disassembleSpirV (size_t binarySize, const deUint8* binary, std::ostream* dst)
+{
+ std::vector<deUint32> binForDisasm (binarySize/4);
+
+ DE_ASSERT(binarySize%4 == 0);
+
+#if (DE_ENDIANNESS == DE_LITTLE_ENDIAN)
+ deMemcpy(&binForDisasm[0], binary, binarySize);
+#else
+# error "Big-endian not supported"
+#endif
+
+ spv::Disassemble(*dst, binForDisasm);
+}
+
+#else // defined(DEQP_HAVE_GLSLANG)
+
+void glslToSpirV (const glu::ProgramSources&, std::vector<deUint8>*, glu::ShaderProgramInfo*)
+{
+ TCU_THROW(NotSupportedError, "GLSL to SPIR-V compilation not supported (DEQP_HAVE_GLSLANG not defined)");
+}
+
+void disassembleSpirV (size_t, const deUint8*, std::ostream*)
+{
+ TCU_THROW(NotSupportedError, "SPIR-V disassembling not supported (DEQP_HAVE_GLSLANG not defined)");
+}
+
+#endif
+
+} // vk
--- /dev/null
+#ifndef _VKGLSLTOSPIRV_HPP
+#define _VKGLSLTOSPIRV_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief GLSL to SPIR-V.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkDefs.hpp"
+#include "vkPrograms.hpp"
+#include "gluShaderProgram.hpp"
+
+#include <ostream>
+
+namespace vk
+{
+
+//! Compile GLSL program to SPIR-V. Will fail with NotSupportedError if compiler is not available.
+void glslToSpirV (const glu::ProgramSources& src, std::vector<deUint8>* dst, glu::ShaderProgramInfo* buildInfo);
+
+//! Disassemble SPIR-V binary
+void disassembleSpirV (size_t binarySize, const deUint8* binary, std::ostream* dst);
+
+} // vk
+
+#endif // _VKGLSLTOSPIRV_HPP
--- /dev/null
+/* WARNING: This is auto-generated file. Do not modify, since changes will
+ * be lost! Modify the generating script instead.
+ */
+enum HandleType
+{
+ HANDLE_TYPE_INSTANCE = 0,
+ HANDLE_TYPE_PHYSICAL_DEVICE,
+ HANDLE_TYPE_DEVICE,
+ HANDLE_TYPE_QUEUE,
+ HANDLE_TYPE_SEMAPHORE,
+ HANDLE_TYPE_COMMAND_BUFFER,
+ HANDLE_TYPE_FENCE,
+ HANDLE_TYPE_DEVICE_MEMORY,
+ HANDLE_TYPE_BUFFER,
+ HANDLE_TYPE_IMAGE,
+ HANDLE_TYPE_EVENT,
+ HANDLE_TYPE_QUERY_POOL,
+ HANDLE_TYPE_BUFFER_VIEW,
+ HANDLE_TYPE_IMAGE_VIEW,
+ HANDLE_TYPE_SHADER_MODULE,
+ HANDLE_TYPE_PIPELINE_CACHE,
+ HANDLE_TYPE_PIPELINE_LAYOUT,
+ HANDLE_TYPE_RENDER_PASS,
+ HANDLE_TYPE_PIPELINE,
+ HANDLE_TYPE_DESCRIPTOR_SET_LAYOUT,
+ HANDLE_TYPE_SAMPLER,
+ HANDLE_TYPE_DESCRIPTOR_POOL,
+ HANDLE_TYPE_DESCRIPTOR_SET,
+ HANDLE_TYPE_FRAMEBUFFER,
+ HANDLE_TYPE_COMMAND_POOL,
+ HANDLE_TYPE_SURFACE_KHR,
+ HANDLE_TYPE_SWAPCHAIN_KHR,
+ HANDLE_TYPE_DISPLAY_KHR,
+ HANDLE_TYPE_DISPLAY_MODE_KHR,
+ HANDLE_TYPE_LAST
+};
+
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Imagination Technologies Ltd.
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Utilities for images.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkImageUtil.hpp"
+#include "tcuTextureUtil.hpp"
+
+namespace vk
+{
+
+bool isFloatFormat (VkFormat format)
+{
+ return tcu::getTextureChannelClass(mapVkFormat(format).type) == tcu::TEXTURECHANNELCLASS_FLOATING_POINT;
+}
+
+bool isUnormFormat (VkFormat format)
+{
+ return tcu::getTextureChannelClass(mapVkFormat(format).type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
+}
+
+bool isSnormFormat (VkFormat format)
+{
+ return tcu::getTextureChannelClass(mapVkFormat(format).type) == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT;
+}
+
+bool isIntFormat (VkFormat format)
+{
+ return tcu::getTextureChannelClass(mapVkFormat(format).type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER;
+}
+
+bool isUintFormat (VkFormat format)
+{
+ return tcu::getTextureChannelClass(mapVkFormat(format).type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER;
+}
+
+bool isDepthStencilFormat (VkFormat format)
+{
+ if (isCompressedFormat(format))
+ return false;
+
+ const tcu::TextureFormat tcuFormat = mapVkFormat(format);
+ return tcuFormat.order == tcu::TextureFormat::D || tcuFormat.order == tcu::TextureFormat::S || tcuFormat.order == tcu::TextureFormat::DS;
+}
+
+bool isCompressedFormat (VkFormat format)
+{
+ // update this mapping if VkFormat changes
+ DE_STATIC_ASSERT(VK_FORMAT_LAST == 185);
+
+ switch (format)
+ {
+ case VK_FORMAT_BC1_RGB_UNORM_BLOCK:
+ case VK_FORMAT_BC1_RGB_SRGB_BLOCK:
+ case VK_FORMAT_BC1_RGBA_UNORM_BLOCK:
+ case VK_FORMAT_BC1_RGBA_SRGB_BLOCK:
+ case VK_FORMAT_BC2_UNORM_BLOCK:
+ case VK_FORMAT_BC2_SRGB_BLOCK:
+ case VK_FORMAT_BC3_UNORM_BLOCK:
+ case VK_FORMAT_BC3_SRGB_BLOCK:
+ case VK_FORMAT_BC4_UNORM_BLOCK:
+ case VK_FORMAT_BC4_SNORM_BLOCK:
+ case VK_FORMAT_BC5_UNORM_BLOCK:
+ case VK_FORMAT_BC5_SNORM_BLOCK:
+ case VK_FORMAT_BC6H_UFLOAT_BLOCK:
+ case VK_FORMAT_BC6H_SFLOAT_BLOCK:
+ case VK_FORMAT_BC7_UNORM_BLOCK:
+ case VK_FORMAT_BC7_SRGB_BLOCK:
+ case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK:
+ case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK:
+ case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK:
+ case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK:
+ case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK:
+ case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK:
+ case VK_FORMAT_EAC_R11_UNORM_BLOCK:
+ case VK_FORMAT_EAC_R11_SNORM_BLOCK:
+ case VK_FORMAT_EAC_R11G11_UNORM_BLOCK:
+ case VK_FORMAT_EAC_R11G11_SNORM_BLOCK:
+ case VK_FORMAT_ASTC_4x4_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_4x4_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_5x4_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_5x4_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_5x5_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_5x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_6x5_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_6x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_6x6_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_6x6_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_8x5_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_8x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_8x6_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_8x6_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_8x8_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_8x8_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x5_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_10x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x6_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_10x6_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x8_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_10x8_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x10_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_10x10_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_12x10_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_12x10_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_12x12_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_12x12_SRGB_BLOCK:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+VkFormat mapTextureFormat (const tcu::TextureFormat& format)
+{
+ DE_STATIC_ASSERT(tcu::TextureFormat::CHANNELORDER_LAST < (1<<16));
+ DE_STATIC_ASSERT(tcu::TextureFormat::CHANNELTYPE_LAST < (1<<16));
+
+#define PACK_FMT(ORDER, TYPE) ((int(ORDER) << 16) | int(TYPE))
+#define FMT_CASE(ORDER, TYPE) PACK_FMT(tcu::TextureFormat::ORDER, tcu::TextureFormat::TYPE)
+
+ // update this mapping if VkFormat changes
+ DE_STATIC_ASSERT(VK_FORMAT_LAST == 185);
+
+ switch (PACK_FMT(format.order, format.type))
+ {
+ case FMT_CASE(RG, UNORM_BYTE_44): return VK_FORMAT_R4G4_UNORM_PACK8;
+ case FMT_CASE(RGB, UNORM_SHORT_565): return VK_FORMAT_R5G6B5_UNORM_PACK16;
+ case FMT_CASE(RGBA, UNORM_SHORT_4444): return VK_FORMAT_R4G4B4A4_UNORM_PACK16;
+ case FMT_CASE(RGBA, UNORM_SHORT_5551): return VK_FORMAT_R5G5B5A1_UNORM_PACK16;
+
+ case FMT_CASE(BGR, UNORM_SHORT_565): return VK_FORMAT_B5G6R5_UNORM_PACK16;
+ case FMT_CASE(BGRA, UNORM_SHORT_4444): return VK_FORMAT_B4G4R4A4_UNORM_PACK16;
+ case FMT_CASE(BGRA, UNORM_SHORT_5551): return VK_FORMAT_B5G5R5A1_UNORM_PACK16;
+
+ case FMT_CASE(ARGB, UNORM_SHORT_1555): return VK_FORMAT_A1R5G5B5_UNORM_PACK16;
+
+ case FMT_CASE(R, UNORM_INT8): return VK_FORMAT_R8_UNORM;
+ case FMT_CASE(R, SNORM_INT8): return VK_FORMAT_R8_SNORM;
+ case FMT_CASE(R, UNSIGNED_INT8): return VK_FORMAT_R8_UINT;
+ case FMT_CASE(R, SIGNED_INT8): return VK_FORMAT_R8_SINT;
+ case FMT_CASE(sR, UNORM_INT8): return VK_FORMAT_R8_SRGB;
+
+ case FMT_CASE(RG, UNORM_INT8): return VK_FORMAT_R8G8_UNORM;
+ case FMT_CASE(RG, SNORM_INT8): return VK_FORMAT_R8G8_SNORM;
+ case FMT_CASE(RG, UNSIGNED_INT8): return VK_FORMAT_R8G8_UINT;
+ case FMT_CASE(RG, SIGNED_INT8): return VK_FORMAT_R8G8_SINT;
+ case FMT_CASE(sRG, UNORM_INT8): return VK_FORMAT_R8G8_SRGB;
+
+ case FMT_CASE(RGB, UNORM_INT8): return VK_FORMAT_R8G8B8_UNORM;
+ case FMT_CASE(RGB, SNORM_INT8): return VK_FORMAT_R8G8B8_SNORM;
+ case FMT_CASE(RGB, UNSIGNED_INT8): return VK_FORMAT_R8G8B8_UINT;
+ case FMT_CASE(RGB, SIGNED_INT8): return VK_FORMAT_R8G8B8_SINT;
+ case FMT_CASE(sRGB, UNORM_INT8): return VK_FORMAT_R8G8B8_SRGB;
+
+ case FMT_CASE(RGBA, UNORM_INT8): return VK_FORMAT_R8G8B8A8_UNORM;
+ case FMT_CASE(RGBA, SNORM_INT8): return VK_FORMAT_R8G8B8A8_SNORM;
+ case FMT_CASE(RGBA, UNSIGNED_INT8): return VK_FORMAT_R8G8B8A8_UINT;
+ case FMT_CASE(RGBA, SIGNED_INT8): return VK_FORMAT_R8G8B8A8_SINT;
+ case FMT_CASE(sRGBA, UNORM_INT8): return VK_FORMAT_R8G8B8A8_SRGB;
+
+ case FMT_CASE(RGBA, UNORM_INT_1010102_REV): return VK_FORMAT_A2B10G10R10_UNORM_PACK32;
+ case FMT_CASE(RGBA, SNORM_INT_1010102_REV): return VK_FORMAT_A2B10G10R10_SNORM_PACK32;
+ case FMT_CASE(RGBA, UNSIGNED_INT_1010102_REV): return VK_FORMAT_A2B10G10R10_UINT_PACK32;
+ case FMT_CASE(RGBA, SIGNED_INT_1010102_REV): return VK_FORMAT_A2B10G10R10_SINT_PACK32;
+
+ case FMT_CASE(R, UNORM_INT16): return VK_FORMAT_R16_UNORM;
+ case FMT_CASE(R, SNORM_INT16): return VK_FORMAT_R16_SNORM;
+ case FMT_CASE(R, UNSIGNED_INT16): return VK_FORMAT_R16_UINT;
+ case FMT_CASE(R, SIGNED_INT16): return VK_FORMAT_R16_SINT;
+ case FMT_CASE(R, HALF_FLOAT): return VK_FORMAT_R16_SFLOAT;
+
+ case FMT_CASE(RG, UNORM_INT16): return VK_FORMAT_R16G16_UNORM;
+ case FMT_CASE(RG, SNORM_INT16): return VK_FORMAT_R16G16_SNORM;
+ case FMT_CASE(RG, UNSIGNED_INT16): return VK_FORMAT_R16G16_UINT;
+ case FMT_CASE(RG, SIGNED_INT16): return VK_FORMAT_R16G16_SINT;
+ case FMT_CASE(RG, HALF_FLOAT): return VK_FORMAT_R16G16_SFLOAT;
+
+ case FMT_CASE(RGB, UNORM_INT16): return VK_FORMAT_R16G16B16_UNORM;
+ case FMT_CASE(RGB, SNORM_INT16): return VK_FORMAT_R16G16B16_SNORM;
+ case FMT_CASE(RGB, UNSIGNED_INT16): return VK_FORMAT_R16G16B16_UINT;
+ case FMT_CASE(RGB, SIGNED_INT16): return VK_FORMAT_R16G16B16_SINT;
+ case FMT_CASE(RGB, HALF_FLOAT): return VK_FORMAT_R16G16B16_SFLOAT;
+
+ case FMT_CASE(RGBA, UNORM_INT16): return VK_FORMAT_R16G16B16A16_UNORM;
+ case FMT_CASE(RGBA, SNORM_INT16): return VK_FORMAT_R16G16B16A16_SNORM;
+ case FMT_CASE(RGBA, UNSIGNED_INT16): return VK_FORMAT_R16G16B16A16_UINT;
+ case FMT_CASE(RGBA, SIGNED_INT16): return VK_FORMAT_R16G16B16A16_SINT;
+ case FMT_CASE(RGBA, HALF_FLOAT): return VK_FORMAT_R16G16B16A16_SFLOAT;
+
+ case FMT_CASE(R, UNSIGNED_INT32): return VK_FORMAT_R32_UINT;
+ case FMT_CASE(R, SIGNED_INT32): return VK_FORMAT_R32_SINT;
+ case FMT_CASE(R, FLOAT): return VK_FORMAT_R32_SFLOAT;
+
+ case FMT_CASE(RG, UNSIGNED_INT32): return VK_FORMAT_R32G32_UINT;
+ case FMT_CASE(RG, SIGNED_INT32): return VK_FORMAT_R32G32_SINT;
+ case FMT_CASE(RG, FLOAT): return VK_FORMAT_R32G32_SFLOAT;
+
+ case FMT_CASE(RGB, UNSIGNED_INT32): return VK_FORMAT_R32G32B32_UINT;
+ case FMT_CASE(RGB, SIGNED_INT32): return VK_FORMAT_R32G32B32_SINT;
+ case FMT_CASE(RGB, FLOAT): return VK_FORMAT_R32G32B32_SFLOAT;
+
+ case FMT_CASE(RGBA, UNSIGNED_INT32): return VK_FORMAT_R32G32B32A32_UINT;
+ case FMT_CASE(RGBA, SIGNED_INT32): return VK_FORMAT_R32G32B32A32_SINT;
+ case FMT_CASE(RGBA, FLOAT): return VK_FORMAT_R32G32B32A32_SFLOAT;
+
+ case FMT_CASE(R, FLOAT64): return VK_FORMAT_R64_SFLOAT;
+ case FMT_CASE(RG, FLOAT64): return VK_FORMAT_R64G64_SFLOAT;
+ case FMT_CASE(RGB, FLOAT64): return VK_FORMAT_R64G64B64_SFLOAT;
+ case FMT_CASE(RGBA, FLOAT64): return VK_FORMAT_R64G64B64A64_SFLOAT;
+
+ case FMT_CASE(RGB, UNSIGNED_INT_11F_11F_10F_REV): return VK_FORMAT_B10G11R11_UFLOAT_PACK32;
+ case FMT_CASE(RGB, UNSIGNED_INT_999_E5_REV): return VK_FORMAT_E5B9G9R9_UFLOAT_PACK32;
+
+ case FMT_CASE(BGR, UNORM_INT8): return VK_FORMAT_B8G8R8_UNORM;
+ case FMT_CASE(BGR, SNORM_INT8): return VK_FORMAT_B8G8R8_SNORM;
+ case FMT_CASE(BGR, UNSIGNED_INT8): return VK_FORMAT_B8G8R8_UINT;
+ case FMT_CASE(BGR, SIGNED_INT8): return VK_FORMAT_B8G8R8_SINT;
+ case FMT_CASE(sBGR, UNORM_INT8): return VK_FORMAT_B8G8R8_SRGB;
+
+ case FMT_CASE(BGRA, UNORM_INT8): return VK_FORMAT_B8G8R8A8_UNORM;
+ case FMT_CASE(BGRA, SNORM_INT8): return VK_FORMAT_B8G8R8A8_SNORM;
+ case FMT_CASE(BGRA, UNSIGNED_INT8): return VK_FORMAT_B8G8R8A8_UINT;
+ case FMT_CASE(BGRA, SIGNED_INT8): return VK_FORMAT_B8G8R8A8_SINT;
+ case FMT_CASE(sBGRA, UNORM_INT8): return VK_FORMAT_B8G8R8A8_SRGB;
+
+ case FMT_CASE(BGRA, UNORM_INT_1010102_REV): return VK_FORMAT_A2R10G10B10_UNORM_PACK32;
+ case FMT_CASE(BGRA, SNORM_INT_1010102_REV): return VK_FORMAT_A2R10G10B10_SNORM_PACK32;
+ case FMT_CASE(BGRA, UNSIGNED_INT_1010102_REV): return VK_FORMAT_A2R10G10B10_UINT_PACK32;
+ case FMT_CASE(BGRA, SIGNED_INT_1010102_REV): return VK_FORMAT_A2R10G10B10_SINT_PACK32;
+
+ case FMT_CASE(D, UNORM_INT16): return VK_FORMAT_D16_UNORM;
+ case FMT_CASE(D, UNSIGNED_INT_24_8_REV): return VK_FORMAT_X8_D24_UNORM_PACK32;
+ case FMT_CASE(D, FLOAT): return VK_FORMAT_D32_SFLOAT;
+
+ case FMT_CASE(S, UNSIGNED_INT8): return VK_FORMAT_S8_UINT;
+
+ case FMT_CASE(DS, UNSIGNED_INT_16_8_8): return VK_FORMAT_D16_UNORM_S8_UINT;
+ case FMT_CASE(DS, UNSIGNED_INT_24_8_REV): return VK_FORMAT_D24_UNORM_S8_UINT;
+ case FMT_CASE(DS, FLOAT_UNSIGNED_INT_24_8_REV): return VK_FORMAT_D32_SFLOAT_S8_UINT;
+
+ default:
+ TCU_THROW(InternalError, "Unknown texture format");
+ }
+
+#undef PACK_FMT
+#undef FMT_CASE
+}
+
+tcu::TextureFormat mapVkFormat (VkFormat format)
+{
+ using tcu::TextureFormat;
+
+ // update this mapping if VkFormat changes
+ DE_STATIC_ASSERT(VK_FORMAT_LAST == 185);
+
+ switch (format)
+ {
+ case VK_FORMAT_R4G4_UNORM_PACK8: return TextureFormat(TextureFormat::RG, TextureFormat::UNORM_BYTE_44);
+ case VK_FORMAT_R5G6B5_UNORM_PACK16: return TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_SHORT_565);
+ case VK_FORMAT_R4G4B4A4_UNORM_PACK16: return TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_SHORT_4444);
+ case VK_FORMAT_R5G5B5A1_UNORM_PACK16: return TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_SHORT_5551);
+
+ case VK_FORMAT_B5G6R5_UNORM_PACK16: return TextureFormat(TextureFormat::BGR, TextureFormat::UNORM_SHORT_565);
+ case VK_FORMAT_B4G4R4A4_UNORM_PACK16: return TextureFormat(TextureFormat::BGRA, TextureFormat::UNORM_SHORT_4444);
+ case VK_FORMAT_B5G5R5A1_UNORM_PACK16: return TextureFormat(TextureFormat::BGRA, TextureFormat::UNORM_SHORT_5551);
+
+ case VK_FORMAT_A1R5G5B5_UNORM_PACK16: return TextureFormat(TextureFormat::ARGB, TextureFormat::UNORM_SHORT_1555);
+
+ case VK_FORMAT_R8_UNORM: return TextureFormat(TextureFormat::R, TextureFormat::UNORM_INT8);
+ case VK_FORMAT_R8_SNORM: return TextureFormat(TextureFormat::R, TextureFormat::SNORM_INT8);
+ case VK_FORMAT_R8_USCALED: return TextureFormat(TextureFormat::R, TextureFormat::UNSIGNED_INT8);
+ case VK_FORMAT_R8_SSCALED: return TextureFormat(TextureFormat::R, TextureFormat::SIGNED_INT8);
+ case VK_FORMAT_R8_UINT: return TextureFormat(TextureFormat::R, TextureFormat::UNSIGNED_INT8);
+ case VK_FORMAT_R8_SINT: return TextureFormat(TextureFormat::R, TextureFormat::SIGNED_INT8);
+ case VK_FORMAT_R8_SRGB: return TextureFormat(TextureFormat::sR, TextureFormat::UNORM_INT8);
+
+ case VK_FORMAT_R8G8_UNORM: return TextureFormat(TextureFormat::RG, TextureFormat::UNORM_INT8);
+ case VK_FORMAT_R8G8_SNORM: return TextureFormat(TextureFormat::RG, TextureFormat::SNORM_INT8);
+ case VK_FORMAT_R8G8_USCALED: return TextureFormat(TextureFormat::RG, TextureFormat::UNSIGNED_INT8);
+ case VK_FORMAT_R8G8_SSCALED: return TextureFormat(TextureFormat::RG, TextureFormat::SIGNED_INT8);
+ case VK_FORMAT_R8G8_UINT: return TextureFormat(TextureFormat::RG, TextureFormat::UNSIGNED_INT8);
+ case VK_FORMAT_R8G8_SINT: return TextureFormat(TextureFormat::RG, TextureFormat::SIGNED_INT8);
+ case VK_FORMAT_R8G8_SRGB: return TextureFormat(TextureFormat::sRG, TextureFormat::UNORM_INT8);
+
+ case VK_FORMAT_R8G8B8_UNORM: return TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8);
+ case VK_FORMAT_R8G8B8_SNORM: return TextureFormat(TextureFormat::RGB, TextureFormat::SNORM_INT8);
+ case VK_FORMAT_R8G8B8_USCALED: return TextureFormat(TextureFormat::RGB, TextureFormat::UNSIGNED_INT8);
+ case VK_FORMAT_R8G8B8_SSCALED: return TextureFormat(TextureFormat::RGB, TextureFormat::SIGNED_INT8);
+ case VK_FORMAT_R8G8B8_UINT: return TextureFormat(TextureFormat::RGB, TextureFormat::UNSIGNED_INT8);
+ case VK_FORMAT_R8G8B8_SINT: return TextureFormat(TextureFormat::RGB, TextureFormat::SIGNED_INT8);
+ case VK_FORMAT_R8G8B8_SRGB: return TextureFormat(TextureFormat::sRGB, TextureFormat::UNORM_INT8);
+
+ case VK_FORMAT_R8G8B8A8_UNORM: return TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8);
+ case VK_FORMAT_R8G8B8A8_SNORM: return TextureFormat(TextureFormat::RGBA, TextureFormat::SNORM_INT8);
+ case VK_FORMAT_R8G8B8A8_USCALED: return TextureFormat(TextureFormat::RGBA, TextureFormat::UNSIGNED_INT8);
+ case VK_FORMAT_R8G8B8A8_SSCALED: return TextureFormat(TextureFormat::RGBA, TextureFormat::SIGNED_INT8);
+ case VK_FORMAT_R8G8B8A8_UINT: return TextureFormat(TextureFormat::RGBA, TextureFormat::UNSIGNED_INT8);
+ case VK_FORMAT_R8G8B8A8_SINT: return TextureFormat(TextureFormat::RGBA, TextureFormat::SIGNED_INT8);
+ case VK_FORMAT_R8G8B8A8_SRGB: return TextureFormat(TextureFormat::sRGBA, TextureFormat::UNORM_INT8);
+
+ case VK_FORMAT_R16_UNORM: return TextureFormat(TextureFormat::R, TextureFormat::UNORM_INT16);
+ case VK_FORMAT_R16_SNORM: return TextureFormat(TextureFormat::R, TextureFormat::SNORM_INT16);
+ case VK_FORMAT_R16_USCALED: return TextureFormat(TextureFormat::R, TextureFormat::UNSIGNED_INT16);
+ case VK_FORMAT_R16_SSCALED: return TextureFormat(TextureFormat::R, TextureFormat::SIGNED_INT16);
+ case VK_FORMAT_R16_UINT: return TextureFormat(TextureFormat::R, TextureFormat::UNSIGNED_INT16);
+ case VK_FORMAT_R16_SINT: return TextureFormat(TextureFormat::R, TextureFormat::SIGNED_INT16);
+ case VK_FORMAT_R16_SFLOAT: return TextureFormat(TextureFormat::R, TextureFormat::HALF_FLOAT);
+
+ case VK_FORMAT_R16G16_UNORM: return TextureFormat(TextureFormat::RG, TextureFormat::UNORM_INT16);
+ case VK_FORMAT_R16G16_SNORM: return TextureFormat(TextureFormat::RG, TextureFormat::SNORM_INT16);
+ case VK_FORMAT_R16G16_USCALED: return TextureFormat(TextureFormat::RG, TextureFormat::UNSIGNED_INT16);
+ case VK_FORMAT_R16G16_SSCALED: return TextureFormat(TextureFormat::RG, TextureFormat::SIGNED_INT16);
+ case VK_FORMAT_R16G16_UINT: return TextureFormat(TextureFormat::RG, TextureFormat::UNSIGNED_INT16);
+ case VK_FORMAT_R16G16_SINT: return TextureFormat(TextureFormat::RG, TextureFormat::SIGNED_INT16);
+ case VK_FORMAT_R16G16_SFLOAT: return TextureFormat(TextureFormat::RG, TextureFormat::HALF_FLOAT);
+
+ case VK_FORMAT_R16G16B16_UNORM: return TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT16);
+ case VK_FORMAT_R16G16B16_SNORM: return TextureFormat(TextureFormat::RGB, TextureFormat::SNORM_INT16);
+ case VK_FORMAT_R16G16B16_USCALED: return TextureFormat(TextureFormat::RGB, TextureFormat::UNSIGNED_INT16);
+ case VK_FORMAT_R16G16B16_SSCALED: return TextureFormat(TextureFormat::RGB, TextureFormat::SIGNED_INT16);
+ case VK_FORMAT_R16G16B16_UINT: return TextureFormat(TextureFormat::RGB, TextureFormat::UNSIGNED_INT16);
+ case VK_FORMAT_R16G16B16_SINT: return TextureFormat(TextureFormat::RGB, TextureFormat::SIGNED_INT16);
+ case VK_FORMAT_R16G16B16_SFLOAT: return TextureFormat(TextureFormat::RGB, TextureFormat::HALF_FLOAT);
+
+ case VK_FORMAT_R16G16B16A16_UNORM: return TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT16);
+ case VK_FORMAT_R16G16B16A16_SNORM: return TextureFormat(TextureFormat::RGBA, TextureFormat::SNORM_INT16);
+ case VK_FORMAT_R16G16B16A16_USCALED: return TextureFormat(TextureFormat::RGBA, TextureFormat::UNSIGNED_INT16);
+ case VK_FORMAT_R16G16B16A16_SSCALED: return TextureFormat(TextureFormat::RGBA, TextureFormat::SIGNED_INT16);
+ case VK_FORMAT_R16G16B16A16_UINT: return TextureFormat(TextureFormat::RGBA, TextureFormat::UNSIGNED_INT16);
+ case VK_FORMAT_R16G16B16A16_SINT: return TextureFormat(TextureFormat::RGBA, TextureFormat::SIGNED_INT16);
+ case VK_FORMAT_R16G16B16A16_SFLOAT: return TextureFormat(TextureFormat::RGBA, TextureFormat::HALF_FLOAT);
+
+ case VK_FORMAT_R32_UINT: return TextureFormat(TextureFormat::R, TextureFormat::UNSIGNED_INT32);
+ case VK_FORMAT_R32_SINT: return TextureFormat(TextureFormat::R, TextureFormat::SIGNED_INT32);
+ case VK_FORMAT_R32_SFLOAT: return TextureFormat(TextureFormat::R, TextureFormat::FLOAT);
+
+ case VK_FORMAT_R32G32_UINT: return TextureFormat(TextureFormat::RG, TextureFormat::UNSIGNED_INT32);
+ case VK_FORMAT_R32G32_SINT: return TextureFormat(TextureFormat::RG, TextureFormat::SIGNED_INT32);
+ case VK_FORMAT_R32G32_SFLOAT: return TextureFormat(TextureFormat::RG, TextureFormat::FLOAT);
+
+ case VK_FORMAT_R32G32B32_UINT: return TextureFormat(TextureFormat::RGB, TextureFormat::UNSIGNED_INT32);
+ case VK_FORMAT_R32G32B32_SINT: return TextureFormat(TextureFormat::RGB, TextureFormat::SIGNED_INT32);
+ case VK_FORMAT_R32G32B32_SFLOAT: return TextureFormat(TextureFormat::RGB, TextureFormat::FLOAT);
+
+ case VK_FORMAT_R32G32B32A32_UINT: return TextureFormat(TextureFormat::RGBA, TextureFormat::UNSIGNED_INT32);
+ case VK_FORMAT_R32G32B32A32_SINT: return TextureFormat(TextureFormat::RGBA, TextureFormat::SIGNED_INT32);
+ case VK_FORMAT_R32G32B32A32_SFLOAT: return TextureFormat(TextureFormat::RGBA, TextureFormat::FLOAT);
+
+ case VK_FORMAT_R64_SFLOAT: return TextureFormat(TextureFormat::R, TextureFormat::FLOAT64);
+ case VK_FORMAT_R64G64_SFLOAT: return TextureFormat(TextureFormat::RG, TextureFormat::FLOAT64);
+ case VK_FORMAT_R64G64B64_SFLOAT: return TextureFormat(TextureFormat::RGB, TextureFormat::FLOAT64);
+ case VK_FORMAT_R64G64B64A64_SFLOAT: return TextureFormat(TextureFormat::RGBA, TextureFormat::FLOAT64);
+
+ case VK_FORMAT_B10G11R11_UFLOAT_PACK32: return TextureFormat(TextureFormat::RGB, TextureFormat::UNSIGNED_INT_11F_11F_10F_REV);
+ case VK_FORMAT_E5B9G9R9_UFLOAT_PACK32: return TextureFormat(TextureFormat::RGB, TextureFormat::UNSIGNED_INT_999_E5_REV);
+
+ case VK_FORMAT_B8G8R8_UNORM: return TextureFormat(TextureFormat::BGR, TextureFormat::UNORM_INT8);
+ case VK_FORMAT_B8G8R8_SNORM: return TextureFormat(TextureFormat::BGR, TextureFormat::SNORM_INT8);
+ case VK_FORMAT_B8G8R8_USCALED: return TextureFormat(TextureFormat::BGR, TextureFormat::UNSIGNED_INT8);
+ case VK_FORMAT_B8G8R8_SSCALED: return TextureFormat(TextureFormat::BGR, TextureFormat::SIGNED_INT8);
+ case VK_FORMAT_B8G8R8_UINT: return TextureFormat(TextureFormat::BGR, TextureFormat::UNSIGNED_INT8);
+ case VK_FORMAT_B8G8R8_SINT: return TextureFormat(TextureFormat::BGR, TextureFormat::SIGNED_INT8);
+ case VK_FORMAT_B8G8R8_SRGB: return TextureFormat(TextureFormat::sBGR, TextureFormat::UNORM_INT8);
+
+ case VK_FORMAT_B8G8R8A8_UNORM: return TextureFormat(TextureFormat::BGRA, TextureFormat::UNORM_INT8);
+ case VK_FORMAT_B8G8R8A8_SNORM: return TextureFormat(TextureFormat::BGRA, TextureFormat::SNORM_INT8);
+ case VK_FORMAT_B8G8R8A8_USCALED: return TextureFormat(TextureFormat::BGRA, TextureFormat::UNSIGNED_INT8);
+ case VK_FORMAT_B8G8R8A8_SSCALED: return TextureFormat(TextureFormat::BGRA, TextureFormat::SIGNED_INT8);
+ case VK_FORMAT_B8G8R8A8_UINT: return TextureFormat(TextureFormat::BGRA, TextureFormat::UNSIGNED_INT8);
+ case VK_FORMAT_B8G8R8A8_SINT: return TextureFormat(TextureFormat::BGRA, TextureFormat::SIGNED_INT8);
+ case VK_FORMAT_B8G8R8A8_SRGB: return TextureFormat(TextureFormat::sBGRA, TextureFormat::UNORM_INT8);
+
+ case VK_FORMAT_D16_UNORM: return TextureFormat(TextureFormat::D, TextureFormat::UNORM_INT16);
+ case VK_FORMAT_X8_D24_UNORM_PACK32: return TextureFormat(TextureFormat::D, TextureFormat::UNSIGNED_INT_24_8_REV);
+ case VK_FORMAT_D32_SFLOAT: return TextureFormat(TextureFormat::D, TextureFormat::FLOAT);
+
+ case VK_FORMAT_S8_UINT: return TextureFormat(TextureFormat::S, TextureFormat::UNSIGNED_INT8);
+
+ // \note There is no standard interleaved memory layout for DS formats; buffer-image copies
+ // will always operate on either D or S aspect only. See Khronos bug 12998
+ case VK_FORMAT_D16_UNORM_S8_UINT: return TextureFormat(TextureFormat::DS, TextureFormat::UNSIGNED_INT_16_8_8);
+ case VK_FORMAT_D24_UNORM_S8_UINT: return TextureFormat(TextureFormat::DS, TextureFormat::UNSIGNED_INT_24_8_REV);
+ case VK_FORMAT_D32_SFLOAT_S8_UINT: return TextureFormat(TextureFormat::DS, TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV);
+
+#if (DE_ENDIANNESS == DE_LITTLE_ENDIAN)
+ case VK_FORMAT_A8B8G8R8_UNORM_PACK32: return TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8);
+ case VK_FORMAT_A8B8G8R8_SNORM_PACK32: return TextureFormat(TextureFormat::RGBA, TextureFormat::SNORM_INT8);
+ case VK_FORMAT_A8B8G8R8_USCALED_PACK32: return TextureFormat(TextureFormat::RGBA, TextureFormat::UNSIGNED_INT8);
+ case VK_FORMAT_A8B8G8R8_SSCALED_PACK32: return TextureFormat(TextureFormat::RGBA, TextureFormat::SIGNED_INT8);
+ case VK_FORMAT_A8B8G8R8_UINT_PACK32: return TextureFormat(TextureFormat::RGBA, TextureFormat::UNSIGNED_INT8);
+ case VK_FORMAT_A8B8G8R8_SINT_PACK32: return TextureFormat(TextureFormat::RGBA, TextureFormat::SIGNED_INT8);
+ case VK_FORMAT_A8B8G8R8_SRGB_PACK32: return TextureFormat(TextureFormat::sRGBA, TextureFormat::UNORM_INT8);
+#else
+# error "Big-endian not supported"
+#endif
+
+ case VK_FORMAT_A2R10G10B10_UNORM_PACK32: return TextureFormat(TextureFormat::BGRA, TextureFormat::UNORM_INT_1010102_REV);
+ case VK_FORMAT_A2R10G10B10_SNORM_PACK32: return TextureFormat(TextureFormat::BGRA, TextureFormat::SNORM_INT_1010102_REV);
+ case VK_FORMAT_A2R10G10B10_USCALED_PACK32: return TextureFormat(TextureFormat::BGRA, TextureFormat::UNSIGNED_INT_1010102_REV);
+ case VK_FORMAT_A2R10G10B10_SSCALED_PACK32: return TextureFormat(TextureFormat::BGRA, TextureFormat::SIGNED_INT_1010102_REV);
+ case VK_FORMAT_A2R10G10B10_UINT_PACK32: return TextureFormat(TextureFormat::BGRA, TextureFormat::UNSIGNED_INT_1010102_REV);
+ case VK_FORMAT_A2R10G10B10_SINT_PACK32: return TextureFormat(TextureFormat::BGRA, TextureFormat::SIGNED_INT_1010102_REV);
+
+ case VK_FORMAT_A2B10G10R10_UNORM_PACK32: return TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT_1010102_REV);
+ case VK_FORMAT_A2B10G10R10_SNORM_PACK32: return TextureFormat(TextureFormat::RGBA, TextureFormat::SNORM_INT_1010102_REV);
+ case VK_FORMAT_A2B10G10R10_USCALED_PACK32: return TextureFormat(TextureFormat::RGBA, TextureFormat::UNSIGNED_INT_1010102_REV);
+ case VK_FORMAT_A2B10G10R10_SSCALED_PACK32: return TextureFormat(TextureFormat::RGBA, TextureFormat::SIGNED_INT_1010102_REV);
+ case VK_FORMAT_A2B10G10R10_UINT_PACK32: return TextureFormat(TextureFormat::RGBA, TextureFormat::UNSIGNED_INT_1010102_REV);
+ case VK_FORMAT_A2B10G10R10_SINT_PACK32: return TextureFormat(TextureFormat::RGBA, TextureFormat::SIGNED_INT_1010102_REV);
+
+
+ default:
+ TCU_THROW(InternalError, "Unknown image format");
+ }
+}
+
+tcu::CompressedTexFormat mapVkCompressedFormat (VkFormat format)
+{
+ // update this mapping if VkFormat changes
+ DE_STATIC_ASSERT(VK_FORMAT_LAST == 185);
+
+ switch (format)
+ {
+ case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK: return tcu::COMPRESSEDTEXFORMAT_ETC2_RGB8;
+ case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK: return tcu::COMPRESSEDTEXFORMAT_ETC2_SRGB8;
+ case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK: return tcu::COMPRESSEDTEXFORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1;
+ case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK: return tcu::COMPRESSEDTEXFORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1;
+ case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK: return tcu::COMPRESSEDTEXFORMAT_ETC2_EAC_RGBA8;
+ case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK: return tcu::COMPRESSEDTEXFORMAT_ETC2_EAC_SRGB8_ALPHA8;
+ case VK_FORMAT_EAC_R11_UNORM_BLOCK: return tcu::COMPRESSEDTEXFORMAT_EAC_R11;
+ case VK_FORMAT_EAC_R11_SNORM_BLOCK: return tcu::COMPRESSEDTEXFORMAT_EAC_SIGNED_R11;
+ case VK_FORMAT_EAC_R11G11_UNORM_BLOCK: return tcu::COMPRESSEDTEXFORMAT_EAC_RG11;
+ case VK_FORMAT_EAC_R11G11_SNORM_BLOCK: return tcu::COMPRESSEDTEXFORMAT_EAC_SIGNED_RG11;
+ case VK_FORMAT_ASTC_4x4_UNORM_BLOCK: return tcu::COMPRESSEDTEXFORMAT_ASTC_4x4_RGBA;
+ case VK_FORMAT_ASTC_4x4_SRGB_BLOCK: return tcu::COMPRESSEDTEXFORMAT_ASTC_4x4_SRGB8_ALPHA8;
+ case VK_FORMAT_ASTC_5x4_UNORM_BLOCK: return tcu::COMPRESSEDTEXFORMAT_ASTC_5x4_RGBA;
+ case VK_FORMAT_ASTC_5x4_SRGB_BLOCK: return tcu::COMPRESSEDTEXFORMAT_ASTC_5x5_SRGB8_ALPHA8;
+ case VK_FORMAT_ASTC_5x5_UNORM_BLOCK: return tcu::COMPRESSEDTEXFORMAT_ASTC_5x5_RGBA;
+ case VK_FORMAT_ASTC_5x5_SRGB_BLOCK: return tcu::COMPRESSEDTEXFORMAT_ASTC_5x5_SRGB8_ALPHA8;
+ case VK_FORMAT_ASTC_6x5_UNORM_BLOCK: return tcu::COMPRESSEDTEXFORMAT_ASTC_6x5_RGBA;
+ case VK_FORMAT_ASTC_6x5_SRGB_BLOCK: return tcu::COMPRESSEDTEXFORMAT_ASTC_6x5_SRGB8_ALPHA8;
+ case VK_FORMAT_ASTC_6x6_UNORM_BLOCK: return tcu::COMPRESSEDTEXFORMAT_ASTC_6x6_RGBA;
+ case VK_FORMAT_ASTC_6x6_SRGB_BLOCK: return tcu::COMPRESSEDTEXFORMAT_ASTC_6x6_SRGB8_ALPHA8;
+ case VK_FORMAT_ASTC_8x5_UNORM_BLOCK: return tcu::COMPRESSEDTEXFORMAT_ASTC_8x5_RGBA;
+ case VK_FORMAT_ASTC_8x5_SRGB_BLOCK: return tcu::COMPRESSEDTEXFORMAT_ASTC_8x6_SRGB8_ALPHA8;
+ case VK_FORMAT_ASTC_8x6_UNORM_BLOCK: return tcu::COMPRESSEDTEXFORMAT_ASTC_8x6_RGBA;
+ case VK_FORMAT_ASTC_8x6_SRGB_BLOCK: return tcu::COMPRESSEDTEXFORMAT_ASTC_8x6_SRGB8_ALPHA8;
+ case VK_FORMAT_ASTC_8x8_UNORM_BLOCK: return tcu::COMPRESSEDTEXFORMAT_ASTC_8x8_RGBA;
+ case VK_FORMAT_ASTC_8x8_SRGB_BLOCK: return tcu::COMPRESSEDTEXFORMAT_ASTC_8x8_SRGB8_ALPHA8;
+ case VK_FORMAT_ASTC_10x5_UNORM_BLOCK: return tcu::COMPRESSEDTEXFORMAT_ASTC_10x5_RGBA;
+ case VK_FORMAT_ASTC_10x5_SRGB_BLOCK: return tcu::COMPRESSEDTEXFORMAT_ASTC_10x5_SRGB8_ALPHA8;
+ case VK_FORMAT_ASTC_10x6_UNORM_BLOCK: return tcu::COMPRESSEDTEXFORMAT_ASTC_10x6_RGBA;
+ case VK_FORMAT_ASTC_10x6_SRGB_BLOCK: return tcu::COMPRESSEDTEXFORMAT_ASTC_10x6_SRGB8_ALPHA8;
+ case VK_FORMAT_ASTC_10x8_UNORM_BLOCK: return tcu::COMPRESSEDTEXFORMAT_ASTC_10x8_RGBA;
+ case VK_FORMAT_ASTC_10x8_SRGB_BLOCK: return tcu::COMPRESSEDTEXFORMAT_ASTC_10x8_SRGB8_ALPHA8;
+ case VK_FORMAT_ASTC_10x10_UNORM_BLOCK: return tcu::COMPRESSEDTEXFORMAT_ASTC_10x10_RGBA;
+ case VK_FORMAT_ASTC_10x10_SRGB_BLOCK: return tcu::COMPRESSEDTEXFORMAT_ASTC_10x10_SRGB8_ALPHA8;
+ case VK_FORMAT_ASTC_12x10_UNORM_BLOCK: return tcu::COMPRESSEDTEXFORMAT_ASTC_12x10_RGBA;
+ case VK_FORMAT_ASTC_12x10_SRGB_BLOCK: return tcu::COMPRESSEDTEXFORMAT_ASTC_12x10_SRGB8_ALPHA8;
+ case VK_FORMAT_ASTC_12x12_UNORM_BLOCK: return tcu::COMPRESSEDTEXFORMAT_ASTC_12x12_RGBA;
+ case VK_FORMAT_ASTC_12x12_SRGB_BLOCK: return tcu::COMPRESSEDTEXFORMAT_ASTC_12x12_SRGB8_ALPHA8;
+ default:
+ break;
+ }
+
+ return tcu::COMPRESSEDTEXFORMAT_LAST;
+}
+
+VkComponentMapping getFormatComponentMapping (VkFormat format)
+{
+ using tcu::TextureFormat;
+
+ static const VkComponentMapping R = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ONE };
+ static const VkComponentMapping RG = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ONE };
+ static const VkComponentMapping RGB = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_ONE };
+ static const VkComponentMapping RGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
+ static const VkComponentMapping S = { VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_A };
+ static const VkComponentMapping DS = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_A };
+ static const VkComponentMapping BGRA = { VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_A };
+ static const VkComponentMapping BGR = { VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_ONE };
+
+ if (format == VK_FORMAT_UNDEFINED)
+ return RGBA;
+
+ const tcu::TextureFormat tcuFormat = (isCompressedFormat(format)) ? tcu::getUncompressedFormat(mapVkCompressedFormat(format))
+ : mapVkFormat(format);
+
+ switch (tcuFormat.order)
+ {
+ case TextureFormat::R: return R;
+ case TextureFormat::RG: return RG;
+ case TextureFormat::RGB: return RGB;
+ case TextureFormat::RGBA: return RGBA;
+ case TextureFormat::BGRA: return BGRA;
+ case TextureFormat::BGR: return BGR;
+ case TextureFormat::sR: return R;
+ case TextureFormat::sRG: return RG;
+ case TextureFormat::sRGB: return RGB;
+ case TextureFormat::sRGBA: return RGBA;
+ case TextureFormat::sBGR: return BGR;
+ case TextureFormat::sBGRA: return BGRA;
+ case TextureFormat::D: return R;
+ case TextureFormat::S: return S;
+ case TextureFormat::DS: return DS;
+ default:
+ break;
+ }
+
+ DE_ASSERT(false);
+ return RGBA;
+}
+
+static bool isScaledFormat (VkFormat format)
+{
+ // update this mapping if VkFormat changes
+ DE_STATIC_ASSERT(VK_FORMAT_LAST == 185);
+
+ switch (format)
+ {
+ case VK_FORMAT_R8_USCALED:
+ case VK_FORMAT_R8_SSCALED:
+ case VK_FORMAT_R8G8_USCALED:
+ case VK_FORMAT_R8G8_SSCALED:
+ case VK_FORMAT_R8G8B8_USCALED:
+ case VK_FORMAT_R8G8B8_SSCALED:
+ case VK_FORMAT_R8G8B8A8_USCALED:
+ case VK_FORMAT_R8G8B8A8_SSCALED:
+ case VK_FORMAT_A2B10G10R10_USCALED_PACK32:
+ case VK_FORMAT_A2B10G10R10_SSCALED_PACK32:
+ case VK_FORMAT_R16_USCALED:
+ case VK_FORMAT_R16_SSCALED:
+ case VK_FORMAT_R16G16_USCALED:
+ case VK_FORMAT_R16G16_SSCALED:
+ case VK_FORMAT_R16G16B16_USCALED:
+ case VK_FORMAT_R16G16B16_SSCALED:
+ case VK_FORMAT_R16G16B16A16_USCALED:
+ case VK_FORMAT_R16G16B16A16_SSCALED:
+ case VK_FORMAT_B8G8R8_USCALED:
+ case VK_FORMAT_B8G8R8_SSCALED:
+ case VK_FORMAT_B8G8R8A8_USCALED:
+ case VK_FORMAT_B8G8R8A8_SSCALED:
+ case VK_FORMAT_A2R10G10B10_USCALED_PACK32:
+ case VK_FORMAT_A2R10G10B10_SSCALED_PACK32:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+static bool fullTextureFormatRoundTripSupported (VkFormat format)
+{
+ if (isScaledFormat(format))
+ {
+ // *SCALED formats get mapped to correspoding (u)int formats since
+ // accessing them through (float) getPixel/setPixel has same behavior
+ // as in shader access in Vulkan.
+ // Unfortunately full round-trip between tcu::TextureFormat and VkFormat
+ // for most SCALED formats is not supported though.
+
+ const tcu::TextureFormat tcuFormat = mapVkFormat(format);
+
+ switch (tcuFormat.type)
+ {
+ case tcu::TextureFormat::UNSIGNED_INT8:
+ case tcu::TextureFormat::UNSIGNED_INT16:
+ case tcu::TextureFormat::UNSIGNED_INT32:
+ case tcu::TextureFormat::SIGNED_INT8:
+ case tcu::TextureFormat::SIGNED_INT16:
+ case tcu::TextureFormat::SIGNED_INT32:
+ case tcu::TextureFormat::UNSIGNED_INT_1010102_REV:
+ case tcu::TextureFormat::SIGNED_INT_1010102_REV:
+ return false;
+
+ default:
+ return true;
+ }
+ }
+ else
+ {
+ switch (format)
+ {
+ case VK_FORMAT_A8B8G8R8_UNORM_PACK32:
+ case VK_FORMAT_A8B8G8R8_SNORM_PACK32:
+ case VK_FORMAT_A8B8G8R8_USCALED_PACK32:
+ case VK_FORMAT_A8B8G8R8_SSCALED_PACK32:
+ case VK_FORMAT_A8B8G8R8_UINT_PACK32:
+ case VK_FORMAT_A8B8G8R8_SINT_PACK32:
+ case VK_FORMAT_A8B8G8R8_SRGB_PACK32:
+ return false; // These map to regular byte array formats
+
+ default:
+ break;
+ }
+
+ return (format != VK_FORMAT_UNDEFINED);
+ }
+}
+
+void imageUtilSelfTest (void)
+{
+ for (int formatNdx = 0; formatNdx < VK_FORMAT_LAST; formatNdx++)
+ {
+ const VkFormat format = (VkFormat)formatNdx;
+
+ if (format == VK_FORMAT_R64_UINT ||
+ format == VK_FORMAT_R64_SINT ||
+ format == VK_FORMAT_R64G64_UINT ||
+ format == VK_FORMAT_R64G64_SINT ||
+ format == VK_FORMAT_R64G64B64_UINT ||
+ format == VK_FORMAT_R64G64B64_SINT ||
+ format == VK_FORMAT_R64G64B64A64_UINT ||
+ format == VK_FORMAT_R64G64B64A64_SINT)
+ continue; // \todo [2015-12-05 pyry] Add framework support for (u)int64 channel type
+
+ if (format != VK_FORMAT_UNDEFINED && !isCompressedFormat(format))
+ {
+ const tcu::TextureFormat tcuFormat = mapVkFormat(format);
+ const VkFormat remappedFormat = mapTextureFormat(tcuFormat);
+
+ DE_TEST_ASSERT(isValid(tcuFormat));
+
+ if (fullTextureFormatRoundTripSupported(format))
+ DE_TEST_ASSERT(format == remappedFormat);
+ }
+ }
+}
+
+VkFilter mapFilterMode (tcu::Sampler::FilterMode filterMode)
+{
+ DE_STATIC_ASSERT(tcu::Sampler::FILTERMODE_LAST == 6);
+
+ switch(filterMode)
+ {
+ case tcu::Sampler::NEAREST: return VK_FILTER_NEAREST;
+ case tcu::Sampler::LINEAR: return VK_FILTER_LINEAR;
+ case tcu::Sampler::NEAREST_MIPMAP_NEAREST: return VK_FILTER_NEAREST;
+ case tcu::Sampler::NEAREST_MIPMAP_LINEAR: return VK_FILTER_NEAREST;
+ case tcu::Sampler::LINEAR_MIPMAP_NEAREST: return VK_FILTER_LINEAR;
+ case tcu::Sampler::LINEAR_MIPMAP_LINEAR: return VK_FILTER_LINEAR;
+ default:
+ DE_FATAL("Illegal filter mode");
+ return (VkFilter)0;
+
+ }
+}
+
+VkSamplerMipmapMode mapMipmapMode (tcu::Sampler::FilterMode filterMode)
+{
+ DE_STATIC_ASSERT(tcu::Sampler::FILTERMODE_LAST == 6);
+
+ switch(filterMode)
+ {
+ case tcu::Sampler::NEAREST: return VK_SAMPLER_MIPMAP_MODE_BASE;
+ case tcu::Sampler::LINEAR: return VK_SAMPLER_MIPMAP_MODE_BASE;
+ case tcu::Sampler::NEAREST_MIPMAP_NEAREST: return VK_SAMPLER_MIPMAP_MODE_NEAREST;
+ case tcu::Sampler::NEAREST_MIPMAP_LINEAR: return VK_SAMPLER_MIPMAP_MODE_LINEAR;
+ case tcu::Sampler::LINEAR_MIPMAP_NEAREST: return VK_SAMPLER_MIPMAP_MODE_NEAREST;
+ case tcu::Sampler::LINEAR_MIPMAP_LINEAR: return VK_SAMPLER_MIPMAP_MODE_LINEAR;
+ default:
+ DE_FATAL("Illegal filter mode");
+ return (VkSamplerMipmapMode)0;
+ }
+}
+
+VkSamplerAddressMode mapWrapMode (tcu::Sampler::WrapMode wrapMode)
+{
+ switch(wrapMode)
+ {
+ case tcu::Sampler::CLAMP_TO_EDGE: return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
+ case tcu::Sampler::CLAMP_TO_BORDER: return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
+ case tcu::Sampler::REPEAT_GL: return VK_SAMPLER_ADDRESS_MODE_REPEAT;
+ case tcu::Sampler::MIRRORED_REPEAT_GL: return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
+ case tcu::Sampler::MIRRORED_ONCE: return VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE;
+ default:
+ DE_FATAL("Wrap mode can't be mapped to Vulkan");
+ return (vk::VkSamplerAddressMode)0;
+ }
+}
+
+vk::VkCompareOp mapCompareMode (tcu::Sampler::CompareMode mode)
+{
+ switch(mode)
+ {
+ case tcu::Sampler::COMPAREMODE_NONE: return vk::VK_COMPARE_OP_NEVER;
+ case tcu::Sampler::COMPAREMODE_LESS: return vk::VK_COMPARE_OP_LESS;
+ case tcu::Sampler::COMPAREMODE_LESS_OR_EQUAL: return vk::VK_COMPARE_OP_LESS_OR_EQUAL;
+ case tcu::Sampler::COMPAREMODE_GREATER: return vk::VK_COMPARE_OP_GREATER;
+ case tcu::Sampler::COMPAREMODE_GREATER_OR_EQUAL: return vk::VK_COMPARE_OP_GREATER_OR_EQUAL;
+ case tcu::Sampler::COMPAREMODE_EQUAL: return vk::VK_COMPARE_OP_EQUAL;
+ case tcu::Sampler::COMPAREMODE_NOT_EQUAL: return vk::VK_COMPARE_OP_NOT_EQUAL;
+ case tcu::Sampler::COMPAREMODE_ALWAYS: return vk::VK_COMPARE_OP_ALWAYS;
+ case tcu::Sampler::COMPAREMODE_NEVER: return vk::VK_COMPARE_OP_NEVER;
+ default:
+ DE_FATAL("Illegal compare mode");
+ return (vk::VkCompareOp)0;
+ }
+}
+
+tcu::Sampler mapVkSampler (const VkSamplerCreateInfo& samplerCreateInfo)
+{
+ tcu::Vec4 borderColor;
+
+ switch (samplerCreateInfo.borderColor)
+ {
+ case VK_BORDER_COLOR_INT_OPAQUE_BLACK:
+ case VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK:
+ borderColor = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
+ break;
+
+ case VK_BORDER_COLOR_INT_OPAQUE_WHITE:
+ case VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE:
+ borderColor = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
+ break;
+
+ case VK_BORDER_COLOR_INT_TRANSPARENT_BLACK:
+ case VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK:
+ borderColor = tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f);
+ break;
+
+ default:
+ DE_ASSERT(false);
+ break;
+ }
+
+ tcu::Sampler sampler(mapVkSamplerAddressMode(samplerCreateInfo.addressModeU),
+ mapVkSamplerAddressMode(samplerCreateInfo.addressModeV),
+ mapVkSamplerAddressMode(samplerCreateInfo.addressModeW),
+ mapVkMinTexFilter(samplerCreateInfo.minFilter, samplerCreateInfo.mipmapMode),
+ mapVkMagTexFilter(samplerCreateInfo.magFilter),
+ 0.0f,
+ !samplerCreateInfo.unnormalizedCoordinates,
+ samplerCreateInfo.compareEnable ? mapVkSamplerCompareOp(samplerCreateInfo.compareOp)
+ : tcu::Sampler::COMPAREMODE_NONE,
+ 0,
+ borderColor,
+ true);
+ return sampler;
+}
+
+tcu::Sampler::CompareMode mapVkSamplerCompareOp (VkCompareOp compareOp)
+{
+ switch (compareOp)
+ {
+ case VK_COMPARE_OP_NEVER: return tcu::Sampler::COMPAREMODE_NEVER;
+ case VK_COMPARE_OP_LESS: return tcu::Sampler::COMPAREMODE_LESS;
+ case VK_COMPARE_OP_EQUAL: return tcu::Sampler::COMPAREMODE_EQUAL;
+ case VK_COMPARE_OP_LESS_OR_EQUAL: return tcu::Sampler::COMPAREMODE_LESS_OR_EQUAL;
+ case VK_COMPARE_OP_GREATER: return tcu::Sampler::COMPAREMODE_GREATER;
+ case VK_COMPARE_OP_NOT_EQUAL: return tcu::Sampler::COMPAREMODE_NOT_EQUAL;
+ case VK_COMPARE_OP_GREATER_OR_EQUAL: return tcu::Sampler::COMPAREMODE_GREATER_OR_EQUAL;
+ case VK_COMPARE_OP_ALWAYS: return tcu::Sampler::COMPAREMODE_ALWAYS;
+ default:
+ break;
+ }
+
+ DE_ASSERT(false);
+ return tcu::Sampler::COMPAREMODE_LAST;
+}
+
+tcu::Sampler::WrapMode mapVkSamplerAddressMode (VkSamplerAddressMode addressMode)
+{
+ switch (addressMode)
+ {
+ case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE: return tcu::Sampler::CLAMP_TO_EDGE;
+ case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER: return tcu::Sampler::CLAMP_TO_BORDER;
+ case VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT: return tcu::Sampler::MIRRORED_REPEAT_GL;
+ case VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE: return tcu::Sampler::MIRRORED_ONCE;
+ case VK_SAMPLER_ADDRESS_MODE_REPEAT: return tcu::Sampler::REPEAT_GL;
+ default:
+ break;
+ }
+
+ DE_ASSERT(false);
+ return tcu::Sampler::WRAPMODE_LAST;
+}
+
+tcu::Sampler::FilterMode mapVkMinTexFilter (VkFilter filter, VkSamplerMipmapMode mipMode)
+{
+ switch (filter)
+ {
+ case VK_FILTER_LINEAR:
+ switch (mipMode)
+ {
+ case VK_SAMPLER_MIPMAP_MODE_BASE: return tcu::Sampler::LINEAR_MIPMAP_NEAREST;
+ case VK_SAMPLER_MIPMAP_MODE_LINEAR: return tcu::Sampler::LINEAR_MIPMAP_LINEAR;
+ case VK_SAMPLER_MIPMAP_MODE_NEAREST: return tcu::Sampler::LINEAR_MIPMAP_NEAREST;
+ default:
+ break;
+ }
+ break;
+
+ case VK_FILTER_NEAREST:
+ switch (mipMode)
+ {
+ case VK_SAMPLER_MIPMAP_MODE_BASE: return tcu::Sampler::NEAREST_MIPMAP_NEAREST;
+ case VK_SAMPLER_MIPMAP_MODE_LINEAR: return tcu::Sampler::NEAREST_MIPMAP_LINEAR;
+ case VK_SAMPLER_MIPMAP_MODE_NEAREST: return tcu::Sampler::NEAREST_MIPMAP_NEAREST;
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ DE_ASSERT(false);
+ return tcu::Sampler::FILTERMODE_LAST;
+}
+
+tcu::Sampler::FilterMode mapVkMagTexFilter (VkFilter filter)
+{
+ switch (filter)
+ {
+ case VK_FILTER_LINEAR: return tcu::Sampler::LINEAR;
+ case VK_FILTER_NEAREST: return tcu::Sampler::NEAREST;
+ default:
+ break;
+ }
+
+ DE_ASSERT(false);
+ return tcu::Sampler::FILTERMODE_LAST;
+}
+
+
+int mapVkComponentSwizzle (const vk::VkComponentSwizzle& channelSwizzle)
+{
+ switch (channelSwizzle)
+ {
+ case vk::VK_COMPONENT_SWIZZLE_ZERO: return 0;
+ case vk::VK_COMPONENT_SWIZZLE_ONE: return 1;
+ case vk::VK_COMPONENT_SWIZZLE_R: return 2;
+ case vk::VK_COMPONENT_SWIZZLE_G: return 3;
+ case vk::VK_COMPONENT_SWIZZLE_B: return 4;
+ case vk::VK_COMPONENT_SWIZZLE_A: return 5;
+ default:
+ break;
+ }
+
+ DE_ASSERT(false);
+ return 0;
+}
+
+tcu::UVec4 mapVkComponentMapping (const vk::VkComponentMapping& mapping)
+{
+ tcu::UVec4 swizzle;
+
+ swizzle.x() = mapVkComponentSwizzle(mapping.r);
+ swizzle.y() = mapVkComponentSwizzle(mapping.g);
+ swizzle.z() = mapVkComponentSwizzle(mapping.b);
+ swizzle.w() = mapVkComponentSwizzle(mapping.a);
+
+ return swizzle;
+}
+
+} // vk
--- /dev/null
+#ifndef _VKIMAGEUTIL_HPP
+#define _VKIMAGEUTIL_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Imagination Technologies Ltd.
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Utilities for images.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkDefs.hpp"
+#include "tcuTexture.hpp"
+#include "tcuCompressedTexture.hpp"
+
+namespace vk
+{
+
+bool isFloatFormat (VkFormat format);
+bool isUnormFormat (VkFormat format);
+bool isSnormFormat (VkFormat format);
+bool isIntFormat (VkFormat format);
+bool isUintFormat (VkFormat format);
+bool isDepthStencilFormat (VkFormat format);
+bool isCompressedFormat (VkFormat format);
+
+tcu::TextureFormat mapVkFormat (VkFormat format);
+tcu::CompressedTexFormat mapVkCompressedFormat (VkFormat format);
+
+tcu::Sampler mapVkSampler (const VkSamplerCreateInfo& samplerCreateInfo);
+tcu::Sampler::CompareMode mapVkSamplerCompareOp (VkCompareOp compareOp);
+tcu::Sampler::WrapMode mapVkSamplerAddressMode (VkSamplerAddressMode addressMode);
+tcu::Sampler::FilterMode mapVkMinTexFilter (VkFilter filter, VkSamplerMipmapMode mipMode);
+tcu::Sampler::FilterMode mapVkMagTexFilter (VkFilter filter);
+int mapVkComponentSwizzle (const VkComponentSwizzle& channelSwizzle);
+tcu::UVec4 mapVkComponentMapping (const vk::VkComponentMapping& mapping);
+
+VkComponentMapping getFormatComponentMapping (VkFormat format);
+VkFilter mapFilterMode (tcu::Sampler::FilterMode filterMode);
+VkSamplerMipmapMode mapMipmapMode (tcu::Sampler::FilterMode filterMode);
+VkSamplerAddressMode mapWrapMode (tcu::Sampler::WrapMode wrapMode);
+VkCompareOp mapCompareMode (tcu::Sampler::CompareMode mode);
+VkFormat mapTextureFormat (const tcu::TextureFormat& format);
+
+void imageUtilSelfTest (void);
+
+} // vk
+
+#endif // _VKIMAGEUTIL_HPP
--- /dev/null
+/* WARNING: This is auto-generated file. Do not modify, since changes will
+ * be lost! Modify the generating script instead.
+ */
+m_vk.destroyDevice = (DestroyDeviceFunc) GET_PROC_ADDR("vkDestroyDevice");
+m_vk.getDeviceQueue = (GetDeviceQueueFunc) GET_PROC_ADDR("vkGetDeviceQueue");
+m_vk.queueSubmit = (QueueSubmitFunc) GET_PROC_ADDR("vkQueueSubmit");
+m_vk.queueWaitIdle = (QueueWaitIdleFunc) GET_PROC_ADDR("vkQueueWaitIdle");
+m_vk.deviceWaitIdle = (DeviceWaitIdleFunc) GET_PROC_ADDR("vkDeviceWaitIdle");
+m_vk.allocateMemory = (AllocateMemoryFunc) GET_PROC_ADDR("vkAllocateMemory");
+m_vk.freeMemory = (FreeMemoryFunc) GET_PROC_ADDR("vkFreeMemory");
+m_vk.mapMemory = (MapMemoryFunc) GET_PROC_ADDR("vkMapMemory");
+m_vk.unmapMemory = (UnmapMemoryFunc) GET_PROC_ADDR("vkUnmapMemory");
+m_vk.flushMappedMemoryRanges = (FlushMappedMemoryRangesFunc) GET_PROC_ADDR("vkFlushMappedMemoryRanges");
+m_vk.invalidateMappedMemoryRanges = (InvalidateMappedMemoryRangesFunc) GET_PROC_ADDR("vkInvalidateMappedMemoryRanges");
+m_vk.getDeviceMemoryCommitment = (GetDeviceMemoryCommitmentFunc) GET_PROC_ADDR("vkGetDeviceMemoryCommitment");
+m_vk.bindBufferMemory = (BindBufferMemoryFunc) GET_PROC_ADDR("vkBindBufferMemory");
+m_vk.bindImageMemory = (BindImageMemoryFunc) GET_PROC_ADDR("vkBindImageMemory");
+m_vk.getBufferMemoryRequirements = (GetBufferMemoryRequirementsFunc) GET_PROC_ADDR("vkGetBufferMemoryRequirements");
+m_vk.getImageMemoryRequirements = (GetImageMemoryRequirementsFunc) GET_PROC_ADDR("vkGetImageMemoryRequirements");
+m_vk.getImageSparseMemoryRequirements = (GetImageSparseMemoryRequirementsFunc) GET_PROC_ADDR("vkGetImageSparseMemoryRequirements");
+m_vk.getPhysicalDeviceSparseImageFormatProperties = (GetPhysicalDeviceSparseImageFormatPropertiesFunc) GET_PROC_ADDR("vkGetPhysicalDeviceSparseImageFormatProperties");
+m_vk.queueBindSparse = (QueueBindSparseFunc) GET_PROC_ADDR("vkQueueBindSparse");
+m_vk.createFence = (CreateFenceFunc) GET_PROC_ADDR("vkCreateFence");
+m_vk.destroyFence = (DestroyFenceFunc) GET_PROC_ADDR("vkDestroyFence");
+m_vk.resetFences = (ResetFencesFunc) GET_PROC_ADDR("vkResetFences");
+m_vk.getFenceStatus = (GetFenceStatusFunc) GET_PROC_ADDR("vkGetFenceStatus");
+m_vk.waitForFences = (WaitForFencesFunc) GET_PROC_ADDR("vkWaitForFences");
+m_vk.createSemaphore = (CreateSemaphoreFunc) GET_PROC_ADDR("vkCreateSemaphore");
+m_vk.destroySemaphore = (DestroySemaphoreFunc) GET_PROC_ADDR("vkDestroySemaphore");
+m_vk.createEvent = (CreateEventFunc) GET_PROC_ADDR("vkCreateEvent");
+m_vk.destroyEvent = (DestroyEventFunc) GET_PROC_ADDR("vkDestroyEvent");
+m_vk.getEventStatus = (GetEventStatusFunc) GET_PROC_ADDR("vkGetEventStatus");
+m_vk.setEvent = (SetEventFunc) GET_PROC_ADDR("vkSetEvent");
+m_vk.resetEvent = (ResetEventFunc) GET_PROC_ADDR("vkResetEvent");
+m_vk.createQueryPool = (CreateQueryPoolFunc) GET_PROC_ADDR("vkCreateQueryPool");
+m_vk.destroyQueryPool = (DestroyQueryPoolFunc) GET_PROC_ADDR("vkDestroyQueryPool");
+m_vk.getQueryPoolResults = (GetQueryPoolResultsFunc) GET_PROC_ADDR("vkGetQueryPoolResults");
+m_vk.createBuffer = (CreateBufferFunc) GET_PROC_ADDR("vkCreateBuffer");
+m_vk.destroyBuffer = (DestroyBufferFunc) GET_PROC_ADDR("vkDestroyBuffer");
+m_vk.createBufferView = (CreateBufferViewFunc) GET_PROC_ADDR("vkCreateBufferView");
+m_vk.destroyBufferView = (DestroyBufferViewFunc) GET_PROC_ADDR("vkDestroyBufferView");
+m_vk.createImage = (CreateImageFunc) GET_PROC_ADDR("vkCreateImage");
+m_vk.destroyImage = (DestroyImageFunc) GET_PROC_ADDR("vkDestroyImage");
+m_vk.getImageSubresourceLayout = (GetImageSubresourceLayoutFunc) GET_PROC_ADDR("vkGetImageSubresourceLayout");
+m_vk.createImageView = (CreateImageViewFunc) GET_PROC_ADDR("vkCreateImageView");
+m_vk.destroyImageView = (DestroyImageViewFunc) GET_PROC_ADDR("vkDestroyImageView");
+m_vk.createShaderModule = (CreateShaderModuleFunc) GET_PROC_ADDR("vkCreateShaderModule");
+m_vk.destroyShaderModule = (DestroyShaderModuleFunc) GET_PROC_ADDR("vkDestroyShaderModule");
+m_vk.createPipelineCache = (CreatePipelineCacheFunc) GET_PROC_ADDR("vkCreatePipelineCache");
+m_vk.destroyPipelineCache = (DestroyPipelineCacheFunc) GET_PROC_ADDR("vkDestroyPipelineCache");
+m_vk.getPipelineCacheData = (GetPipelineCacheDataFunc) GET_PROC_ADDR("vkGetPipelineCacheData");
+m_vk.mergePipelineCaches = (MergePipelineCachesFunc) GET_PROC_ADDR("vkMergePipelineCaches");
+m_vk.createGraphicsPipelines = (CreateGraphicsPipelinesFunc) GET_PROC_ADDR("vkCreateGraphicsPipelines");
+m_vk.createComputePipelines = (CreateComputePipelinesFunc) GET_PROC_ADDR("vkCreateComputePipelines");
+m_vk.destroyPipeline = (DestroyPipelineFunc) GET_PROC_ADDR("vkDestroyPipeline");
+m_vk.createPipelineLayout = (CreatePipelineLayoutFunc) GET_PROC_ADDR("vkCreatePipelineLayout");
+m_vk.destroyPipelineLayout = (DestroyPipelineLayoutFunc) GET_PROC_ADDR("vkDestroyPipelineLayout");
+m_vk.createSampler = (CreateSamplerFunc) GET_PROC_ADDR("vkCreateSampler");
+m_vk.destroySampler = (DestroySamplerFunc) GET_PROC_ADDR("vkDestroySampler");
+m_vk.createDescriptorSetLayout = (CreateDescriptorSetLayoutFunc) GET_PROC_ADDR("vkCreateDescriptorSetLayout");
+m_vk.destroyDescriptorSetLayout = (DestroyDescriptorSetLayoutFunc) GET_PROC_ADDR("vkDestroyDescriptorSetLayout");
+m_vk.createDescriptorPool = (CreateDescriptorPoolFunc) GET_PROC_ADDR("vkCreateDescriptorPool");
+m_vk.destroyDescriptorPool = (DestroyDescriptorPoolFunc) GET_PROC_ADDR("vkDestroyDescriptorPool");
+m_vk.resetDescriptorPool = (ResetDescriptorPoolFunc) GET_PROC_ADDR("vkResetDescriptorPool");
+m_vk.allocateDescriptorSets = (AllocateDescriptorSetsFunc) GET_PROC_ADDR("vkAllocateDescriptorSets");
+m_vk.freeDescriptorSets = (FreeDescriptorSetsFunc) GET_PROC_ADDR("vkFreeDescriptorSets");
+m_vk.updateDescriptorSets = (UpdateDescriptorSetsFunc) GET_PROC_ADDR("vkUpdateDescriptorSets");
+m_vk.createFramebuffer = (CreateFramebufferFunc) GET_PROC_ADDR("vkCreateFramebuffer");
+m_vk.destroyFramebuffer = (DestroyFramebufferFunc) GET_PROC_ADDR("vkDestroyFramebuffer");
+m_vk.createRenderPass = (CreateRenderPassFunc) GET_PROC_ADDR("vkCreateRenderPass");
+m_vk.destroyRenderPass = (DestroyRenderPassFunc) GET_PROC_ADDR("vkDestroyRenderPass");
+m_vk.getRenderAreaGranularity = (GetRenderAreaGranularityFunc) GET_PROC_ADDR("vkGetRenderAreaGranularity");
+m_vk.createCommandPool = (CreateCommandPoolFunc) GET_PROC_ADDR("vkCreateCommandPool");
+m_vk.destroyCommandPool = (DestroyCommandPoolFunc) GET_PROC_ADDR("vkDestroyCommandPool");
+m_vk.resetCommandPool = (ResetCommandPoolFunc) GET_PROC_ADDR("vkResetCommandPool");
+m_vk.allocateCommandBuffers = (AllocateCommandBuffersFunc) GET_PROC_ADDR("vkAllocateCommandBuffers");
+m_vk.freeCommandBuffers = (FreeCommandBuffersFunc) GET_PROC_ADDR("vkFreeCommandBuffers");
+m_vk.beginCommandBuffer = (BeginCommandBufferFunc) GET_PROC_ADDR("vkBeginCommandBuffer");
+m_vk.endCommandBuffer = (EndCommandBufferFunc) GET_PROC_ADDR("vkEndCommandBuffer");
+m_vk.resetCommandBuffer = (ResetCommandBufferFunc) GET_PROC_ADDR("vkResetCommandBuffer");
+m_vk.cmdBindPipeline = (CmdBindPipelineFunc) GET_PROC_ADDR("vkCmdBindPipeline");
+m_vk.cmdSetViewport = (CmdSetViewportFunc) GET_PROC_ADDR("vkCmdSetViewport");
+m_vk.cmdSetScissor = (CmdSetScissorFunc) GET_PROC_ADDR("vkCmdSetScissor");
+m_vk.cmdSetLineWidth = (CmdSetLineWidthFunc) GET_PROC_ADDR("vkCmdSetLineWidth");
+m_vk.cmdSetDepthBias = (CmdSetDepthBiasFunc) GET_PROC_ADDR("vkCmdSetDepthBias");
+m_vk.cmdSetBlendConstants = (CmdSetBlendConstantsFunc) GET_PROC_ADDR("vkCmdSetBlendConstants");
+m_vk.cmdSetDepthBounds = (CmdSetDepthBoundsFunc) GET_PROC_ADDR("vkCmdSetDepthBounds");
+m_vk.cmdSetStencilCompareMask = (CmdSetStencilCompareMaskFunc) GET_PROC_ADDR("vkCmdSetStencilCompareMask");
+m_vk.cmdSetStencilWriteMask = (CmdSetStencilWriteMaskFunc) GET_PROC_ADDR("vkCmdSetStencilWriteMask");
+m_vk.cmdSetStencilReference = (CmdSetStencilReferenceFunc) GET_PROC_ADDR("vkCmdSetStencilReference");
+m_vk.cmdBindDescriptorSets = (CmdBindDescriptorSetsFunc) GET_PROC_ADDR("vkCmdBindDescriptorSets");
+m_vk.cmdBindIndexBuffer = (CmdBindIndexBufferFunc) GET_PROC_ADDR("vkCmdBindIndexBuffer");
+m_vk.cmdBindVertexBuffers = (CmdBindVertexBuffersFunc) GET_PROC_ADDR("vkCmdBindVertexBuffers");
+m_vk.cmdDraw = (CmdDrawFunc) GET_PROC_ADDR("vkCmdDraw");
+m_vk.cmdDrawIndexed = (CmdDrawIndexedFunc) GET_PROC_ADDR("vkCmdDrawIndexed");
+m_vk.cmdDrawIndirect = (CmdDrawIndirectFunc) GET_PROC_ADDR("vkCmdDrawIndirect");
+m_vk.cmdDrawIndexedIndirect = (CmdDrawIndexedIndirectFunc) GET_PROC_ADDR("vkCmdDrawIndexedIndirect");
+m_vk.cmdDispatch = (CmdDispatchFunc) GET_PROC_ADDR("vkCmdDispatch");
+m_vk.cmdDispatchIndirect = (CmdDispatchIndirectFunc) GET_PROC_ADDR("vkCmdDispatchIndirect");
+m_vk.cmdCopyBuffer = (CmdCopyBufferFunc) GET_PROC_ADDR("vkCmdCopyBuffer");
+m_vk.cmdCopyImage = (CmdCopyImageFunc) GET_PROC_ADDR("vkCmdCopyImage");
+m_vk.cmdBlitImage = (CmdBlitImageFunc) GET_PROC_ADDR("vkCmdBlitImage");
+m_vk.cmdCopyBufferToImage = (CmdCopyBufferToImageFunc) GET_PROC_ADDR("vkCmdCopyBufferToImage");
+m_vk.cmdCopyImageToBuffer = (CmdCopyImageToBufferFunc) GET_PROC_ADDR("vkCmdCopyImageToBuffer");
+m_vk.cmdUpdateBuffer = (CmdUpdateBufferFunc) GET_PROC_ADDR("vkCmdUpdateBuffer");
+m_vk.cmdFillBuffer = (CmdFillBufferFunc) GET_PROC_ADDR("vkCmdFillBuffer");
+m_vk.cmdClearColorImage = (CmdClearColorImageFunc) GET_PROC_ADDR("vkCmdClearColorImage");
+m_vk.cmdClearDepthStencilImage = (CmdClearDepthStencilImageFunc) GET_PROC_ADDR("vkCmdClearDepthStencilImage");
+m_vk.cmdClearAttachments = (CmdClearAttachmentsFunc) GET_PROC_ADDR("vkCmdClearAttachments");
+m_vk.cmdResolveImage = (CmdResolveImageFunc) GET_PROC_ADDR("vkCmdResolveImage");
+m_vk.cmdSetEvent = (CmdSetEventFunc) GET_PROC_ADDR("vkCmdSetEvent");
+m_vk.cmdResetEvent = (CmdResetEventFunc) GET_PROC_ADDR("vkCmdResetEvent");
+m_vk.cmdWaitEvents = (CmdWaitEventsFunc) GET_PROC_ADDR("vkCmdWaitEvents");
+m_vk.cmdPipelineBarrier = (CmdPipelineBarrierFunc) GET_PROC_ADDR("vkCmdPipelineBarrier");
+m_vk.cmdBeginQuery = (CmdBeginQueryFunc) GET_PROC_ADDR("vkCmdBeginQuery");
+m_vk.cmdEndQuery = (CmdEndQueryFunc) GET_PROC_ADDR("vkCmdEndQuery");
+m_vk.cmdResetQueryPool = (CmdResetQueryPoolFunc) GET_PROC_ADDR("vkCmdResetQueryPool");
+m_vk.cmdWriteTimestamp = (CmdWriteTimestampFunc) GET_PROC_ADDR("vkCmdWriteTimestamp");
+m_vk.cmdCopyQueryPoolResults = (CmdCopyQueryPoolResultsFunc) GET_PROC_ADDR("vkCmdCopyQueryPoolResults");
+m_vk.cmdPushConstants = (CmdPushConstantsFunc) GET_PROC_ADDR("vkCmdPushConstants");
+m_vk.cmdBeginRenderPass = (CmdBeginRenderPassFunc) GET_PROC_ADDR("vkCmdBeginRenderPass");
+m_vk.cmdNextSubpass = (CmdNextSubpassFunc) GET_PROC_ADDR("vkCmdNextSubpass");
+m_vk.cmdEndRenderPass = (CmdEndRenderPassFunc) GET_PROC_ADDR("vkCmdEndRenderPass");
+m_vk.cmdExecuteCommands = (CmdExecuteCommandsFunc) GET_PROC_ADDR("vkCmdExecuteCommands");
--- /dev/null
+/* WARNING: This is auto-generated file. Do not modify, since changes will
+ * be lost! Modify the generating script instead.
+ */
+m_vk.destroyInstance = (DestroyInstanceFunc) GET_PROC_ADDR("vkDestroyInstance");
+m_vk.enumeratePhysicalDevices = (EnumeratePhysicalDevicesFunc) GET_PROC_ADDR("vkEnumeratePhysicalDevices");
+m_vk.getPhysicalDeviceFeatures = (GetPhysicalDeviceFeaturesFunc) GET_PROC_ADDR("vkGetPhysicalDeviceFeatures");
+m_vk.getPhysicalDeviceFormatProperties = (GetPhysicalDeviceFormatPropertiesFunc) GET_PROC_ADDR("vkGetPhysicalDeviceFormatProperties");
+m_vk.getPhysicalDeviceImageFormatProperties = (GetPhysicalDeviceImageFormatPropertiesFunc) GET_PROC_ADDR("vkGetPhysicalDeviceImageFormatProperties");
+m_vk.getPhysicalDeviceProperties = (GetPhysicalDevicePropertiesFunc) GET_PROC_ADDR("vkGetPhysicalDeviceProperties");
+m_vk.getPhysicalDeviceQueueFamilyProperties = (GetPhysicalDeviceQueueFamilyPropertiesFunc) GET_PROC_ADDR("vkGetPhysicalDeviceQueueFamilyProperties");
+m_vk.getPhysicalDeviceMemoryProperties = (GetPhysicalDeviceMemoryPropertiesFunc) GET_PROC_ADDR("vkGetPhysicalDeviceMemoryProperties");
+m_vk.getDeviceProcAddr = (GetDeviceProcAddrFunc) GET_PROC_ADDR("vkGetDeviceProcAddr");
+m_vk.createDevice = (CreateDeviceFunc) GET_PROC_ADDR("vkCreateDevice");
+m_vk.enumerateDeviceExtensionProperties = (EnumerateDeviceExtensionPropertiesFunc) GET_PROC_ADDR("vkEnumerateDeviceExtensionProperties");
+m_vk.enumerateDeviceLayerProperties = (EnumerateDeviceLayerPropertiesFunc) GET_PROC_ADDR("vkEnumerateDeviceLayerProperties");
--- /dev/null
+/* WARNING: This is auto-generated file. Do not modify, since changes will
+ * be lost! Modify the generating script instead.
+ */
+m_vk.createInstance = (CreateInstanceFunc) GET_PROC_ADDR("vkCreateInstance");
+m_vk.getInstanceProcAddr = (GetInstanceProcAddrFunc) GET_PROC_ADDR("vkGetInstanceProcAddr");
+m_vk.enumerateInstanceExtensionProperties = (EnumerateInstanceExtensionPropertiesFunc) GET_PROC_ADDR("vkEnumerateInstanceExtensionProperties");
+m_vk.enumerateInstanceLayerProperties = (EnumerateInstanceLayerPropertiesFunc) GET_PROC_ADDR("vkEnumerateInstanceLayerProperties");
--- /dev/null
+/* WARNING: This is auto-generated file. Do not modify, since changes will
+ * be lost! Modify the generating script instead.
+ */
+
+void InstanceDriver::destroyInstance (VkInstance instance, const VkAllocationCallbacks* pAllocator) const
+{
+ m_vk.destroyInstance(instance, pAllocator);
+}
+
+VkResult InstanceDriver::enumeratePhysicalDevices (VkInstance instance, deUint32* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices) const
+{
+ return m_vk.enumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices);
+}
+
+void InstanceDriver::getPhysicalDeviceFeatures (VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures* pFeatures) const
+{
+ m_vk.getPhysicalDeviceFeatures(physicalDevice, pFeatures);
+}
+
+void InstanceDriver::getPhysicalDeviceFormatProperties (VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties* pFormatProperties) const
+{
+ m_vk.getPhysicalDeviceFormatProperties(physicalDevice, format, pFormatProperties);
+}
+
+VkResult InstanceDriver::getPhysicalDeviceImageFormatProperties (VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties* pImageFormatProperties) const
+{
+ return m_vk.getPhysicalDeviceImageFormatProperties(physicalDevice, format, type, tiling, usage, flags, pImageFormatProperties);
+}
+
+void InstanceDriver::getPhysicalDeviceProperties (VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties* pProperties) const
+{
+ m_vk.getPhysicalDeviceProperties(physicalDevice, pProperties);
+}
+
+void InstanceDriver::getPhysicalDeviceQueueFamilyProperties (VkPhysicalDevice physicalDevice, deUint32* pQueueFamilyPropertyCount, VkQueueFamilyProperties* pQueueFamilyProperties) const
+{
+ m_vk.getPhysicalDeviceQueueFamilyProperties(physicalDevice, pQueueFamilyPropertyCount, pQueueFamilyProperties);
+}
+
+void InstanceDriver::getPhysicalDeviceMemoryProperties (VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties* pMemoryProperties) const
+{
+ m_vk.getPhysicalDeviceMemoryProperties(physicalDevice, pMemoryProperties);
+}
+
+PFN_vkVoidFunction InstanceDriver::getDeviceProcAddr (VkDevice device, const char* pName) const
+{
+ return m_vk.getDeviceProcAddr(device, pName);
+}
+
+VkResult InstanceDriver::createDevice (VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice) const
+{
+ return m_vk.createDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
+}
+
+VkResult InstanceDriver::enumerateDeviceExtensionProperties (VkPhysicalDevice physicalDevice, const char* pLayerName, deUint32* pPropertyCount, VkExtensionProperties* pProperties) const
+{
+ return m_vk.enumerateDeviceExtensionProperties(physicalDevice, pLayerName, pPropertyCount, pProperties);
+}
+
+VkResult InstanceDriver::enumerateDeviceLayerProperties (VkPhysicalDevice physicalDevice, deUint32* pPropertyCount, VkLayerProperties* pProperties) const
+{
+ return m_vk.enumerateDeviceLayerProperties(physicalDevice, pPropertyCount, pProperties);
+}
--- /dev/null
+/* WARNING: This is auto-generated file. Do not modify, since changes will
+ * be lost! Modify the generating script instead.
+ */
+DestroyInstanceFunc destroyInstance;
+EnumeratePhysicalDevicesFunc enumeratePhysicalDevices;
+GetPhysicalDeviceFeaturesFunc getPhysicalDeviceFeatures;
+GetPhysicalDeviceFormatPropertiesFunc getPhysicalDeviceFormatProperties;
+GetPhysicalDeviceImageFormatPropertiesFunc getPhysicalDeviceImageFormatProperties;
+GetPhysicalDevicePropertiesFunc getPhysicalDeviceProperties;
+GetPhysicalDeviceQueueFamilyPropertiesFunc getPhysicalDeviceQueueFamilyProperties;
+GetPhysicalDeviceMemoryPropertiesFunc getPhysicalDeviceMemoryProperties;
+GetDeviceProcAddrFunc getDeviceProcAddr;
+CreateDeviceFunc createDevice;
+EnumerateDeviceExtensionPropertiesFunc enumerateDeviceExtensionProperties;
+EnumerateDeviceLayerPropertiesFunc enumerateDeviceLayerProperties;
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Memory management utilities.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkMemUtil.hpp"
+#include "vkStrUtil.hpp"
+#include "vkQueryUtil.hpp"
+#include "vkRef.hpp"
+#include "vkRefUtil.hpp"
+#include "deInt32.h"
+
+#include <sstream>
+
+namespace vk
+{
+
+using de::UniquePtr;
+using de::MovePtr;
+
+namespace
+{
+
+class HostPtr
+{
+public:
+ HostPtr (const DeviceInterface& vkd, VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags);
+ ~HostPtr (void);
+
+ void* get (void) const { return m_ptr; }
+
+private:
+ const DeviceInterface& m_vkd;
+ const VkDevice m_device;
+ const VkDeviceMemory m_memory;
+ void* const m_ptr;
+};
+
+void* mapMemory (const DeviceInterface& vkd, VkDevice device, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags)
+{
+ void* hostPtr = DE_NULL;
+ VK_CHECK(vkd.mapMemory(device, mem, offset, size, flags, &hostPtr));
+ TCU_CHECK(hostPtr);
+ return hostPtr;
+}
+
+HostPtr::HostPtr (const DeviceInterface& vkd, VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags)
+ : m_vkd (vkd)
+ , m_device (device)
+ , m_memory (memory)
+ , m_ptr (mapMemory(vkd, device, memory, offset, size, flags))
+{
+}
+
+HostPtr::~HostPtr (void)
+{
+ m_vkd.unmapMemory(m_device, m_memory);
+}
+
+deUint32 selectMatchingMemoryType (const VkPhysicalDeviceMemoryProperties& deviceMemProps, deUint32 allowedMemTypeBits, MemoryRequirement requirement)
+{
+ for (deUint32 memoryTypeNdx = 0; memoryTypeNdx < deviceMemProps.memoryTypeCount; memoryTypeNdx++)
+ {
+ if ((allowedMemTypeBits & (1u << memoryTypeNdx)) != 0 &&
+ requirement.matchesHeap(deviceMemProps.memoryTypes[memoryTypeNdx].propertyFlags))
+ return memoryTypeNdx;
+ }
+
+ TCU_THROW(NotSupportedError, "No compatible memory type found");
+}
+
+bool isHostVisibleMemory (const VkPhysicalDeviceMemoryProperties& deviceMemProps, deUint32 memoryTypeNdx)
+{
+ DE_ASSERT(memoryTypeNdx < deviceMemProps.memoryTypeCount);
+ return (deviceMemProps.memoryTypes[memoryTypeNdx].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0u;
+}
+
+} // anonymous
+
+// Allocation
+
+Allocation::Allocation (VkDeviceMemory memory, VkDeviceSize offset, void* hostPtr)
+ : m_memory (memory)
+ , m_offset (offset)
+ , m_hostPtr (hostPtr)
+{
+}
+
+Allocation::~Allocation (void)
+{
+}
+
+// MemoryRequirement
+
+const MemoryRequirement MemoryRequirement::Any = MemoryRequirement(0x0u);
+const MemoryRequirement MemoryRequirement::HostVisible = MemoryRequirement(MemoryRequirement::FLAG_HOST_VISIBLE);
+const MemoryRequirement MemoryRequirement::Coherent = MemoryRequirement(MemoryRequirement::FLAG_COHERENT);
+const MemoryRequirement MemoryRequirement::LazilyAllocated = MemoryRequirement(MemoryRequirement::FLAG_LAZY_ALLOCATION);
+
+bool MemoryRequirement::matchesHeap (VkMemoryPropertyFlags heapFlags) const
+{
+ // sanity check
+ if ((m_flags & FLAG_COHERENT) && !(m_flags & FLAG_HOST_VISIBLE))
+ DE_FATAL("Coherent memory must be host-visible");
+ if ((m_flags & FLAG_HOST_VISIBLE) && (m_flags & FLAG_LAZY_ALLOCATION))
+ DE_FATAL("Lazily allocated memory cannot be mappable");
+
+ // host-visible
+ if ((m_flags & FLAG_HOST_VISIBLE) && !(heapFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT))
+ return false;
+
+ // coherent
+ if ((m_flags & FLAG_COHERENT) && !(heapFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT))
+ return false;
+
+ // lazy
+ if ((m_flags & FLAG_LAZY_ALLOCATION) && !(heapFlags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT))
+ return false;
+
+ return true;
+}
+
+MemoryRequirement::MemoryRequirement (deUint32 flags)
+ : m_flags(flags)
+{
+}
+
+// SimpleAllocator
+
+class SimpleAllocation : public Allocation
+{
+public:
+ SimpleAllocation (Move<VkDeviceMemory> mem, MovePtr<HostPtr> hostPtr);
+ virtual ~SimpleAllocation (void);
+
+private:
+ const Unique<VkDeviceMemory> m_memHolder;
+ const UniquePtr<HostPtr> m_hostPtr;
+};
+
+SimpleAllocation::SimpleAllocation (Move<VkDeviceMemory> mem, MovePtr<HostPtr> hostPtr)
+ : Allocation (*mem, (VkDeviceSize)0, hostPtr ? hostPtr->get() : DE_NULL)
+ , m_memHolder (mem)
+ , m_hostPtr (hostPtr)
+{
+}
+
+SimpleAllocation::~SimpleAllocation (void)
+{
+}
+
+SimpleAllocator::SimpleAllocator (const DeviceInterface& vk, VkDevice device, const VkPhysicalDeviceMemoryProperties& deviceMemProps)
+ : m_vk (vk)
+ , m_device (device)
+ , m_memProps(deviceMemProps)
+{
+}
+
+MovePtr<Allocation> SimpleAllocator::allocate (const VkMemoryAllocateInfo& allocInfo, VkDeviceSize alignment)
+{
+ DE_UNREF(alignment);
+
+ Move<VkDeviceMemory> mem = allocateMemory(m_vk, m_device, &allocInfo);
+ MovePtr<HostPtr> hostPtr;
+
+ if (isHostVisibleMemory(m_memProps, allocInfo.memoryTypeIndex))
+ hostPtr = MovePtr<HostPtr>(new HostPtr(m_vk, m_device, *mem, 0u, allocInfo.allocationSize, 0u));
+
+ return MovePtr<Allocation>(new SimpleAllocation(mem, hostPtr));
+}
+
+MovePtr<Allocation> SimpleAllocator::allocate (const VkMemoryRequirements& memReqs, MemoryRequirement requirement)
+{
+ const deUint32 memoryTypeNdx = selectMatchingMemoryType(m_memProps, memReqs.memoryTypeBits, requirement);
+ const VkMemoryAllocateInfo allocInfo =
+ {
+ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ memReqs.size, // VkDeviceSize allocationSize;
+ memoryTypeNdx, // deUint32 memoryTypeIndex;
+ };
+
+ Move<VkDeviceMemory> mem = allocateMemory(m_vk, m_device, &allocInfo);
+ MovePtr<HostPtr> hostPtr;
+
+ if (requirement & MemoryRequirement::HostVisible)
+ {
+ DE_ASSERT(isHostVisibleMemory(m_memProps, allocInfo.memoryTypeIndex));
+ hostPtr = MovePtr<HostPtr>(new HostPtr(m_vk, m_device, *mem, 0u, allocInfo.allocationSize, 0u));
+ }
+
+ return MovePtr<Allocation>(new SimpleAllocation(mem, hostPtr));
+}
+
+void flushMappedMemoryRange (const DeviceInterface& vkd, VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size)
+{
+ const VkMappedMemoryRange range =
+ {
+ VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
+ DE_NULL,
+ memory,
+ offset,
+ size
+ };
+
+ VK_CHECK(vkd.flushMappedMemoryRanges(device, 1u, &range));
+}
+
+void invalidateMappedMemoryRange (const DeviceInterface& vkd, VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size)
+{
+ const VkMappedMemoryRange range =
+ {
+ VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
+ DE_NULL,
+ memory,
+ offset,
+ size
+ };
+
+ VK_CHECK(vkd.invalidateMappedMemoryRanges(device, 1u, &range));
+}
+
+} // vk
--- /dev/null
+#ifndef _VKMEMUTIL_HPP
+#define _VKMEMUTIL_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Memory management utilities.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkDefs.hpp"
+#include "deUniquePtr.hpp"
+
+namespace vk
+{
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Memory allocation interface
+ *
+ * Allocation represents block of device memory and is allocated by
+ * Allocator implementation. Test code should use Allocator for allocating
+ * memory, unless there is a reason not to (for example testing vkAllocMemory).
+ *
+ * Allocation doesn't necessarily correspond to a whole VkDeviceMemory, but
+ * instead it may represent sub-allocation. Thus whenever VkDeviceMemory
+ * (getMemory()) managed by Allocation is passed to Vulkan API calls,
+ * offset given by getOffset() must be used.
+ *
+ * If host-visible memory was requested, host pointer to the memory can
+ * be queried with getHostPtr(). No offset is needed when accessing host
+ * pointer, i.e. the pointer is already adjusted in case of sub-allocation.
+ *
+ * Memory mappings are managed solely by Allocation, i.e. unmapping or
+ * re-mapping VkDeviceMemory owned by Allocation is not allowed.
+ *//*--------------------------------------------------------------------*/
+class Allocation
+{
+public:
+ virtual ~Allocation (void);
+
+ //! Get VkDeviceMemory backing this allocation
+ VkDeviceMemory getMemory (void) const { return m_memory; }
+
+ //! Get offset in VkDeviceMemory for this allocation
+ VkDeviceSize getOffset (void) const { return m_offset; }
+
+ //! Get host pointer for this allocation. Only available for host-visible allocations
+ void* getHostPtr (void) const { DE_ASSERT(m_hostPtr); return m_hostPtr; }
+
+protected:
+ Allocation (VkDeviceMemory memory, VkDeviceSize offset, void* hostPtr);
+
+private:
+ const VkDeviceMemory m_memory;
+ const VkDeviceSize m_offset;
+ void* const m_hostPtr;
+};
+
+//! Memory allocation requirements
+class MemoryRequirement
+{
+public:
+ static const MemoryRequirement Any;
+ static const MemoryRequirement HostVisible;
+ static const MemoryRequirement Coherent;
+ static const MemoryRequirement LazilyAllocated;
+
+ inline MemoryRequirement operator| (MemoryRequirement requirement) const
+ {
+ return MemoryRequirement(m_flags | requirement.m_flags);
+ }
+
+ inline MemoryRequirement operator& (MemoryRequirement requirement) const
+ {
+ return MemoryRequirement(m_flags & requirement.m_flags);
+ }
+
+ bool matchesHeap (VkMemoryPropertyFlags heapFlags) const;
+
+ inline operator bool (void) const { return m_flags != 0u; }
+
+private:
+ explicit MemoryRequirement (deUint32 flags);
+
+ const deUint32 m_flags;
+
+ enum Flags
+ {
+ FLAG_HOST_VISIBLE = 1u << 0u,
+ FLAG_COHERENT = 1u << 1u,
+ FLAG_LAZY_ALLOCATION = 1u << 2u,
+ };
+};
+
+//! Memory allocator interface
+class Allocator
+{
+public:
+ Allocator (void) {}
+ virtual ~Allocator (void) {}
+
+ virtual de::MovePtr<Allocation> allocate (const VkMemoryAllocateInfo& allocInfo, VkDeviceSize alignment) = 0;
+ virtual de::MovePtr<Allocation> allocate (const VkMemoryRequirements& memRequirements, MemoryRequirement requirement) = 0;
+};
+
+//! Allocator that backs every allocation with its own VkDeviceMemory
+class SimpleAllocator : public Allocator
+{
+public:
+ SimpleAllocator (const DeviceInterface& vk, VkDevice device, const VkPhysicalDeviceMemoryProperties& deviceMemProps);
+
+ de::MovePtr<Allocation> allocate (const VkMemoryAllocateInfo& allocInfo, VkDeviceSize alignment);
+ de::MovePtr<Allocation> allocate (const VkMemoryRequirements& memRequirements, MemoryRequirement requirement);
+
+private:
+ const DeviceInterface& m_vk;
+ const VkDevice m_device;
+ const VkPhysicalDeviceMemoryProperties m_memProps;
+};
+
+void flushMappedMemoryRange (const DeviceInterface& vkd, VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size);
+void invalidateMappedMemoryRange (const DeviceInterface& vkd, VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size);
+
+} // vk
+
+#endif // _VKMEMUTIL_HPP
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Null (dummy) Vulkan implementation.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkNullDriver.hpp"
+#include "vkPlatform.hpp"
+#include "vkImageUtil.hpp"
+#include "tcuFunctionLibrary.hpp"
+#include "deMemory.h"
+
+#include <stdexcept>
+#include <algorithm>
+
+namespace vk
+{
+
+namespace
+{
+
+using std::vector;
+
+#define VK_NULL_RETURN(STMT) \
+ do { \
+ try { \
+ STMT; \
+ return VK_SUCCESS; \
+ } catch (const std::bad_alloc&) { \
+ return VK_ERROR_OUT_OF_HOST_MEMORY; \
+ } catch (VkResult res) { \
+ return res; \
+ } \
+ } while (deGetFalse())
+
+// \todo [2015-07-14 pyry] Check FUNC type by checkedCastToPtr<T>() or similar
+#define VK_NULL_FUNC_ENTRY(NAME, FUNC) { #NAME, (deFunctionPtr)FUNC }
+
+#define VK_NULL_DEFINE_DEVICE_OBJ(NAME) \
+struct NAME \
+{ \
+ NAME (VkDevice, const Vk##NAME##CreateInfo*) {} \
+}
+
+VK_NULL_DEFINE_DEVICE_OBJ(Fence);
+VK_NULL_DEFINE_DEVICE_OBJ(Semaphore);
+VK_NULL_DEFINE_DEVICE_OBJ(Event);
+VK_NULL_DEFINE_DEVICE_OBJ(QueryPool);
+VK_NULL_DEFINE_DEVICE_OBJ(BufferView);
+VK_NULL_DEFINE_DEVICE_OBJ(ImageView);
+VK_NULL_DEFINE_DEVICE_OBJ(ShaderModule);
+VK_NULL_DEFINE_DEVICE_OBJ(PipelineCache);
+VK_NULL_DEFINE_DEVICE_OBJ(PipelineLayout);
+VK_NULL_DEFINE_DEVICE_OBJ(RenderPass);
+VK_NULL_DEFINE_DEVICE_OBJ(DescriptorSetLayout);
+VK_NULL_DEFINE_DEVICE_OBJ(Sampler);
+VK_NULL_DEFINE_DEVICE_OBJ(Framebuffer);
+VK_NULL_DEFINE_DEVICE_OBJ(CommandPool);
+
+class Instance
+{
+public:
+ Instance (const VkInstanceCreateInfo* instanceInfo);
+ ~Instance (void) {}
+
+ PFN_vkVoidFunction getProcAddr (const char* name) const { return (PFN_vkVoidFunction)m_functions.getFunction(name); }
+
+private:
+ const tcu::StaticFunctionLibrary m_functions;
+};
+
+class Device
+{
+public:
+ Device (VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* deviceInfo);
+ ~Device (void) {}
+
+ PFN_vkVoidFunction getProcAddr (const char* name) const { return (PFN_vkVoidFunction)m_functions.getFunction(name); }
+
+private:
+ const tcu::StaticFunctionLibrary m_functions;
+};
+
+class Pipeline
+{
+public:
+ Pipeline (VkDevice, const VkGraphicsPipelineCreateInfo*) {}
+ Pipeline (VkDevice, const VkComputePipelineCreateInfo*) {}
+};
+
+void* allocateHeap (const VkMemoryAllocateInfo* pAllocInfo)
+{
+ // \todo [2015-12-03 pyry] Alignment requirements?
+ // \todo [2015-12-03 pyry] Empty allocations okay?
+ if (pAllocInfo->allocationSize > 0)
+ {
+ void* const heapPtr = deMalloc((size_t)pAllocInfo->allocationSize);
+ if (!heapPtr)
+ throw std::bad_alloc();
+ return heapPtr;
+ }
+ else
+ return DE_NULL;
+}
+
+void freeHeap (void* ptr)
+{
+ deFree(ptr);
+}
+
+class DeviceMemory
+{
+public:
+ DeviceMemory (VkDevice, const VkMemoryAllocateInfo* pAllocInfo)
+ : m_memory(allocateHeap(pAllocInfo))
+ {
+ }
+ ~DeviceMemory (void)
+ {
+ freeHeap(m_memory);
+ }
+
+ void* getPtr (void) const { return m_memory; }
+
+private:
+ void* const m_memory;
+};
+
+class Buffer
+{
+public:
+ Buffer (VkDevice, const VkBufferCreateInfo* pCreateInfo)
+ : m_size(pCreateInfo->size)
+ {}
+
+ VkDeviceSize getSize (void) const { return m_size; }
+
+private:
+ const VkDeviceSize m_size;
+};
+
+class Image
+{
+public:
+ Image (VkDevice, const VkImageCreateInfo* pCreateInfo)
+ : m_imageType (pCreateInfo->imageType)
+ , m_format (pCreateInfo->format)
+ , m_extent (pCreateInfo->extent)
+ , m_samples (pCreateInfo->samples)
+ {}
+
+ VkImageType getImageType (void) const { return m_imageType; }
+ VkFormat getFormat (void) const { return m_format; }
+ VkExtent3D getExtent (void) const { return m_extent; }
+ VkSampleCountFlagBits getSamples (void) const { return m_samples; }
+
+private:
+ const VkImageType m_imageType;
+ const VkFormat m_format;
+ const VkExtent3D m_extent;
+ const VkSampleCountFlagBits m_samples;
+};
+
+class CommandBuffer
+{
+public:
+ CommandBuffer(VkDevice, VkCommandPool, VkCommandBufferLevel)
+ {}
+};
+
+class DescriptorSet
+{
+public:
+ DescriptorSet (VkDevice, VkDescriptorPool, VkDescriptorSetLayout) {}
+};
+
+class DescriptorPool
+{
+public:
+ DescriptorPool (VkDevice device, const VkDescriptorPoolCreateInfo* pCreateInfo)
+ : m_device (device)
+ , m_flags (pCreateInfo->flags)
+ {}
+ ~DescriptorPool (void)
+ {
+ reset();
+ }
+
+ VkDescriptorSet allocate (VkDescriptorSetLayout setLayout);
+ void free (VkDescriptorSet set);
+
+ void reset (void);
+
+private:
+ const VkDevice m_device;
+ const VkDescriptorPoolCreateFlags m_flags;
+
+ vector<DescriptorSet*> m_managedSets;
+};
+
+VkDescriptorSet DescriptorPool::allocate (VkDescriptorSetLayout setLayout)
+{
+ DescriptorSet* const impl = new DescriptorSet(m_device, VkDescriptorPool(reinterpret_cast<deUintptr>(this)), setLayout);
+
+ try
+ {
+ m_managedSets.push_back(impl);
+ }
+ catch (...)
+ {
+ delete impl;
+ throw;
+ }
+
+ return VkDescriptorSet(reinterpret_cast<deUintptr>(impl));
+}
+
+void DescriptorPool::free (VkDescriptorSet set)
+{
+ DescriptorSet* const impl = reinterpret_cast<DescriptorSet*>((deUintptr)set.getInternal());
+
+ DE_ASSERT(m_flags & VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT);
+
+ delete impl;
+
+ for (size_t ndx = 0; ndx < m_managedSets.size(); ++ndx)
+ {
+ if (m_managedSets[ndx] == impl)
+ {
+ std::swap(m_managedSets[ndx], m_managedSets.back());
+ m_managedSets.pop_back();
+ return;
+ }
+ }
+
+ DE_FATAL("VkDescriptorSet not owned by VkDescriptorPool");
+}
+
+void DescriptorPool::reset (void)
+{
+ for (size_t ndx = 0; ndx < m_managedSets.size(); ++ndx)
+ delete m_managedSets[ndx];
+ m_managedSets.clear();
+}
+
+extern "C"
+{
+
+PFN_vkVoidFunction getInstanceProcAddr (VkInstance instance, const char* pName)
+{
+ return reinterpret_cast<Instance*>(instance)->getProcAddr(pName);
+}
+
+PFN_vkVoidFunction getDeviceProcAddr (VkDevice device, const char* pName)
+{
+ return reinterpret_cast<Device*>(device)->getProcAddr(pName);
+}
+
+VkResult createGraphicsPipelines (VkDevice device, VkPipelineCache, deUint32 count, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks*, VkPipeline* pPipelines)
+{
+ for (deUint32 ndx = 0; ndx < count; ndx++)
+ pPipelines[ndx] = VkPipeline((deUint64)(deUintptr)new Pipeline(device, pCreateInfos+ndx));
+ return VK_SUCCESS;
+}
+
+VkResult createComputePipelines (VkDevice device, VkPipelineCache, deUint32 count, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks*, VkPipeline* pPipelines)
+{
+ for (deUint32 ndx = 0; ndx < count; ndx++)
+ pPipelines[ndx] = VkPipeline((deUint64)(deUintptr)new Pipeline(device, pCreateInfos+ndx));
+ return VK_SUCCESS;
+}
+
+VkResult enumeratePhysicalDevices (VkInstance, deUint32* pPhysicalDeviceCount, VkPhysicalDevice* pDevices)
+{
+ if (pDevices && *pPhysicalDeviceCount >= 1u)
+ *pDevices = reinterpret_cast<VkPhysicalDevice>((void*)(deUintptr)1u);
+
+ *pPhysicalDeviceCount = 1;
+
+ return VK_SUCCESS;
+}
+
+void getPhysicalDeviceProperties (VkPhysicalDevice, VkPhysicalDeviceProperties* props)
+{
+ deMemset(props, 0, sizeof(VkPhysicalDeviceProperties));
+
+ props->apiVersion = VK_API_VERSION;
+ props->driverVersion = 1u;
+ props->deviceType = VK_PHYSICAL_DEVICE_TYPE_OTHER;
+
+ deMemcpy(props->deviceName, "null", 5);
+
+ // \todo [2015-09-25 pyry] Fill in reasonable limits
+ props->limits.maxTexelBufferElements = 8096;
+}
+
+void getPhysicalDeviceQueueFamilyProperties (VkPhysicalDevice, deUint32* count, VkQueueFamilyProperties* props)
+{
+ if (props && *count >= 1u)
+ {
+ deMemset(props, 0, sizeof(VkQueueFamilyProperties));
+
+ props->queueCount = 1u;
+ props->queueFlags = VK_QUEUE_GRAPHICS_BIT|VK_QUEUE_COMPUTE_BIT;
+ props->timestampValidBits = 64;
+ }
+
+ *count = 1u;
+}
+
+void getPhysicalDeviceMemoryProperties (VkPhysicalDevice, VkPhysicalDeviceMemoryProperties* props)
+{
+ deMemset(props, 0, sizeof(VkPhysicalDeviceMemoryProperties));
+
+ props->memoryTypeCount = 1u;
+ props->memoryTypes[0].heapIndex = 0u;
+ props->memoryTypes[0].propertyFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
+
+ props->memoryHeapCount = 1u;
+ props->memoryHeaps[0].size = 1ull << 31;
+ props->memoryHeaps[0].flags = 0u;
+}
+
+void getPhysicalDeviceFormatProperties (VkPhysicalDevice, VkFormat, VkFormatProperties* pFormatProperties)
+{
+ const VkFormatFeatureFlags allFeatures = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT
+ | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT
+ | VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT
+ | VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT
+ | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT
+ | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT
+ | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT
+ | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT
+ | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT
+ | VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT
+ | VK_FORMAT_FEATURE_BLIT_SRC_BIT
+ | VK_FORMAT_FEATURE_BLIT_DST_BIT;
+
+ pFormatProperties->linearTilingFeatures = allFeatures;
+ pFormatProperties->optimalTilingFeatures = allFeatures;
+ pFormatProperties->bufferFeatures = allFeatures;
+}
+
+void getBufferMemoryRequirements (VkDevice, VkBuffer bufferHandle, VkMemoryRequirements* requirements)
+{
+ const Buffer* buffer = reinterpret_cast<const Buffer*>(bufferHandle.getInternal());
+
+ requirements->memoryTypeBits = 1u;
+ requirements->size = buffer->getSize();
+ requirements->alignment = (VkDeviceSize)1u;
+}
+
+VkDeviceSize getPackedImageDataSize (VkFormat format, VkExtent3D extent, VkSampleCountFlagBits samples)
+{
+ return (VkDeviceSize)getPixelSize(mapVkFormat(format))
+ * (VkDeviceSize)extent.width
+ * (VkDeviceSize)extent.height
+ * (VkDeviceSize)extent.depth
+ * (VkDeviceSize)samples;
+}
+
+void getImageMemoryRequirements (VkDevice, VkImage imageHandle, VkMemoryRequirements* requirements)
+{
+ const Image* image = reinterpret_cast<const Image*>(imageHandle.getInternal());
+
+ requirements->memoryTypeBits = 1u;
+ requirements->alignment = 4u;
+ requirements->size = getPackedImageDataSize(image->getFormat(), image->getExtent(), image->getSamples());
+}
+
+VkResult mapMemory (VkDevice, VkDeviceMemory memHandle, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData)
+{
+ const DeviceMemory* memory = reinterpret_cast<DeviceMemory*>(memHandle.getInternal());
+
+ DE_UNREF(size);
+ DE_UNREF(flags);
+
+ *ppData = (deUint8*)memory->getPtr() + offset;
+
+ return VK_SUCCESS;
+}
+
+VkResult allocateDescriptorSets (VkDevice, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets)
+{
+ DescriptorPool* const poolImpl = reinterpret_cast<DescriptorPool*>((deUintptr)pAllocateInfo->descriptorPool.getInternal());
+
+ for (deUint32 ndx = 0; ndx < pAllocateInfo->setLayoutCount; ++ndx)
+ {
+ try
+ {
+ pDescriptorSets[ndx] = poolImpl->allocate(pAllocateInfo->pSetLayouts[ndx]);
+ }
+ catch (const std::bad_alloc&)
+ {
+ for (deUint32 freeNdx = 0; freeNdx < ndx; freeNdx++)
+ delete reinterpret_cast<DescriptorSet*>((deUintptr)pDescriptorSets[freeNdx].getInternal());
+
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ catch (VkResult res)
+ {
+ for (deUint32 freeNdx = 0; freeNdx < ndx; freeNdx++)
+ delete reinterpret_cast<DescriptorSet*>((deUintptr)pDescriptorSets[freeNdx].getInternal());
+
+ return res;
+ }
+ }
+
+ return VK_SUCCESS;
+}
+
+void freeDescriptorSets (VkDevice, VkDescriptorPool descriptorPool, deUint32 count, const VkDescriptorSet* pDescriptorSets)
+{
+ DescriptorPool* const poolImpl = reinterpret_cast<DescriptorPool*>((deUintptr)descriptorPool.getInternal());
+
+ for (deUint32 ndx = 0; ndx < count; ++ndx)
+ poolImpl->free(pDescriptorSets[ndx]);
+}
+
+VkResult resetDescriptorPool (VkDevice, VkDescriptorPool descriptorPool, VkDescriptorPoolResetFlags)
+{
+ DescriptorPool* const poolImpl = reinterpret_cast<DescriptorPool*>((deUintptr)descriptorPool.getInternal());
+
+ poolImpl->reset();
+
+ return VK_SUCCESS;
+}
+
+VkResult allocateCommandBuffers (VkDevice device, const VkCommandBufferAllocateInfo* pAllocateInfo, VkCommandBuffer* pCommandBuffers)
+{
+ if (pAllocateInfo && pCommandBuffers)
+ {
+ for (deUint32 ndx = 0; ndx < pAllocateInfo->bufferCount; ++ndx)
+ {
+ pCommandBuffers[ndx] = reinterpret_cast<VkCommandBuffer>(new CommandBuffer(device, pAllocateInfo->commandPool, pAllocateInfo->level));
+ }
+ }
+
+ return VK_SUCCESS;
+}
+
+void freeCommandBuffers (VkDevice device, VkCommandPool commandPool, deUint32 commandBufferCount, const VkCommandBuffer* pCommandBuffers)
+{
+ DE_UNREF(device);
+ DE_UNREF(commandPool);
+
+ for (deUint32 ndx = 0; ndx < commandBufferCount; ++ndx)
+ delete reinterpret_cast<CommandBuffer*>(pCommandBuffers[ndx]);
+}
+
+#include "vkNullDriverImpl.inl"
+
+} // extern "C"
+
+Instance::Instance (const VkInstanceCreateInfo*)
+ : m_functions(s_instanceFunctions, DE_LENGTH_OF_ARRAY(s_instanceFunctions))
+{
+}
+
+Device::Device (VkPhysicalDevice, const VkDeviceCreateInfo*)
+ : m_functions(s_deviceFunctions, DE_LENGTH_OF_ARRAY(s_deviceFunctions))
+{
+}
+
+class NullDriverLibrary : public Library
+{
+public:
+ NullDriverLibrary (void)
+ : m_library (s_platformFunctions, DE_LENGTH_OF_ARRAY(s_platformFunctions))
+ , m_driver (m_library)
+ {}
+
+ const PlatformInterface& getPlatformInterface (void) const { return m_driver; }
+
+private:
+ const tcu::StaticFunctionLibrary m_library;
+ const PlatformDriver m_driver;
+};
+
+} // anonymous
+
+Library* createNullDriver (void)
+{
+ return new NullDriverLibrary();
+}
+
+} // vk
--- /dev/null
+#ifndef _VKNULLDRIVER_HPP
+#define _VKNULLDRIVER_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Null (dummy) Vulkan implementation.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkDefs.hpp"
+
+namespace vk
+{
+
+class Library;
+
+Library* createNullDriver (void);
+
+} // vk
+
+#endif // _VKNULLDRIVER_HPP
--- /dev/null
+/* WARNING: This is auto-generated file. Do not modify, since changes will
+ * be lost! Modify the generating script instead.
+ */
+VkResult createInstance (const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance)
+{
+ DE_UNREF(pAllocator);
+ VK_NULL_RETURN(*pInstance = reinterpret_cast<VkInstance>(new Instance(pCreateInfo)));
+}
+
+VkResult createDevice (VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice)
+{
+ DE_UNREF(pAllocator);
+ VK_NULL_RETURN(*pDevice = reinterpret_cast<VkDevice>(new Device(physicalDevice, pCreateInfo)));
+}
+
+VkResult allocateMemory (VkDevice device, const VkMemoryAllocateInfo* pAllocateInfo, const VkAllocationCallbacks* pAllocator, VkDeviceMemory* pMemory)
+{
+ DE_UNREF(pAllocator);
+ VK_NULL_RETURN(*pMemory = VkDeviceMemory((deUint64)(deUintptr)new DeviceMemory(device, pAllocateInfo)));
+}
+
+VkResult createFence (VkDevice device, const VkFenceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence)
+{
+ DE_UNREF(pAllocator);
+ VK_NULL_RETURN(*pFence = VkFence((deUint64)(deUintptr)new Fence(device, pCreateInfo)));
+}
+
+VkResult createSemaphore (VkDevice device, const VkSemaphoreCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSemaphore* pSemaphore)
+{
+ DE_UNREF(pAllocator);
+ VK_NULL_RETURN(*pSemaphore = VkSemaphore((deUint64)(deUintptr)new Semaphore(device, pCreateInfo)));
+}
+
+VkResult createEvent (VkDevice device, const VkEventCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkEvent* pEvent)
+{
+ DE_UNREF(pAllocator);
+ VK_NULL_RETURN(*pEvent = VkEvent((deUint64)(deUintptr)new Event(device, pCreateInfo)));
+}
+
+VkResult createQueryPool (VkDevice device, const VkQueryPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkQueryPool* pQueryPool)
+{
+ DE_UNREF(pAllocator);
+ VK_NULL_RETURN(*pQueryPool = VkQueryPool((deUint64)(deUintptr)new QueryPool(device, pCreateInfo)));
+}
+
+VkResult createBuffer (VkDevice device, const VkBufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBuffer* pBuffer)
+{
+ DE_UNREF(pAllocator);
+ VK_NULL_RETURN(*pBuffer = VkBuffer((deUint64)(deUintptr)new Buffer(device, pCreateInfo)));
+}
+
+VkResult createBufferView (VkDevice device, const VkBufferViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBufferView* pView)
+{
+ DE_UNREF(pAllocator);
+ VK_NULL_RETURN(*pView = VkBufferView((deUint64)(deUintptr)new BufferView(device, pCreateInfo)));
+}
+
+VkResult createImage (VkDevice device, const VkImageCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImage* pImage)
+{
+ DE_UNREF(pAllocator);
+ VK_NULL_RETURN(*pImage = VkImage((deUint64)(deUintptr)new Image(device, pCreateInfo)));
+}
+
+VkResult createImageView (VkDevice device, const VkImageViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImageView* pView)
+{
+ DE_UNREF(pAllocator);
+ VK_NULL_RETURN(*pView = VkImageView((deUint64)(deUintptr)new ImageView(device, pCreateInfo)));
+}
+
+VkResult createShaderModule (VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule)
+{
+ DE_UNREF(pAllocator);
+ VK_NULL_RETURN(*pShaderModule = VkShaderModule((deUint64)(deUintptr)new ShaderModule(device, pCreateInfo)));
+}
+
+VkResult createPipelineCache (VkDevice device, const VkPipelineCacheCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineCache* pPipelineCache)
+{
+ DE_UNREF(pAllocator);
+ VK_NULL_RETURN(*pPipelineCache = VkPipelineCache((deUint64)(deUintptr)new PipelineCache(device, pCreateInfo)));
+}
+
+VkResult createPipelineLayout (VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout)
+{
+ DE_UNREF(pAllocator);
+ VK_NULL_RETURN(*pPipelineLayout = VkPipelineLayout((deUint64)(deUintptr)new PipelineLayout(device, pCreateInfo)));
+}
+
+VkResult createSampler (VkDevice device, const VkSamplerCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSampler* pSampler)
+{
+ DE_UNREF(pAllocator);
+ VK_NULL_RETURN(*pSampler = VkSampler((deUint64)(deUintptr)new Sampler(device, pCreateInfo)));
+}
+
+VkResult createDescriptorSetLayout (VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorSetLayout* pSetLayout)
+{
+ DE_UNREF(pAllocator);
+ VK_NULL_RETURN(*pSetLayout = VkDescriptorSetLayout((deUint64)(deUintptr)new DescriptorSetLayout(device, pCreateInfo)));
+}
+
+VkResult createDescriptorPool (VkDevice device, const VkDescriptorPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorPool* pDescriptorPool)
+{
+ DE_UNREF(pAllocator);
+ VK_NULL_RETURN(*pDescriptorPool = VkDescriptorPool((deUint64)(deUintptr)new DescriptorPool(device, pCreateInfo)));
+}
+
+VkResult createFramebuffer (VkDevice device, const VkFramebufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkFramebuffer* pFramebuffer)
+{
+ DE_UNREF(pAllocator);
+ VK_NULL_RETURN(*pFramebuffer = VkFramebuffer((deUint64)(deUintptr)new Framebuffer(device, pCreateInfo)));
+}
+
+VkResult createRenderPass (VkDevice device, const VkRenderPassCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass)
+{
+ DE_UNREF(pAllocator);
+ VK_NULL_RETURN(*pRenderPass = VkRenderPass((deUint64)(deUintptr)new RenderPass(device, pCreateInfo)));
+}
+
+VkResult createCommandPool (VkDevice device, const VkCommandPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCommandPool* pCommandPool)
+{
+ DE_UNREF(pAllocator);
+ VK_NULL_RETURN(*pCommandPool = VkCommandPool((deUint64)(deUintptr)new CommandPool(device, pCreateInfo)));
+}
+
+void destroyInstance (VkInstance instance, const VkAllocationCallbacks* pAllocator)
+{
+ DE_UNREF(pAllocator);
+ delete reinterpret_cast<Instance*>(instance);
+}
+
+void destroyDevice (VkDevice device, const VkAllocationCallbacks* pAllocator)
+{
+ DE_UNREF(pAllocator);
+ delete reinterpret_cast<Device*>(device);
+}
+
+void freeMemory (VkDevice device, VkDeviceMemory memory, const VkAllocationCallbacks* pAllocator)
+{
+ DE_UNREF(device);
+ DE_UNREF(pAllocator);
+ delete reinterpret_cast<DeviceMemory*>((deUintptr)memory.getInternal());
+}
+
+void destroyFence (VkDevice device, VkFence fence, const VkAllocationCallbacks* pAllocator)
+{
+ DE_UNREF(device);
+ DE_UNREF(pAllocator);
+ delete reinterpret_cast<Fence*>((deUintptr)fence.getInternal());
+}
+
+void destroySemaphore (VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks* pAllocator)
+{
+ DE_UNREF(device);
+ DE_UNREF(pAllocator);
+ delete reinterpret_cast<Semaphore*>((deUintptr)semaphore.getInternal());
+}
+
+void destroyEvent (VkDevice device, VkEvent event, const VkAllocationCallbacks* pAllocator)
+{
+ DE_UNREF(device);
+ DE_UNREF(pAllocator);
+ delete reinterpret_cast<Event*>((deUintptr)event.getInternal());
+}
+
+void destroyQueryPool (VkDevice device, VkQueryPool queryPool, const VkAllocationCallbacks* pAllocator)
+{
+ DE_UNREF(device);
+ DE_UNREF(pAllocator);
+ delete reinterpret_cast<QueryPool*>((deUintptr)queryPool.getInternal());
+}
+
+void destroyBuffer (VkDevice device, VkBuffer buffer, const VkAllocationCallbacks* pAllocator)
+{
+ DE_UNREF(device);
+ DE_UNREF(pAllocator);
+ delete reinterpret_cast<Buffer*>((deUintptr)buffer.getInternal());
+}
+
+void destroyBufferView (VkDevice device, VkBufferView bufferView, const VkAllocationCallbacks* pAllocator)
+{
+ DE_UNREF(device);
+ DE_UNREF(pAllocator);
+ delete reinterpret_cast<BufferView*>((deUintptr)bufferView.getInternal());
+}
+
+void destroyImage (VkDevice device, VkImage image, const VkAllocationCallbacks* pAllocator)
+{
+ DE_UNREF(device);
+ DE_UNREF(pAllocator);
+ delete reinterpret_cast<Image*>((deUintptr)image.getInternal());
+}
+
+void destroyImageView (VkDevice device, VkImageView imageView, const VkAllocationCallbacks* pAllocator)
+{
+ DE_UNREF(device);
+ DE_UNREF(pAllocator);
+ delete reinterpret_cast<ImageView*>((deUintptr)imageView.getInternal());
+}
+
+void destroyShaderModule (VkDevice device, VkShaderModule shaderModule, const VkAllocationCallbacks* pAllocator)
+{
+ DE_UNREF(device);
+ DE_UNREF(pAllocator);
+ delete reinterpret_cast<ShaderModule*>((deUintptr)shaderModule.getInternal());
+}
+
+void destroyPipelineCache (VkDevice device, VkPipelineCache pipelineCache, const VkAllocationCallbacks* pAllocator)
+{
+ DE_UNREF(device);
+ DE_UNREF(pAllocator);
+ delete reinterpret_cast<PipelineCache*>((deUintptr)pipelineCache.getInternal());
+}
+
+void destroyPipeline (VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks* pAllocator)
+{
+ DE_UNREF(device);
+ DE_UNREF(pAllocator);
+ delete reinterpret_cast<Pipeline*>((deUintptr)pipeline.getInternal());
+}
+
+void destroyPipelineLayout (VkDevice device, VkPipelineLayout pipelineLayout, const VkAllocationCallbacks* pAllocator)
+{
+ DE_UNREF(device);
+ DE_UNREF(pAllocator);
+ delete reinterpret_cast<PipelineLayout*>((deUintptr)pipelineLayout.getInternal());
+}
+
+void destroySampler (VkDevice device, VkSampler sampler, const VkAllocationCallbacks* pAllocator)
+{
+ DE_UNREF(device);
+ DE_UNREF(pAllocator);
+ delete reinterpret_cast<Sampler*>((deUintptr)sampler.getInternal());
+}
+
+void destroyDescriptorSetLayout (VkDevice device, VkDescriptorSetLayout descriptorSetLayout, const VkAllocationCallbacks* pAllocator)
+{
+ DE_UNREF(device);
+ DE_UNREF(pAllocator);
+ delete reinterpret_cast<DescriptorSetLayout*>((deUintptr)descriptorSetLayout.getInternal());
+}
+
+void destroyDescriptorPool (VkDevice device, VkDescriptorPool descriptorPool, const VkAllocationCallbacks* pAllocator)
+{
+ DE_UNREF(device);
+ DE_UNREF(pAllocator);
+ delete reinterpret_cast<DescriptorPool*>((deUintptr)descriptorPool.getInternal());
+}
+
+void destroyFramebuffer (VkDevice device, VkFramebuffer framebuffer, const VkAllocationCallbacks* pAllocator)
+{
+ DE_UNREF(device);
+ DE_UNREF(pAllocator);
+ delete reinterpret_cast<Framebuffer*>((deUintptr)framebuffer.getInternal());
+}
+
+void destroyRenderPass (VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks* pAllocator)
+{
+ DE_UNREF(device);
+ DE_UNREF(pAllocator);
+ delete reinterpret_cast<RenderPass*>((deUintptr)renderPass.getInternal());
+}
+
+void destroyCommandPool (VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks* pAllocator)
+{
+ DE_UNREF(device);
+ DE_UNREF(pAllocator);
+ delete reinterpret_cast<CommandPool*>((deUintptr)commandPool.getInternal());
+}
+
+void getPhysicalDeviceFeatures (VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures* pFeatures)
+{
+ DE_UNREF(physicalDevice);
+ DE_UNREF(pFeatures);
+}
+
+VkResult getPhysicalDeviceImageFormatProperties (VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties* pImageFormatProperties)
+{
+ DE_UNREF(physicalDevice);
+ DE_UNREF(format);
+ DE_UNREF(type);
+ DE_UNREF(tiling);
+ DE_UNREF(usage);
+ DE_UNREF(flags);
+ DE_UNREF(pImageFormatProperties);
+ return VK_SUCCESS;
+}
+
+VkResult enumerateInstanceExtensionProperties (const char* pLayerName, deUint32* pPropertyCount, VkExtensionProperties* pProperties)
+{
+ DE_UNREF(pLayerName);
+ DE_UNREF(pPropertyCount);
+ DE_UNREF(pProperties);
+ return VK_SUCCESS;
+}
+
+VkResult enumerateDeviceExtensionProperties (VkPhysicalDevice physicalDevice, const char* pLayerName, deUint32* pPropertyCount, VkExtensionProperties* pProperties)
+{
+ DE_UNREF(physicalDevice);
+ DE_UNREF(pLayerName);
+ DE_UNREF(pPropertyCount);
+ DE_UNREF(pProperties);
+ return VK_SUCCESS;
+}
+
+VkResult enumerateInstanceLayerProperties (deUint32* pPropertyCount, VkLayerProperties* pProperties)
+{
+ DE_UNREF(pPropertyCount);
+ DE_UNREF(pProperties);
+ return VK_SUCCESS;
+}
+
+VkResult enumerateDeviceLayerProperties (VkPhysicalDevice physicalDevice, deUint32* pPropertyCount, VkLayerProperties* pProperties)
+{
+ DE_UNREF(physicalDevice);
+ DE_UNREF(pPropertyCount);
+ DE_UNREF(pProperties);
+ return VK_SUCCESS;
+}
+
+void getDeviceQueue (VkDevice device, deUint32 queueFamilyIndex, deUint32 queueIndex, VkQueue* pQueue)
+{
+ DE_UNREF(device);
+ DE_UNREF(queueFamilyIndex);
+ DE_UNREF(queueIndex);
+ DE_UNREF(pQueue);
+}
+
+VkResult queueSubmit (VkQueue queue, deUint32 submitCount, const VkSubmitInfo* pSubmits, VkFence fence)
+{
+ DE_UNREF(queue);
+ DE_UNREF(submitCount);
+ DE_UNREF(pSubmits);
+ DE_UNREF(fence);
+ return VK_SUCCESS;
+}
+
+VkResult queueWaitIdle (VkQueue queue)
+{
+ DE_UNREF(queue);
+ return VK_SUCCESS;
+}
+
+VkResult deviceWaitIdle (VkDevice device)
+{
+ DE_UNREF(device);
+ return VK_SUCCESS;
+}
+
+void unmapMemory (VkDevice device, VkDeviceMemory memory)
+{
+ DE_UNREF(device);
+ DE_UNREF(memory);
+}
+
+VkResult flushMappedMemoryRanges (VkDevice device, deUint32 memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges)
+{
+ DE_UNREF(device);
+ DE_UNREF(memoryRangeCount);
+ DE_UNREF(pMemoryRanges);
+ return VK_SUCCESS;
+}
+
+VkResult invalidateMappedMemoryRanges (VkDevice device, deUint32 memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges)
+{
+ DE_UNREF(device);
+ DE_UNREF(memoryRangeCount);
+ DE_UNREF(pMemoryRanges);
+ return VK_SUCCESS;
+}
+
+void getDeviceMemoryCommitment (VkDevice device, VkDeviceMemory memory, VkDeviceSize* pCommittedMemoryInBytes)
+{
+ DE_UNREF(device);
+ DE_UNREF(memory);
+ DE_UNREF(pCommittedMemoryInBytes);
+}
+
+VkResult bindBufferMemory (VkDevice device, VkBuffer buffer, VkDeviceMemory memory, VkDeviceSize memoryOffset)
+{
+ DE_UNREF(device);
+ DE_UNREF(buffer);
+ DE_UNREF(memory);
+ DE_UNREF(memoryOffset);
+ return VK_SUCCESS;
+}
+
+VkResult bindImageMemory (VkDevice device, VkImage image, VkDeviceMemory memory, VkDeviceSize memoryOffset)
+{
+ DE_UNREF(device);
+ DE_UNREF(image);
+ DE_UNREF(memory);
+ DE_UNREF(memoryOffset);
+ return VK_SUCCESS;
+}
+
+void getImageSparseMemoryRequirements (VkDevice device, VkImage image, deUint32* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements* pSparseMemoryRequirements)
+{
+ DE_UNREF(device);
+ DE_UNREF(image);
+ DE_UNREF(pSparseMemoryRequirementCount);
+ DE_UNREF(pSparseMemoryRequirements);
+}
+
+void getPhysicalDeviceSparseImageFormatProperties (VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling, deUint32* pPropertyCount, VkSparseImageFormatProperties* pProperties)
+{
+ DE_UNREF(physicalDevice);
+ DE_UNREF(format);
+ DE_UNREF(type);
+ DE_UNREF(samples);
+ DE_UNREF(usage);
+ DE_UNREF(tiling);
+ DE_UNREF(pPropertyCount);
+ DE_UNREF(pProperties);
+}
+
+VkResult queueBindSparse (VkQueue queue, deUint32 bindInfoCount, const VkBindSparseInfo* pBindInfo, VkFence fence)
+{
+ DE_UNREF(queue);
+ DE_UNREF(bindInfoCount);
+ DE_UNREF(pBindInfo);
+ DE_UNREF(fence);
+ return VK_SUCCESS;
+}
+
+VkResult resetFences (VkDevice device, deUint32 fenceCount, const VkFence* pFences)
+{
+ DE_UNREF(device);
+ DE_UNREF(fenceCount);
+ DE_UNREF(pFences);
+ return VK_SUCCESS;
+}
+
+VkResult getFenceStatus (VkDevice device, VkFence fence)
+{
+ DE_UNREF(device);
+ DE_UNREF(fence);
+ return VK_SUCCESS;
+}
+
+VkResult waitForFences (VkDevice device, deUint32 fenceCount, const VkFence* pFences, VkBool32 waitAll, deUint64 timeout)
+{
+ DE_UNREF(device);
+ DE_UNREF(fenceCount);
+ DE_UNREF(pFences);
+ DE_UNREF(waitAll);
+ DE_UNREF(timeout);
+ return VK_SUCCESS;
+}
+
+VkResult getEventStatus (VkDevice device, VkEvent event)
+{
+ DE_UNREF(device);
+ DE_UNREF(event);
+ return VK_SUCCESS;
+}
+
+VkResult setEvent (VkDevice device, VkEvent event)
+{
+ DE_UNREF(device);
+ DE_UNREF(event);
+ return VK_SUCCESS;
+}
+
+VkResult resetEvent (VkDevice device, VkEvent event)
+{
+ DE_UNREF(device);
+ DE_UNREF(event);
+ return VK_SUCCESS;
+}
+
+VkResult getQueryPoolResults (VkDevice device, VkQueryPool queryPool, deUint32 startQuery, deUint32 queryCount, deUintptr dataSize, void* pData, VkDeviceSize stride, VkQueryResultFlags flags)
+{
+ DE_UNREF(device);
+ DE_UNREF(queryPool);
+ DE_UNREF(startQuery);
+ DE_UNREF(queryCount);
+ DE_UNREF(dataSize);
+ DE_UNREF(pData);
+ DE_UNREF(stride);
+ DE_UNREF(flags);
+ return VK_SUCCESS;
+}
+
+void getImageSubresourceLayout (VkDevice device, VkImage image, const VkImageSubresource* pSubresource, VkSubresourceLayout* pLayout)
+{
+ DE_UNREF(device);
+ DE_UNREF(image);
+ DE_UNREF(pSubresource);
+ DE_UNREF(pLayout);
+}
+
+VkResult getPipelineCacheData (VkDevice device, VkPipelineCache pipelineCache, deUintptr* pDataSize, void* pData)
+{
+ DE_UNREF(device);
+ DE_UNREF(pipelineCache);
+ DE_UNREF(pDataSize);
+ DE_UNREF(pData);
+ return VK_SUCCESS;
+}
+
+VkResult mergePipelineCaches (VkDevice device, VkPipelineCache dstCache, deUint32 srcCacheCount, const VkPipelineCache* pSrcCaches)
+{
+ DE_UNREF(device);
+ DE_UNREF(dstCache);
+ DE_UNREF(srcCacheCount);
+ DE_UNREF(pSrcCaches);
+ return VK_SUCCESS;
+}
+
+void updateDescriptorSets (VkDevice device, deUint32 descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites, deUint32 descriptorCopyCount, const VkCopyDescriptorSet* pDescriptorCopies)
+{
+ DE_UNREF(device);
+ DE_UNREF(descriptorWriteCount);
+ DE_UNREF(pDescriptorWrites);
+ DE_UNREF(descriptorCopyCount);
+ DE_UNREF(pDescriptorCopies);
+}
+
+void getRenderAreaGranularity (VkDevice device, VkRenderPass renderPass, VkExtent2D* pGranularity)
+{
+ DE_UNREF(device);
+ DE_UNREF(renderPass);
+ DE_UNREF(pGranularity);
+}
+
+VkResult resetCommandPool (VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags)
+{
+ DE_UNREF(device);
+ DE_UNREF(commandPool);
+ DE_UNREF(flags);
+ return VK_SUCCESS;
+}
+
+VkResult beginCommandBuffer (VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo* pBeginInfo)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(pBeginInfo);
+ return VK_SUCCESS;
+}
+
+VkResult endCommandBuffer (VkCommandBuffer commandBuffer)
+{
+ DE_UNREF(commandBuffer);
+ return VK_SUCCESS;
+}
+
+VkResult resetCommandBuffer (VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(flags);
+ return VK_SUCCESS;
+}
+
+void cmdBindPipeline (VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(pipelineBindPoint);
+ DE_UNREF(pipeline);
+}
+
+void cmdSetViewport (VkCommandBuffer commandBuffer, deUint32 viewportCount, const VkViewport* pViewports)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(viewportCount);
+ DE_UNREF(pViewports);
+}
+
+void cmdSetScissor (VkCommandBuffer commandBuffer, deUint32 scissorCount, const VkRect2D* pScissors)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(scissorCount);
+ DE_UNREF(pScissors);
+}
+
+void cmdSetLineWidth (VkCommandBuffer commandBuffer, float lineWidth)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(lineWidth);
+}
+
+void cmdSetDepthBias (VkCommandBuffer commandBuffer, float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(depthBiasConstantFactor);
+ DE_UNREF(depthBiasClamp);
+ DE_UNREF(depthBiasSlopeFactor);
+}
+
+void cmdSetBlendConstants (VkCommandBuffer commandBuffer, const float blendConstants[4])
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(blendConstants);
+}
+
+void cmdSetDepthBounds (VkCommandBuffer commandBuffer, float minDepthBounds, float maxDepthBounds)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(minDepthBounds);
+ DE_UNREF(maxDepthBounds);
+}
+
+void cmdSetStencilCompareMask (VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, deUint32 compareMask)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(faceMask);
+ DE_UNREF(compareMask);
+}
+
+void cmdSetStencilWriteMask (VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, deUint32 writeMask)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(faceMask);
+ DE_UNREF(writeMask);
+}
+
+void cmdSetStencilReference (VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, deUint32 reference)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(faceMask);
+ DE_UNREF(reference);
+}
+
+void cmdBindDescriptorSets (VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, deUint32 firstSet, deUint32 descriptorSetCount, const VkDescriptorSet* pDescriptorSets, deUint32 dynamicOffsetCount, const deUint32* pDynamicOffsets)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(pipelineBindPoint);
+ DE_UNREF(layout);
+ DE_UNREF(firstSet);
+ DE_UNREF(descriptorSetCount);
+ DE_UNREF(pDescriptorSets);
+ DE_UNREF(dynamicOffsetCount);
+ DE_UNREF(pDynamicOffsets);
+}
+
+void cmdBindIndexBuffer (VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(buffer);
+ DE_UNREF(offset);
+ DE_UNREF(indexType);
+}
+
+void cmdBindVertexBuffers (VkCommandBuffer commandBuffer, deUint32 startBinding, deUint32 bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(startBinding);
+ DE_UNREF(bindingCount);
+ DE_UNREF(pBuffers);
+ DE_UNREF(pOffsets);
+}
+
+void cmdDraw (VkCommandBuffer commandBuffer, deUint32 vertexCount, deUint32 instanceCount, deUint32 firstVertex, deUint32 firstInstance)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(vertexCount);
+ DE_UNREF(instanceCount);
+ DE_UNREF(firstVertex);
+ DE_UNREF(firstInstance);
+}
+
+void cmdDrawIndexed (VkCommandBuffer commandBuffer, deUint32 indexCount, deUint32 instanceCount, deUint32 firstIndex, deInt32 vertexOffset, deUint32 firstInstance)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(indexCount);
+ DE_UNREF(instanceCount);
+ DE_UNREF(firstIndex);
+ DE_UNREF(vertexOffset);
+ DE_UNREF(firstInstance);
+}
+
+void cmdDrawIndirect (VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, deUint32 drawCount, deUint32 stride)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(buffer);
+ DE_UNREF(offset);
+ DE_UNREF(drawCount);
+ DE_UNREF(stride);
+}
+
+void cmdDrawIndexedIndirect (VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, deUint32 drawCount, deUint32 stride)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(buffer);
+ DE_UNREF(offset);
+ DE_UNREF(drawCount);
+ DE_UNREF(stride);
+}
+
+void cmdDispatch (VkCommandBuffer commandBuffer, deUint32 x, deUint32 y, deUint32 z)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(x);
+ DE_UNREF(y);
+ DE_UNREF(z);
+}
+
+void cmdDispatchIndirect (VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(buffer);
+ DE_UNREF(offset);
+}
+
+void cmdCopyBuffer (VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, deUint32 regionCount, const VkBufferCopy* pRegions)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(srcBuffer);
+ DE_UNREF(dstBuffer);
+ DE_UNREF(regionCount);
+ DE_UNREF(pRegions);
+}
+
+void cmdCopyImage (VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, deUint32 regionCount, const VkImageCopy* pRegions)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(srcImage);
+ DE_UNREF(srcImageLayout);
+ DE_UNREF(dstImage);
+ DE_UNREF(dstImageLayout);
+ DE_UNREF(regionCount);
+ DE_UNREF(pRegions);
+}
+
+void cmdBlitImage (VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, deUint32 regionCount, const VkImageBlit* pRegions, VkFilter filter)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(srcImage);
+ DE_UNREF(srcImageLayout);
+ DE_UNREF(dstImage);
+ DE_UNREF(dstImageLayout);
+ DE_UNREF(regionCount);
+ DE_UNREF(pRegions);
+ DE_UNREF(filter);
+}
+
+void cmdCopyBufferToImage (VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage, VkImageLayout dstImageLayout, deUint32 regionCount, const VkBufferImageCopy* pRegions)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(srcBuffer);
+ DE_UNREF(dstImage);
+ DE_UNREF(dstImageLayout);
+ DE_UNREF(regionCount);
+ DE_UNREF(pRegions);
+}
+
+void cmdCopyImageToBuffer (VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkBuffer dstBuffer, deUint32 regionCount, const VkBufferImageCopy* pRegions)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(srcImage);
+ DE_UNREF(srcImageLayout);
+ DE_UNREF(dstBuffer);
+ DE_UNREF(regionCount);
+ DE_UNREF(pRegions);
+}
+
+void cmdUpdateBuffer (VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const deUint32* pData)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(dstBuffer);
+ DE_UNREF(dstOffset);
+ DE_UNREF(dataSize);
+ DE_UNREF(pData);
+}
+
+void cmdFillBuffer (VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, deUint32 data)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(dstBuffer);
+ DE_UNREF(dstOffset);
+ DE_UNREF(size);
+ DE_UNREF(data);
+}
+
+void cmdClearColorImage (VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearColorValue* pColor, deUint32 rangeCount, const VkImageSubresourceRange* pRanges)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(image);
+ DE_UNREF(imageLayout);
+ DE_UNREF(pColor);
+ DE_UNREF(rangeCount);
+ DE_UNREF(pRanges);
+}
+
+void cmdClearDepthStencilImage (VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearDepthStencilValue* pDepthStencil, deUint32 rangeCount, const VkImageSubresourceRange* pRanges)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(image);
+ DE_UNREF(imageLayout);
+ DE_UNREF(pDepthStencil);
+ DE_UNREF(rangeCount);
+ DE_UNREF(pRanges);
+}
+
+void cmdClearAttachments (VkCommandBuffer commandBuffer, deUint32 attachmentCount, const VkClearAttachment* pAttachments, deUint32 rectCount, const VkClearRect* pRects)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(attachmentCount);
+ DE_UNREF(pAttachments);
+ DE_UNREF(rectCount);
+ DE_UNREF(pRects);
+}
+
+void cmdResolveImage (VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, deUint32 regionCount, const VkImageResolve* pRegions)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(srcImage);
+ DE_UNREF(srcImageLayout);
+ DE_UNREF(dstImage);
+ DE_UNREF(dstImageLayout);
+ DE_UNREF(regionCount);
+ DE_UNREF(pRegions);
+}
+
+void cmdSetEvent (VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(event);
+ DE_UNREF(stageMask);
+}
+
+void cmdResetEvent (VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(event);
+ DE_UNREF(stageMask);
+}
+
+void cmdWaitEvents (VkCommandBuffer commandBuffer, deUint32 eventCount, const VkEvent* pEvents, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, deUint32 memoryBarrierCount, const void* const* ppMemoryBarriers)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(eventCount);
+ DE_UNREF(pEvents);
+ DE_UNREF(srcStageMask);
+ DE_UNREF(dstStageMask);
+ DE_UNREF(memoryBarrierCount);
+ DE_UNREF(ppMemoryBarriers);
+}
+
+void cmdPipelineBarrier (VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, deUint32 memoryBarrierCount, const void* const* ppMemoryBarriers)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(srcStageMask);
+ DE_UNREF(dstStageMask);
+ DE_UNREF(dependencyFlags);
+ DE_UNREF(memoryBarrierCount);
+ DE_UNREF(ppMemoryBarriers);
+}
+
+void cmdBeginQuery (VkCommandBuffer commandBuffer, VkQueryPool queryPool, deUint32 entry, VkQueryControlFlags flags)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(queryPool);
+ DE_UNREF(entry);
+ DE_UNREF(flags);
+}
+
+void cmdEndQuery (VkCommandBuffer commandBuffer, VkQueryPool queryPool, deUint32 entry)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(queryPool);
+ DE_UNREF(entry);
+}
+
+void cmdResetQueryPool (VkCommandBuffer commandBuffer, VkQueryPool queryPool, deUint32 startQuery, deUint32 queryCount)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(queryPool);
+ DE_UNREF(startQuery);
+ DE_UNREF(queryCount);
+}
+
+void cmdWriteTimestamp (VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkQueryPool queryPool, deUint32 entry)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(pipelineStage);
+ DE_UNREF(queryPool);
+ DE_UNREF(entry);
+}
+
+void cmdCopyQueryPoolResults (VkCommandBuffer commandBuffer, VkQueryPool queryPool, deUint32 startQuery, deUint32 queryCount, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(queryPool);
+ DE_UNREF(startQuery);
+ DE_UNREF(queryCount);
+ DE_UNREF(dstBuffer);
+ DE_UNREF(dstOffset);
+ DE_UNREF(stride);
+ DE_UNREF(flags);
+}
+
+void cmdPushConstants (VkCommandBuffer commandBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, deUint32 offset, deUint32 size, const void* pValues)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(layout);
+ DE_UNREF(stageFlags);
+ DE_UNREF(offset);
+ DE_UNREF(size);
+ DE_UNREF(pValues);
+}
+
+void cmdBeginRenderPass (VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, VkSubpassContents contents)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(pRenderPassBegin);
+ DE_UNREF(contents);
+}
+
+void cmdNextSubpass (VkCommandBuffer commandBuffer, VkSubpassContents contents)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(contents);
+}
+
+void cmdEndRenderPass (VkCommandBuffer commandBuffer)
+{
+ DE_UNREF(commandBuffer);
+}
+
+void cmdExecuteCommands (VkCommandBuffer commandBuffer, deUint32 commandBuffersCount, const VkCommandBuffer* pCommandBuffers)
+{
+ DE_UNREF(commandBuffer);
+ DE_UNREF(commandBuffersCount);
+ DE_UNREF(pCommandBuffers);
+}
+
+static const tcu::StaticFunctionLibrary::Entry s_platformFunctions[] =
+{
+ VK_NULL_FUNC_ENTRY(vkCreateInstance, createInstance),
+ VK_NULL_FUNC_ENTRY(vkGetInstanceProcAddr, getInstanceProcAddr),
+ VK_NULL_FUNC_ENTRY(vkEnumerateInstanceExtensionProperties, enumerateInstanceExtensionProperties),
+ VK_NULL_FUNC_ENTRY(vkEnumerateInstanceLayerProperties, enumerateInstanceLayerProperties),
+};
+
+static const tcu::StaticFunctionLibrary::Entry s_instanceFunctions[] =
+{
+ VK_NULL_FUNC_ENTRY(vkDestroyInstance, destroyInstance),
+ VK_NULL_FUNC_ENTRY(vkEnumeratePhysicalDevices, enumeratePhysicalDevices),
+ VK_NULL_FUNC_ENTRY(vkGetPhysicalDeviceFeatures, getPhysicalDeviceFeatures),
+ VK_NULL_FUNC_ENTRY(vkGetPhysicalDeviceFormatProperties, getPhysicalDeviceFormatProperties),
+ VK_NULL_FUNC_ENTRY(vkGetPhysicalDeviceImageFormatProperties, getPhysicalDeviceImageFormatProperties),
+ VK_NULL_FUNC_ENTRY(vkGetPhysicalDeviceProperties, getPhysicalDeviceProperties),
+ VK_NULL_FUNC_ENTRY(vkGetPhysicalDeviceQueueFamilyProperties, getPhysicalDeviceQueueFamilyProperties),
+ VK_NULL_FUNC_ENTRY(vkGetPhysicalDeviceMemoryProperties, getPhysicalDeviceMemoryProperties),
+ VK_NULL_FUNC_ENTRY(vkGetDeviceProcAddr, getDeviceProcAddr),
+ VK_NULL_FUNC_ENTRY(vkCreateDevice, createDevice),
+ VK_NULL_FUNC_ENTRY(vkEnumerateDeviceExtensionProperties, enumerateDeviceExtensionProperties),
+ VK_NULL_FUNC_ENTRY(vkEnumerateDeviceLayerProperties, enumerateDeviceLayerProperties),
+};
+
+static const tcu::StaticFunctionLibrary::Entry s_deviceFunctions[] =
+{
+ VK_NULL_FUNC_ENTRY(vkDestroyDevice, destroyDevice),
+ VK_NULL_FUNC_ENTRY(vkGetDeviceQueue, getDeviceQueue),
+ VK_NULL_FUNC_ENTRY(vkQueueSubmit, queueSubmit),
+ VK_NULL_FUNC_ENTRY(vkQueueWaitIdle, queueWaitIdle),
+ VK_NULL_FUNC_ENTRY(vkDeviceWaitIdle, deviceWaitIdle),
+ VK_NULL_FUNC_ENTRY(vkAllocateMemory, allocateMemory),
+ VK_NULL_FUNC_ENTRY(vkFreeMemory, freeMemory),
+ VK_NULL_FUNC_ENTRY(vkMapMemory, mapMemory),
+ VK_NULL_FUNC_ENTRY(vkUnmapMemory, unmapMemory),
+ VK_NULL_FUNC_ENTRY(vkFlushMappedMemoryRanges, flushMappedMemoryRanges),
+ VK_NULL_FUNC_ENTRY(vkInvalidateMappedMemoryRanges, invalidateMappedMemoryRanges),
+ VK_NULL_FUNC_ENTRY(vkGetDeviceMemoryCommitment, getDeviceMemoryCommitment),
+ VK_NULL_FUNC_ENTRY(vkBindBufferMemory, bindBufferMemory),
+ VK_NULL_FUNC_ENTRY(vkBindImageMemory, bindImageMemory),
+ VK_NULL_FUNC_ENTRY(vkGetBufferMemoryRequirements, getBufferMemoryRequirements),
+ VK_NULL_FUNC_ENTRY(vkGetImageMemoryRequirements, getImageMemoryRequirements),
+ VK_NULL_FUNC_ENTRY(vkGetImageSparseMemoryRequirements, getImageSparseMemoryRequirements),
+ VK_NULL_FUNC_ENTRY(vkGetPhysicalDeviceSparseImageFormatProperties, getPhysicalDeviceSparseImageFormatProperties),
+ VK_NULL_FUNC_ENTRY(vkQueueBindSparse, queueBindSparse),
+ VK_NULL_FUNC_ENTRY(vkCreateFence, createFence),
+ VK_NULL_FUNC_ENTRY(vkDestroyFence, destroyFence),
+ VK_NULL_FUNC_ENTRY(vkResetFences, resetFences),
+ VK_NULL_FUNC_ENTRY(vkGetFenceStatus, getFenceStatus),
+ VK_NULL_FUNC_ENTRY(vkWaitForFences, waitForFences),
+ VK_NULL_FUNC_ENTRY(vkCreateSemaphore, createSemaphore),
+ VK_NULL_FUNC_ENTRY(vkDestroySemaphore, destroySemaphore),
+ VK_NULL_FUNC_ENTRY(vkCreateEvent, createEvent),
+ VK_NULL_FUNC_ENTRY(vkDestroyEvent, destroyEvent),
+ VK_NULL_FUNC_ENTRY(vkGetEventStatus, getEventStatus),
+ VK_NULL_FUNC_ENTRY(vkSetEvent, setEvent),
+ VK_NULL_FUNC_ENTRY(vkResetEvent, resetEvent),
+ VK_NULL_FUNC_ENTRY(vkCreateQueryPool, createQueryPool),
+ VK_NULL_FUNC_ENTRY(vkDestroyQueryPool, destroyQueryPool),
+ VK_NULL_FUNC_ENTRY(vkGetQueryPoolResults, getQueryPoolResults),
+ VK_NULL_FUNC_ENTRY(vkCreateBuffer, createBuffer),
+ VK_NULL_FUNC_ENTRY(vkDestroyBuffer, destroyBuffer),
+ VK_NULL_FUNC_ENTRY(vkCreateBufferView, createBufferView),
+ VK_NULL_FUNC_ENTRY(vkDestroyBufferView, destroyBufferView),
+ VK_NULL_FUNC_ENTRY(vkCreateImage, createImage),
+ VK_NULL_FUNC_ENTRY(vkDestroyImage, destroyImage),
+ VK_NULL_FUNC_ENTRY(vkGetImageSubresourceLayout, getImageSubresourceLayout),
+ VK_NULL_FUNC_ENTRY(vkCreateImageView, createImageView),
+ VK_NULL_FUNC_ENTRY(vkDestroyImageView, destroyImageView),
+ VK_NULL_FUNC_ENTRY(vkCreateShaderModule, createShaderModule),
+ VK_NULL_FUNC_ENTRY(vkDestroyShaderModule, destroyShaderModule),
+ VK_NULL_FUNC_ENTRY(vkCreatePipelineCache, createPipelineCache),
+ VK_NULL_FUNC_ENTRY(vkDestroyPipelineCache, destroyPipelineCache),
+ VK_NULL_FUNC_ENTRY(vkGetPipelineCacheData, getPipelineCacheData),
+ VK_NULL_FUNC_ENTRY(vkMergePipelineCaches, mergePipelineCaches),
+ VK_NULL_FUNC_ENTRY(vkCreateGraphicsPipelines, createGraphicsPipelines),
+ VK_NULL_FUNC_ENTRY(vkCreateComputePipelines, createComputePipelines),
+ VK_NULL_FUNC_ENTRY(vkDestroyPipeline, destroyPipeline),
+ VK_NULL_FUNC_ENTRY(vkCreatePipelineLayout, createPipelineLayout),
+ VK_NULL_FUNC_ENTRY(vkDestroyPipelineLayout, destroyPipelineLayout),
+ VK_NULL_FUNC_ENTRY(vkCreateSampler, createSampler),
+ VK_NULL_FUNC_ENTRY(vkDestroySampler, destroySampler),
+ VK_NULL_FUNC_ENTRY(vkCreateDescriptorSetLayout, createDescriptorSetLayout),
+ VK_NULL_FUNC_ENTRY(vkDestroyDescriptorSetLayout, destroyDescriptorSetLayout),
+ VK_NULL_FUNC_ENTRY(vkCreateDescriptorPool, createDescriptorPool),
+ VK_NULL_FUNC_ENTRY(vkDestroyDescriptorPool, destroyDescriptorPool),
+ VK_NULL_FUNC_ENTRY(vkResetDescriptorPool, resetDescriptorPool),
+ VK_NULL_FUNC_ENTRY(vkAllocateDescriptorSets, allocateDescriptorSets),
+ VK_NULL_FUNC_ENTRY(vkFreeDescriptorSets, freeDescriptorSets),
+ VK_NULL_FUNC_ENTRY(vkUpdateDescriptorSets, updateDescriptorSets),
+ VK_NULL_FUNC_ENTRY(vkCreateFramebuffer, createFramebuffer),
+ VK_NULL_FUNC_ENTRY(vkDestroyFramebuffer, destroyFramebuffer),
+ VK_NULL_FUNC_ENTRY(vkCreateRenderPass, createRenderPass),
+ VK_NULL_FUNC_ENTRY(vkDestroyRenderPass, destroyRenderPass),
+ VK_NULL_FUNC_ENTRY(vkGetRenderAreaGranularity, getRenderAreaGranularity),
+ VK_NULL_FUNC_ENTRY(vkCreateCommandPool, createCommandPool),
+ VK_NULL_FUNC_ENTRY(vkDestroyCommandPool, destroyCommandPool),
+ VK_NULL_FUNC_ENTRY(vkResetCommandPool, resetCommandPool),
+ VK_NULL_FUNC_ENTRY(vkAllocateCommandBuffers, allocateCommandBuffers),
+ VK_NULL_FUNC_ENTRY(vkFreeCommandBuffers, freeCommandBuffers),
+ VK_NULL_FUNC_ENTRY(vkBeginCommandBuffer, beginCommandBuffer),
+ VK_NULL_FUNC_ENTRY(vkEndCommandBuffer, endCommandBuffer),
+ VK_NULL_FUNC_ENTRY(vkResetCommandBuffer, resetCommandBuffer),
+ VK_NULL_FUNC_ENTRY(vkCmdBindPipeline, cmdBindPipeline),
+ VK_NULL_FUNC_ENTRY(vkCmdSetViewport, cmdSetViewport),
+ VK_NULL_FUNC_ENTRY(vkCmdSetScissor, cmdSetScissor),
+ VK_NULL_FUNC_ENTRY(vkCmdSetLineWidth, cmdSetLineWidth),
+ VK_NULL_FUNC_ENTRY(vkCmdSetDepthBias, cmdSetDepthBias),
+ VK_NULL_FUNC_ENTRY(vkCmdSetBlendConstants, cmdSetBlendConstants),
+ VK_NULL_FUNC_ENTRY(vkCmdSetDepthBounds, cmdSetDepthBounds),
+ VK_NULL_FUNC_ENTRY(vkCmdSetStencilCompareMask, cmdSetStencilCompareMask),
+ VK_NULL_FUNC_ENTRY(vkCmdSetStencilWriteMask, cmdSetStencilWriteMask),
+ VK_NULL_FUNC_ENTRY(vkCmdSetStencilReference, cmdSetStencilReference),
+ VK_NULL_FUNC_ENTRY(vkCmdBindDescriptorSets, cmdBindDescriptorSets),
+ VK_NULL_FUNC_ENTRY(vkCmdBindIndexBuffer, cmdBindIndexBuffer),
+ VK_NULL_FUNC_ENTRY(vkCmdBindVertexBuffers, cmdBindVertexBuffers),
+ VK_NULL_FUNC_ENTRY(vkCmdDraw, cmdDraw),
+ VK_NULL_FUNC_ENTRY(vkCmdDrawIndexed, cmdDrawIndexed),
+ VK_NULL_FUNC_ENTRY(vkCmdDrawIndirect, cmdDrawIndirect),
+ VK_NULL_FUNC_ENTRY(vkCmdDrawIndexedIndirect, cmdDrawIndexedIndirect),
+ VK_NULL_FUNC_ENTRY(vkCmdDispatch, cmdDispatch),
+ VK_NULL_FUNC_ENTRY(vkCmdDispatchIndirect, cmdDispatchIndirect),
+ VK_NULL_FUNC_ENTRY(vkCmdCopyBuffer, cmdCopyBuffer),
+ VK_NULL_FUNC_ENTRY(vkCmdCopyImage, cmdCopyImage),
+ VK_NULL_FUNC_ENTRY(vkCmdBlitImage, cmdBlitImage),
+ VK_NULL_FUNC_ENTRY(vkCmdCopyBufferToImage, cmdCopyBufferToImage),
+ VK_NULL_FUNC_ENTRY(vkCmdCopyImageToBuffer, cmdCopyImageToBuffer),
+ VK_NULL_FUNC_ENTRY(vkCmdUpdateBuffer, cmdUpdateBuffer),
+ VK_NULL_FUNC_ENTRY(vkCmdFillBuffer, cmdFillBuffer),
+ VK_NULL_FUNC_ENTRY(vkCmdClearColorImage, cmdClearColorImage),
+ VK_NULL_FUNC_ENTRY(vkCmdClearDepthStencilImage, cmdClearDepthStencilImage),
+ VK_NULL_FUNC_ENTRY(vkCmdClearAttachments, cmdClearAttachments),
+ VK_NULL_FUNC_ENTRY(vkCmdResolveImage, cmdResolveImage),
+ VK_NULL_FUNC_ENTRY(vkCmdSetEvent, cmdSetEvent),
+ VK_NULL_FUNC_ENTRY(vkCmdResetEvent, cmdResetEvent),
+ VK_NULL_FUNC_ENTRY(vkCmdWaitEvents, cmdWaitEvents),
+ VK_NULL_FUNC_ENTRY(vkCmdPipelineBarrier, cmdPipelineBarrier),
+ VK_NULL_FUNC_ENTRY(vkCmdBeginQuery, cmdBeginQuery),
+ VK_NULL_FUNC_ENTRY(vkCmdEndQuery, cmdEndQuery),
+ VK_NULL_FUNC_ENTRY(vkCmdResetQueryPool, cmdResetQueryPool),
+ VK_NULL_FUNC_ENTRY(vkCmdWriteTimestamp, cmdWriteTimestamp),
+ VK_NULL_FUNC_ENTRY(vkCmdCopyQueryPoolResults, cmdCopyQueryPoolResults),
+ VK_NULL_FUNC_ENTRY(vkCmdPushConstants, cmdPushConstants),
+ VK_NULL_FUNC_ENTRY(vkCmdBeginRenderPass, cmdBeginRenderPass),
+ VK_NULL_FUNC_ENTRY(vkCmdNextSubpass, cmdNextSubpass),
+ VK_NULL_FUNC_ENTRY(vkCmdEndRenderPass, cmdEndRenderPass),
+ VK_NULL_FUNC_ENTRY(vkCmdExecuteCommands, cmdExecuteCommands),
+};
+
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Vulkan platform abstraction.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkPlatform.hpp"
+#include "tcuFunctionLibrary.hpp"
+
+namespace vk
+{
+
+PlatformDriver::PlatformDriver (const tcu::FunctionLibrary& library)
+{
+#define GET_PROC_ADDR(NAME) library.getFunction(NAME)
+#include "vkInitPlatformFunctionPointers.inl"
+#undef GET_PROC_ADDR
+}
+
+PlatformDriver::~PlatformDriver (void)
+{
+}
+
+InstanceDriver::InstanceDriver (const PlatformInterface& platformInterface, VkInstance instance)
+{
+#define GET_PROC_ADDR(NAME) platformInterface.getInstanceProcAddr(instance, NAME)
+#include "vkInitInstanceFunctionPointers.inl"
+#undef GET_PROC_ADDR
+}
+
+InstanceDriver::~InstanceDriver (void)
+{
+}
+
+DeviceDriver::DeviceDriver (const InstanceInterface& instanceInterface, VkDevice device)
+{
+#define GET_PROC_ADDR(NAME) instanceInterface.getDeviceProcAddr(device, NAME)
+#include "vkInitDeviceFunctionPointers.inl"
+#undef GET_PROC_ADDR
+}
+
+DeviceDriver::~DeviceDriver (void)
+{
+}
+
+#include "vkPlatformDriverImpl.inl"
+#include "vkInstanceDriverImpl.inl"
+#include "vkDeviceDriverImpl.inl"
+
+} // vk
--- /dev/null
+#ifndef _VKPLATFORM_HPP
+#define _VKPLATFORM_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Vulkan platform abstraction.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkDefs.hpp"
+
+namespace tcu
+{
+class FunctionLibrary;
+}
+
+namespace vk
+{
+
+class Library
+{
+public:
+ Library (void) {}
+ virtual ~Library (void) {}
+
+ virtual const PlatformInterface& getPlatformInterface (void) const = 0;
+};
+
+class PlatformDriver : public PlatformInterface
+{
+public:
+ PlatformDriver (const tcu::FunctionLibrary& library);
+ ~PlatformDriver (void);
+
+#include "vkConcretePlatformInterface.inl"
+
+protected:
+ struct Functions
+ {
+#include "vkPlatformFunctionPointers.inl"
+ };
+
+ Functions m_vk;
+};
+
+class InstanceDriver : public InstanceInterface
+{
+public:
+ InstanceDriver (const PlatformInterface& platformInterface, VkInstance instance);
+ ~InstanceDriver (void);
+
+#include "vkConcreteInstanceInterface.inl"
+
+protected:
+ struct Functions
+ {
+#include "vkInstanceFunctionPointers.inl"
+ };
+
+ Functions m_vk;
+};
+
+class DeviceDriver : public DeviceInterface
+{
+public:
+ DeviceDriver (const InstanceInterface& instanceInterface, VkDevice device);
+ ~DeviceDriver (void);
+
+#include "vkConcreteDeviceInterface.inl"
+
+protected:
+ struct Functions
+ {
+#include "vkDeviceFunctionPointers.inl"
+ };
+
+ Functions m_vk;
+};
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Vulkan platform interface
+ *//*--------------------------------------------------------------------*/
+class Platform
+{
+public:
+ Platform (void) {}
+ ~Platform (void) {}
+
+ // \todo [2015-01-05 pyry] Parametrize this to select for example debug library / interface?
+ virtual Library* createLibrary (void) const = 0;
+};
+
+} // vk
+
+#endif // _VKPLATFORM_HPP
--- /dev/null
+/* WARNING: This is auto-generated file. Do not modify, since changes will
+ * be lost! Modify the generating script instead.
+ */
+
+VkResult PlatformDriver::createInstance (const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance) const
+{
+ return m_vk.createInstance(pCreateInfo, pAllocator, pInstance);
+}
+
+PFN_vkVoidFunction PlatformDriver::getInstanceProcAddr (VkInstance instance, const char* pName) const
+{
+ return m_vk.getInstanceProcAddr(instance, pName);
+}
+
+VkResult PlatformDriver::enumerateInstanceExtensionProperties (const char* pLayerName, deUint32* pPropertyCount, VkExtensionProperties* pProperties) const
+{
+ return m_vk.enumerateInstanceExtensionProperties(pLayerName, pPropertyCount, pProperties);
+}
+
+VkResult PlatformDriver::enumerateInstanceLayerProperties (deUint32* pPropertyCount, VkLayerProperties* pProperties) const
+{
+ return m_vk.enumerateInstanceLayerProperties(pPropertyCount, pProperties);
+}
--- /dev/null
+/* WARNING: This is auto-generated file. Do not modify, since changes will
+ * be lost! Modify the generating script instead.
+ */
+CreateInstanceFunc createInstance;
+GetInstanceProcAddrFunc getInstanceProcAddr;
+EnumerateInstanceExtensionPropertiesFunc enumerateInstanceExtensionProperties;
+EnumerateInstanceLayerPropertiesFunc enumerateInstanceLayerProperties;
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Program utilities.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkPrograms.hpp"
+#include "vkGlslToSpirV.hpp"
+#include "vkSpirVAsm.hpp"
+#include "vkRefUtil.hpp"
+
+#include "tcuTestLog.hpp"
+
+#include "deArrayUtil.hpp"
+#include "deMemory.h"
+
+namespace vk
+{
+
+using std::string;
+using std::vector;
+using tcu::TestLog;
+
+// ProgramBinary
+
+ProgramBinary::ProgramBinary (ProgramFormat format, size_t binarySize, const deUint8* binary)
+ : m_format (format)
+ , m_binary (binary, binary+binarySize)
+{
+}
+
+// Utils
+
+ProgramBinary* buildProgram (const glu::ProgramSources& program, ProgramFormat binaryFormat, glu::ShaderProgramInfo* buildInfo)
+{
+ if (binaryFormat == PROGRAM_FORMAT_SPIRV)
+ {
+ vector<deUint8> binary;
+ glslToSpirV(program, &binary, buildInfo);
+ return new ProgramBinary(binaryFormat, binary.size(), &binary[0]);
+ }
+ else
+ TCU_THROW(NotSupportedError, "Unsupported program format");
+}
+
+ProgramBinary* assembleProgram (const SpirVAsmSource& program, SpirVProgramInfo* buildInfo)
+{
+ vector<deUint8> binary;
+ assembleSpirV(&program, &binary, buildInfo);
+ return new ProgramBinary(PROGRAM_FORMAT_SPIRV, binary.size(), &binary[0]);
+}
+
+Move<VkShaderModule> createShaderModule (const DeviceInterface& deviceInterface, VkDevice device, const ProgramBinary& binary, VkShaderModuleCreateFlags flags)
+{
+ if (binary.getFormat() == PROGRAM_FORMAT_SPIRV)
+ {
+ const struct VkShaderModuleCreateInfo shaderModuleInfo =
+ {
+ VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
+ DE_NULL,
+ flags,
+ (deUintptr)binary.getSize(),
+ (const deUint32*)binary.getBinary(),
+ };
+
+ return createShaderModule(deviceInterface, device, &shaderModuleInfo);
+ }
+ else
+ TCU_THROW(NotSupportedError, "Unsupported program format");
+}
+
+glu::ShaderType getGluShaderType (VkShaderStageFlagBits shaderStage)
+{
+ switch (shaderStage)
+ {
+ case VK_SHADER_STAGE_VERTEX_BIT: return glu::SHADERTYPE_VERTEX;
+ case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: return glu::SHADERTYPE_TESSELLATION_CONTROL;
+ case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: return glu::SHADERTYPE_TESSELLATION_EVALUATION;
+ case VK_SHADER_STAGE_GEOMETRY_BIT: return glu::SHADERTYPE_GEOMETRY;
+ case VK_SHADER_STAGE_FRAGMENT_BIT: return glu::SHADERTYPE_FRAGMENT;
+ case VK_SHADER_STAGE_COMPUTE_BIT: return glu::SHADERTYPE_COMPUTE;
+ default:
+ DE_FATAL("Unknown shader stage");
+ return glu::SHADERTYPE_LAST;
+ }
+}
+
+VkShaderStageFlagBits getVkShaderStage (glu::ShaderType shaderType)
+{
+ static const VkShaderStageFlagBits s_shaderStages[] =
+ {
+ VK_SHADER_STAGE_VERTEX_BIT,
+ VK_SHADER_STAGE_FRAGMENT_BIT,
+ VK_SHADER_STAGE_GEOMETRY_BIT,
+ VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
+ VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
+ VK_SHADER_STAGE_COMPUTE_BIT
+ };
+
+ return de::getSizedArrayElement<glu::SHADERTYPE_LAST>(s_shaderStages, shaderType);
+}
+
+} // vk
--- /dev/null
+#ifndef _VKPROGRAMS_HPP
+#define _VKPROGRAMS_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Program utilities.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkDefs.hpp"
+#include "vkRef.hpp"
+#include "vkSpirVProgram.hpp"
+#include "gluShaderProgram.hpp"
+#include "deUniquePtr.hpp"
+#include "deSTLUtil.hpp"
+
+#include <vector>
+#include <map>
+
+namespace tcu
+{
+class TestLog;
+} // tcu
+
+namespace vk
+{
+
+enum ProgramFormat
+{
+ PROGRAM_FORMAT_SPIRV = 0,
+
+ PROGRAM_FORMAT_LAST
+};
+
+class ProgramBinary
+{
+public:
+ ProgramBinary (ProgramFormat format, size_t binarySize, const deUint8* binary);
+
+ ProgramFormat getFormat (void) const { return m_format; }
+ size_t getSize (void) const { return m_binary.size(); }
+ const deUint8* getBinary (void) const { return m_binary.empty() ? DE_NULL : &m_binary[0]; }
+
+private:
+ const ProgramFormat m_format;
+ const std::vector<deUint8> m_binary;
+};
+
+template<typename Program>
+class ProgramCollection
+{
+public:
+ ProgramCollection (void);
+ ~ProgramCollection (void);
+
+ void clear (void);
+
+ Program& add (const std::string& name);
+ void add (const std::string& name, de::MovePtr<Program>& program);
+
+ bool contains (const std::string& name) const;
+ const Program& get (const std::string& name) const;
+
+ class Iterator
+ {
+ private:
+ typedef typename std::map<std::string, Program*>::const_iterator IteratorImpl;
+
+ public:
+ explicit Iterator (const IteratorImpl& i) : m_impl(i) {}
+
+ Iterator& operator++ (void) { ++m_impl; return *this; }
+ const Program& operator* (void) const { return getProgram(); }
+
+ const std::string& getName (void) const { return m_impl->first; }
+ const Program& getProgram (void) const { return *m_impl->second; }
+
+ bool operator== (const Iterator& other) const { return m_impl == other.m_impl; }
+ bool operator!= (const Iterator& other) const { return m_impl != other.m_impl; }
+
+ private:
+
+ IteratorImpl m_impl;
+ };
+
+ Iterator begin (void) const { return Iterator(m_programs.begin()); }
+ Iterator end (void) const { return Iterator(m_programs.end()); }
+
+private:
+ typedef std::map<std::string, Program*> ProgramMap;
+
+ ProgramMap m_programs;
+};
+
+template<typename Program>
+ProgramCollection<Program>::ProgramCollection (void)
+{
+}
+
+template<typename Program>
+ProgramCollection<Program>::~ProgramCollection (void)
+{
+ clear();
+}
+
+template<typename Program>
+void ProgramCollection<Program>::clear (void)
+{
+ for (typename ProgramMap::const_iterator i = m_programs.begin(); i != m_programs.end(); ++i)
+ delete i->second;
+ m_programs.clear();
+}
+
+template<typename Program>
+Program& ProgramCollection<Program>::add (const std::string& name)
+{
+ DE_ASSERT(!contains(name));
+ de::MovePtr<Program> prog = de::newMovePtr<Program>();
+ m_programs[name] = prog.get();
+ prog.release();
+ return *m_programs[name];
+}
+
+template<typename Program>
+void ProgramCollection<Program>::add (const std::string& name, de::MovePtr<Program>& program)
+{
+ DE_ASSERT(!contains(name));
+ m_programs[name] = program.get();
+ program.release();
+}
+
+template<typename Program>
+bool ProgramCollection<Program>::contains (const std::string& name) const
+{
+ return de::contains(m_programs, name);
+}
+
+template<typename Program>
+const Program& ProgramCollection<Program>::get (const std::string& name) const
+{
+ DE_ASSERT(contains(name));
+ return *m_programs.find(name)->second;
+}
+
+typedef vk::ProgramCollection<glu::ProgramSources> GlslSourceCollection;
+typedef vk::ProgramCollection<vk::SpirVAsmSource> SpirVAsmCollection;
+
+struct SourceCollections
+{
+ GlslSourceCollection glslSources;
+ SpirVAsmCollection spirvAsmSources;
+};
+
+typedef ProgramCollection<ProgramBinary> BinaryCollection;
+
+// \todo [2015-03-13 pyry] Likely need BinaryBuilder abstraction for this
+ProgramBinary* buildProgram (const glu::ProgramSources& program, ProgramFormat binaryFormat, glu::ShaderProgramInfo* buildInfo);
+ProgramBinary* assembleProgram (const vk::SpirVAsmSource& program, SpirVProgramInfo* buildInfo);
+Move<VkShaderModule> createShaderModule (const DeviceInterface& deviceInterface, VkDevice device, const ProgramBinary& binary, VkShaderModuleCreateFlags flags);
+
+glu::ShaderType getGluShaderType (VkShaderStageFlagBits shaderStage);
+VkShaderStageFlagBits getVkShaderStage (glu::ShaderType shaderType);
+
+} // vk
+
+#endif // _VKPROGRAMS_HPP
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Vulkan query utilities.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkQueryUtil.hpp"
+#include "deMemory.h"
+
+namespace vk
+{
+
+using std::vector;
+
+vector<VkPhysicalDevice> enumeratePhysicalDevices (const InstanceInterface& vk, VkInstance instance)
+{
+ deUint32 numDevices = 0;
+ vector<VkPhysicalDevice> devices;
+
+ VK_CHECK(vk.enumeratePhysicalDevices(instance, &numDevices, DE_NULL));
+
+ if (numDevices > 0)
+ {
+ devices.resize(numDevices);
+ VK_CHECK(vk.enumeratePhysicalDevices(instance, &numDevices, &devices[0]));
+
+ if ((size_t)numDevices != devices.size())
+ TCU_FAIL("Returned device count changed between queries");
+ }
+
+ return devices;
+}
+
+vector<VkQueueFamilyProperties> getPhysicalDeviceQueueFamilyProperties (const InstanceInterface& vk, VkPhysicalDevice physicalDevice)
+{
+ deUint32 numQueues = 0;
+ vector<VkQueueFamilyProperties> properties;
+
+ vk.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numQueues, DE_NULL);
+
+ if (numQueues > 0)
+ {
+ properties.resize(numQueues);
+ vk.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numQueues, &properties[0]);
+
+ if ((size_t)numQueues != properties.size())
+ TCU_FAIL("Returned queue family count changes between queries");
+ }
+
+ return properties;
+}
+
+VkPhysicalDeviceFeatures getPhysicalDeviceFeatures (const InstanceInterface& vk, VkPhysicalDevice physicalDevice)
+{
+ VkPhysicalDeviceFeatures features;
+
+ deMemset(&features, 0, sizeof(features));
+
+ vk.getPhysicalDeviceFeatures(physicalDevice, &features);
+ return features;
+}
+
+VkPhysicalDeviceMemoryProperties getPhysicalDeviceMemoryProperties (const InstanceInterface& vk, VkPhysicalDevice physicalDevice)
+{
+ VkPhysicalDeviceMemoryProperties properties;
+
+ deMemset(&properties, 0, sizeof(properties));
+
+ vk.getPhysicalDeviceMemoryProperties(physicalDevice, &properties);
+ return properties;
+}
+
+VkMemoryRequirements getBufferMemoryRequirements (const DeviceInterface& vk, VkDevice device, VkBuffer buffer)
+{
+ VkMemoryRequirements req;
+ vk.getBufferMemoryRequirements(device, buffer, &req);
+ return req;
+}
+VkMemoryRequirements getImageMemoryRequirements (const DeviceInterface& vk, VkDevice device, VkImage image)
+{
+ VkMemoryRequirements req;
+ vk.getImageMemoryRequirements(device, image, &req);
+ return req;
+}
+
+vector<VkLayerProperties> enumerateInstanceLayerProperties (const PlatformInterface& vkp)
+{
+ vector<VkLayerProperties> properties;
+ deUint32 numLayers = 0;
+
+ VK_CHECK(vkp.enumerateInstanceLayerProperties(&numLayers, DE_NULL));
+
+ if (numLayers > 0)
+ {
+ properties.resize(numLayers);
+ VK_CHECK(vkp.enumerateInstanceLayerProperties(&numLayers, &properties[0]));
+ TCU_CHECK((size_t)numLayers == properties.size());
+ }
+
+ return properties;
+}
+
+vector<VkExtensionProperties> enumerateInstanceExtensionProperties (const PlatformInterface& vkp, const char* layerName)
+{
+ vector<VkExtensionProperties> properties;
+ deUint32 numExtensions = 0;
+
+ VK_CHECK(vkp.enumerateInstanceExtensionProperties(layerName, &numExtensions, DE_NULL));
+
+ if (numExtensions > 0)
+ {
+ properties.resize(numExtensions);
+ VK_CHECK(vkp.enumerateInstanceExtensionProperties(layerName, &numExtensions, &properties[0]));
+ TCU_CHECK((size_t)numExtensions == properties.size());
+ }
+
+ return properties;
+}
+
+vector<VkLayerProperties> enumerateDeviceLayerProperties (const InstanceInterface& vki, VkPhysicalDevice physicalDevice)
+{
+ vector<VkLayerProperties> properties;
+ deUint32 numLayers = 0;
+
+ VK_CHECK(vki.enumerateDeviceLayerProperties(physicalDevice, &numLayers, DE_NULL));
+
+ if (numLayers > 0)
+ {
+ properties.resize(numLayers);
+ VK_CHECK(vki.enumerateDeviceLayerProperties(physicalDevice, &numLayers, &properties[0]));
+ TCU_CHECK((size_t)numLayers == properties.size());
+ }
+
+ return properties;
+}
+
+vector<VkExtensionProperties> enumerateDeviceExtensionProperties (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, const char* layerName)
+{
+ vector<VkExtensionProperties> properties;
+ deUint32 numExtensions = 0;
+
+ VK_CHECK(vki.enumerateDeviceExtensionProperties(physicalDevice, layerName, &numExtensions, DE_NULL));
+
+ if (numExtensions > 0)
+ {
+ properties.resize(numExtensions);
+ VK_CHECK(vki.enumerateDeviceExtensionProperties(physicalDevice, layerName, &numExtensions, &properties[0]));
+ TCU_CHECK((size_t)numExtensions == properties.size());
+ }
+
+ return properties;
+}
+
+bool isShaderStageSupported (const VkPhysicalDeviceFeatures& deviceFeatures, VkShaderStageFlagBits stage)
+{
+ if (stage == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT || stage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
+ return deviceFeatures.tessellationShader == VK_TRUE;
+ else if (stage == VK_SHADER_STAGE_GEOMETRY_BIT)
+ return deviceFeatures.geometryShader == VK_TRUE;
+ else
+ return true;
+}
+
+} // vk
--- /dev/null
+#ifndef _VKQUERYUTIL_HPP
+#define _VKQUERYUTIL_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Vulkan query utilities.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkDefs.hpp"
+
+#include <vector>
+
+namespace vk
+{
+
+std::vector<VkPhysicalDevice> enumeratePhysicalDevices (const InstanceInterface& vk, VkInstance instance);
+std::vector<VkQueueFamilyProperties> getPhysicalDeviceQueueFamilyProperties (const InstanceInterface& vk, VkPhysicalDevice physicalDevice);
+VkPhysicalDeviceFeatures getPhysicalDeviceFeatures (const InstanceInterface& vk, VkPhysicalDevice physicalDevice);
+VkPhysicalDeviceMemoryProperties getPhysicalDeviceMemoryProperties (const InstanceInterface& vk, VkPhysicalDevice physicalDevice);
+
+VkMemoryRequirements getBufferMemoryRequirements (const DeviceInterface& vk, VkDevice device, VkBuffer buffer);
+VkMemoryRequirements getImageMemoryRequirements (const DeviceInterface& vk, VkDevice device, VkImage image);
+
+std::vector<VkLayerProperties> enumerateInstanceLayerProperties (const PlatformInterface& vkp);
+std::vector<VkExtensionProperties> enumerateInstanceExtensionProperties (const PlatformInterface& vkp, const char* layerName);
+std::vector<VkLayerProperties> enumerateDeviceLayerProperties (const InstanceInterface& vki, VkPhysicalDevice physicalDevice);
+std::vector<VkExtensionProperties> enumerateDeviceExtensionProperties (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, const char* layerName);
+
+bool isShaderStageSupported (const VkPhysicalDeviceFeatures& deviceFeatures, VkShaderStageFlagBits stage);
+
+} // vk
+
+#endif // _VKQUERYUTIL_HPP
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Vulkan object reference holder.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkRef.hpp"
+
+DE_EMPTY_CPP_FILE
--- /dev/null
+#ifndef _VKREF_HPP
+#define _VKREF_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Vulkan object reference holder.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkDefs.hpp"
+#include "vkStrUtil.hpp"
+#include "deMeta.hpp"
+
+#include <algorithm>
+
+namespace vk
+{
+
+namespace refdetails
+{
+
+using std::swap;
+
+template<typename T>
+struct Checked
+{
+ explicit inline Checked (T object_) : object(object_) {}
+
+ T object;
+};
+
+//! Check that object is not null
+template<typename T>
+inline Checked<T> check (T object)
+{
+ if (!object)
+ throw tcu::TestError("Object check() failed", (std::string(getTypeName<T>()) + " = 0").c_str(), __FILE__, __LINE__);
+ return Checked<T>(object);
+}
+
+//! Declare object as checked earlier
+template<typename T>
+inline Checked<T> notNull (T object)
+{
+ if (!object)
+ throw tcu::InternalError("Null object was given to notNull()", (std::string(getTypeName<T>()) + " = 0").c_str(), __FILE__, __LINE__);
+ return Checked<T>(object);
+}
+
+//! Allow null object
+template<typename T>
+inline Checked<T> allowNull (T object)
+{
+ return Checked<T>(object);
+}
+
+template<typename T>
+class Deleter
+{
+public:
+ Deleter (const DeviceInterface& deviceIface, VkDevice device)
+ : m_deviceIface (&deviceIface)
+ , m_device (device)
+ {}
+ Deleter (void)
+ : m_deviceIface (DE_NULL)
+ , m_device (DE_NULL)
+ {}
+
+ void operator() (T obj) const;
+
+private:
+ const DeviceInterface* m_deviceIface;
+ VkDevice m_device;
+};
+
+template<>
+class Deleter<VkInstance>
+{
+public:
+ Deleter (const PlatformInterface& platformIface, VkInstance instance)
+ : m_destroyInstance((DestroyInstanceFunc)platformIface.getInstanceProcAddr(instance, "vkDestroyInstance"))
+ {}
+ Deleter (void)
+ : m_destroyInstance((DestroyInstanceFunc)DE_NULL)
+ {}
+
+ void operator() (VkInstance obj) const { m_destroyInstance(obj, DE_NULL); }
+
+private:
+ DestroyInstanceFunc m_destroyInstance;
+};
+
+template<>
+class Deleter<VkDevice>
+{
+public:
+ Deleter (const InstanceInterface& instanceIface, VkDevice device)
+ : m_destroyDevice((DestroyDeviceFunc)instanceIface.getDeviceProcAddr(device, "vkDestroyDevice"))
+ {}
+ Deleter (void)
+ : m_destroyDevice((DestroyDeviceFunc)DE_NULL)
+ {}
+
+ void operator() (VkDevice obj) const { m_destroyDevice(obj, DE_NULL); }
+
+private:
+ DestroyDeviceFunc m_destroyDevice;
+};
+
+template<>
+class Deleter<VkDescriptorSet>
+{
+public:
+ Deleter (const DeviceInterface& deviceIface, VkDevice device, VkDescriptorPool pool)
+ : m_deviceIface (&deviceIface)
+ , m_device (device)
+ , m_pool (pool)
+ {}
+ Deleter (void)
+ : m_deviceIface (DE_NULL)
+ , m_device (DE_NULL)
+ , m_pool (DE_NULL)
+ {}
+
+ void operator() (VkDescriptorSet obj) const { m_deviceIface->freeDescriptorSets(m_device, m_pool, 1, &obj); }
+
+private:
+ const DeviceInterface* m_deviceIface;
+ VkDevice m_device;
+ VkDescriptorPool m_pool;
+};
+
+template<>
+class Deleter<VkCommandBuffer>
+{
+public:
+ Deleter (const DeviceInterface& deviceIface, VkDevice device, VkCommandPool pool)
+ : m_deviceIface (&deviceIface)
+ , m_device (device)
+ , m_pool (pool)
+ {}
+ Deleter (void)
+ : m_deviceIface (DE_NULL)
+ , m_device (DE_NULL)
+ , m_pool (DE_NULL)
+ {}
+
+ void operator() (VkCommandBuffer obj) const { m_deviceIface->freeCommandBuffers(m_device, m_pool, 1, &obj); }
+
+private:
+ const DeviceInterface* m_deviceIface;
+ VkDevice m_device;
+ VkCommandPool m_pool;
+};
+
+template<typename T>
+struct RefData
+{
+ RefData (T object_, Deleter<T> deleter_)
+ : object (object_)
+ , deleter (deleter_)
+ {}
+ RefData (void)
+ : object (0)
+ {}
+
+ T object;
+ Deleter<T> deleter;
+};
+
+template<typename T>
+class RefBase
+{
+public:
+ ~RefBase (void);
+
+ inline const T& get (void) const throw() { return m_data.object; }
+ inline const T& operator* (void) const throw() { return get(); }
+ inline operator bool (void) const throw() { return !!get(); }
+
+protected:
+ RefBase (RefData<T> data) : m_data(data) {}
+
+ void reset (void); //!< Release previous object, set to null.
+ RefData<T> disown (void) throw(); //!< Disown and return object (ownership transferred to caller).
+ void assign (RefData<T> data); //!< Set new pointer, release previous pointer.
+
+private:
+ RefData<T> m_data;
+};
+
+template<typename T>
+inline RefBase<T>::~RefBase (void)
+{
+ this->reset();
+}
+
+template<typename T>
+inline void RefBase<T>::reset (void)
+{
+ if (!!m_data.object)
+ m_data.deleter(m_data.object);
+
+ m_data = RefData<T>();
+}
+
+template<typename T>
+inline RefData<T> RefBase<T>::disown (void) throw()
+{
+ RefData<T> tmp;
+ swap(m_data, tmp);
+ return tmp;
+}
+
+template<typename T>
+inline void RefBase<T>::assign (RefData<T> data)
+{
+ this->reset();
+ m_data = data;
+}
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Movable Vulkan object reference.
+ *
+ * Similar to de::MovePtr.
+ *//*--------------------------------------------------------------------*/
+template<typename T>
+class Move : public RefBase<T>
+{
+public:
+ template<typename U>
+ Move (Checked<U> object, Deleter<U> deleter)
+ : RefBase<T>(RefData<T>(object.object, deleter))
+ {}
+
+ Move (RefData<T> data)
+ : RefBase<T>(data)
+ {}
+ Move (Move<T>& other)
+ : RefBase<T>(other.RefBase<T>::disown())
+ {}
+ Move (void)
+ : RefBase<T>(RefData<T>())
+ {}
+
+ T disown (void) { return this->RefBase<T>::disown().object; }
+ Move<T>& operator= (Move<T>& other);
+ Move<T>& operator= (RefData<T> data);
+
+ operator RefData<T> (void) { return this->RefBase<T>::disown(); }
+};
+
+template<typename T>
+inline Move<T>& Move<T>::operator= (Move<T>& other)
+{
+ if (this != &other)
+ this->assign(other.RefBase<T>::disown());
+
+ return *this;
+}
+
+template<typename T>
+inline Move<T>& Move<T>::operator= (RefData<T> data)
+{
+ this->assign(data);
+ return *this;
+}
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Unique Vulkan object reference.
+ *
+ * Similar to de::UniquePtr.
+ *//*--------------------------------------------------------------------*/
+template<typename T>
+class Unique : public RefBase<T>
+{
+public:
+ template<typename U>
+ Unique (Checked<U> object, Deleter<U> deleter)
+ : RefBase<T>(RefData<T>(object.object, deleter))
+ {}
+
+ Unique (RefData<T> data)
+ : RefBase<T>(data)
+ {}
+
+private:
+ Unique (const Unique<T>&);
+ Unique<T>& operator= (const Unique<T>&);
+};
+
+} // refdetails
+
+using refdetails::Move;
+using refdetails::Unique;
+using refdetails::Deleter;
+using refdetails::check;
+using refdetails::notNull;
+using refdetails::allowNull;
+
+} // vk
+
+#endif // _VKREF_HPP
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Vulkan object reference holder utilities.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkRefUtil.hpp"
+
+namespace vk
+{
+
+#include "vkRefUtilImpl.inl"
+
+Move<VkPipeline> createGraphicsPipeline (const DeviceInterface& vk, VkDevice device, VkPipelineCache pipelineCache, const VkGraphicsPipelineCreateInfo* pCreateInfo)
+{
+ VkPipeline object = 0;
+ VK_CHECK(vk.createGraphicsPipelines(device, pipelineCache, 1u, pCreateInfo, DE_NULL, &object));
+ return Move<VkPipeline>(check<VkPipeline>(object), Deleter<VkPipeline>(vk, device));
+}
+
+Move<VkPipeline> createComputePipeline (const DeviceInterface& vk, VkDevice device, VkPipelineCache pipelineCache, const VkComputePipelineCreateInfo* pCreateInfo)
+{
+ VkPipeline object = 0;
+ VK_CHECK(vk.createComputePipelines(device, pipelineCache, 1u, pCreateInfo, DE_NULL, &object));
+ return Move<VkPipeline>(check<VkPipeline>(object), Deleter<VkPipeline>(vk, device));
+}
+
+Move<VkCommandBuffer> allocateCommandBuffer (const DeviceInterface& vk, VkDevice device, const VkCommandBufferAllocateInfo* pAllocateInfo)
+{
+ VkCommandBuffer object = 0;
+ DE_ASSERT(pAllocateInfo->bufferCount == 1u);
+ VK_CHECK(vk.allocateCommandBuffers(device, pAllocateInfo, &object));
+ return Move<VkCommandBuffer>(check<VkCommandBuffer>(object), Deleter<VkCommandBuffer>(vk, device, pAllocateInfo->commandPool));
+}
+
+Move<VkDescriptorSet> allocateDescriptorSet (const DeviceInterface& vk, VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo)
+{
+ VkDescriptorSet object = 0;
+ DE_ASSERT(pAllocateInfo->setLayoutCount == 1u);
+ VK_CHECK(vk.allocateDescriptorSets(device, pAllocateInfo, &object));
+ return Move<VkDescriptorSet>(check<VkDescriptorSet>(object), Deleter<VkDescriptorSet>(vk, device, pAllocateInfo->descriptorPool));
+}
+
+} // vk
--- /dev/null
+#ifndef _VKREFUTIL_HPP
+#define _VKREFUTIL_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Vulkan object reference holder utilities.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkDefs.hpp"
+#include "vkRef.hpp"
+
+namespace vk
+{
+
+#include "vkRefUtil.inl"
+
+Move<VkPipeline> createGraphicsPipeline (const DeviceInterface& vk, VkDevice device, VkPipelineCache pipelineCache, const VkGraphicsPipelineCreateInfo* pCreateInfo);
+Move<VkPipeline> createComputePipeline (const DeviceInterface& vk, VkDevice device, VkPipelineCache pipelineCache, const VkComputePipelineCreateInfo* pCreateInfo);
+Move<VkCommandBuffer> allocateCommandBuffer (const DeviceInterface& vk, VkDevice device, const VkCommandBufferAllocateInfo* pAllocateInfo);
+Move<VkDescriptorSet> allocateDescriptorSet (const DeviceInterface& vk, VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo);
+
+} // vk
+
+#endif // _VKREFUTIL_HPP
--- /dev/null
+/* WARNING: This is auto-generated file. Do not modify, since changes will
+ * be lost! Modify the generating script instead.
+ */
+Move<VkInstance> createInstance (const PlatformInterface& vk, const VkInstanceCreateInfo* pCreateInfo);
+Move<VkDevice> createDevice (const InstanceInterface& vk, VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo);
+Move<VkDeviceMemory> allocateMemory (const DeviceInterface& vk, VkDevice device, const VkMemoryAllocateInfo* pAllocateInfo);
+Move<VkFence> createFence (const DeviceInterface& vk, VkDevice device, const VkFenceCreateInfo* pCreateInfo);
+Move<VkSemaphore> createSemaphore (const DeviceInterface& vk, VkDevice device, const VkSemaphoreCreateInfo* pCreateInfo);
+Move<VkEvent> createEvent (const DeviceInterface& vk, VkDevice device, const VkEventCreateInfo* pCreateInfo);
+Move<VkQueryPool> createQueryPool (const DeviceInterface& vk, VkDevice device, const VkQueryPoolCreateInfo* pCreateInfo);
+Move<VkBuffer> createBuffer (const DeviceInterface& vk, VkDevice device, const VkBufferCreateInfo* pCreateInfo);
+Move<VkBufferView> createBufferView (const DeviceInterface& vk, VkDevice device, const VkBufferViewCreateInfo* pCreateInfo);
+Move<VkImage> createImage (const DeviceInterface& vk, VkDevice device, const VkImageCreateInfo* pCreateInfo);
+Move<VkImageView> createImageView (const DeviceInterface& vk, VkDevice device, const VkImageViewCreateInfo* pCreateInfo);
+Move<VkShaderModule> createShaderModule (const DeviceInterface& vk, VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo);
+Move<VkPipelineCache> createPipelineCache (const DeviceInterface& vk, VkDevice device, const VkPipelineCacheCreateInfo* pCreateInfo);
+Move<VkPipeline> createGraphicsPipelines (const DeviceInterface& vk, VkDevice device, VkPipelineCache pipelineCache, deUint32 createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos);
+Move<VkPipeline> createComputePipelines (const DeviceInterface& vk, VkDevice device, VkPipelineCache pipelineCache, deUint32 createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos);
+Move<VkPipelineLayout> createPipelineLayout (const DeviceInterface& vk, VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo);
+Move<VkSampler> createSampler (const DeviceInterface& vk, VkDevice device, const VkSamplerCreateInfo* pCreateInfo);
+Move<VkDescriptorSetLayout> createDescriptorSetLayout (const DeviceInterface& vk, VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo);
+Move<VkDescriptorPool> createDescriptorPool (const DeviceInterface& vk, VkDevice device, const VkDescriptorPoolCreateInfo* pCreateInfo);
+Move<VkFramebuffer> createFramebuffer (const DeviceInterface& vk, VkDevice device, const VkFramebufferCreateInfo* pCreateInfo);
+Move<VkRenderPass> createRenderPass (const DeviceInterface& vk, VkDevice device, const VkRenderPassCreateInfo* pCreateInfo);
+Move<VkCommandPool> createCommandPool (const DeviceInterface& vk, VkDevice device, const VkCommandPoolCreateInfo* pCreateInfo);
--- /dev/null
+/* WARNING: This is auto-generated file. Do not modify, since changes will
+ * be lost! Modify the generating script instead.
+ */
+namespace refdetails
+{
+
+template<>
+void Deleter<VkDeviceMemory>::operator() (VkDeviceMemory obj) const
+{
+ m_deviceIface->freeMemory(m_device, obj, DE_NULL);
+}
+
+template<>
+void Deleter<VkFence>::operator() (VkFence obj) const
+{
+ m_deviceIface->destroyFence(m_device, obj, DE_NULL);
+}
+
+template<>
+void Deleter<VkSemaphore>::operator() (VkSemaphore obj) const
+{
+ m_deviceIface->destroySemaphore(m_device, obj, DE_NULL);
+}
+
+template<>
+void Deleter<VkEvent>::operator() (VkEvent obj) const
+{
+ m_deviceIface->destroyEvent(m_device, obj, DE_NULL);
+}
+
+template<>
+void Deleter<VkQueryPool>::operator() (VkQueryPool obj) const
+{
+ m_deviceIface->destroyQueryPool(m_device, obj, DE_NULL);
+}
+
+template<>
+void Deleter<VkBuffer>::operator() (VkBuffer obj) const
+{
+ m_deviceIface->destroyBuffer(m_device, obj, DE_NULL);
+}
+
+template<>
+void Deleter<VkBufferView>::operator() (VkBufferView obj) const
+{
+ m_deviceIface->destroyBufferView(m_device, obj, DE_NULL);
+}
+
+template<>
+void Deleter<VkImage>::operator() (VkImage obj) const
+{
+ m_deviceIface->destroyImage(m_device, obj, DE_NULL);
+}
+
+template<>
+void Deleter<VkImageView>::operator() (VkImageView obj) const
+{
+ m_deviceIface->destroyImageView(m_device, obj, DE_NULL);
+}
+
+template<>
+void Deleter<VkShaderModule>::operator() (VkShaderModule obj) const
+{
+ m_deviceIface->destroyShaderModule(m_device, obj, DE_NULL);
+}
+
+template<>
+void Deleter<VkPipelineCache>::operator() (VkPipelineCache obj) const
+{
+ m_deviceIface->destroyPipelineCache(m_device, obj, DE_NULL);
+}
+
+template<>
+void Deleter<VkPipeline>::operator() (VkPipeline obj) const
+{
+ m_deviceIface->destroyPipeline(m_device, obj, DE_NULL);
+}
+
+template<>
+void Deleter<VkPipelineLayout>::operator() (VkPipelineLayout obj) const
+{
+ m_deviceIface->destroyPipelineLayout(m_device, obj, DE_NULL);
+}
+
+template<>
+void Deleter<VkSampler>::operator() (VkSampler obj) const
+{
+ m_deviceIface->destroySampler(m_device, obj, DE_NULL);
+}
+
+template<>
+void Deleter<VkDescriptorSetLayout>::operator() (VkDescriptorSetLayout obj) const
+{
+ m_deviceIface->destroyDescriptorSetLayout(m_device, obj, DE_NULL);
+}
+
+template<>
+void Deleter<VkDescriptorPool>::operator() (VkDescriptorPool obj) const
+{
+ m_deviceIface->destroyDescriptorPool(m_device, obj, DE_NULL);
+}
+
+template<>
+void Deleter<VkFramebuffer>::operator() (VkFramebuffer obj) const
+{
+ m_deviceIface->destroyFramebuffer(m_device, obj, DE_NULL);
+}
+
+template<>
+void Deleter<VkRenderPass>::operator() (VkRenderPass obj) const
+{
+ m_deviceIface->destroyRenderPass(m_device, obj, DE_NULL);
+}
+
+template<>
+void Deleter<VkCommandPool>::operator() (VkCommandPool obj) const
+{
+ m_deviceIface->destroyCommandPool(m_device, obj, DE_NULL);
+}
+
+} // refdetails
+
+Move<VkInstance> createInstance (const PlatformInterface& vk, const VkInstanceCreateInfo* pCreateInfo)
+{
+ VkInstance object = 0;
+ VK_CHECK(vk.createInstance(pCreateInfo, DE_NULL, &object));
+ return Move<VkInstance>(check<VkInstance>(object), Deleter<VkInstance>(vk, object));
+}
+
+Move<VkDevice> createDevice (const InstanceInterface& vk, VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo)
+{
+ VkDevice object = 0;
+ VK_CHECK(vk.createDevice(physicalDevice, pCreateInfo, DE_NULL, &object));
+ return Move<VkDevice>(check<VkDevice>(object), Deleter<VkDevice>(vk, object));
+}
+
+Move<VkDeviceMemory> allocateMemory (const DeviceInterface& vk, VkDevice device, const VkMemoryAllocateInfo* pAllocateInfo)
+{
+ VkDeviceMemory object = 0;
+ VK_CHECK(vk.allocateMemory(device, pAllocateInfo, DE_NULL, &object));
+ return Move<VkDeviceMemory>(check<VkDeviceMemory>(object), Deleter<VkDeviceMemory>(vk, device));
+}
+
+Move<VkFence> createFence (const DeviceInterface& vk, VkDevice device, const VkFenceCreateInfo* pCreateInfo)
+{
+ VkFence object = 0;
+ VK_CHECK(vk.createFence(device, pCreateInfo, DE_NULL, &object));
+ return Move<VkFence>(check<VkFence>(object), Deleter<VkFence>(vk, device));
+}
+
+Move<VkSemaphore> createSemaphore (const DeviceInterface& vk, VkDevice device, const VkSemaphoreCreateInfo* pCreateInfo)
+{
+ VkSemaphore object = 0;
+ VK_CHECK(vk.createSemaphore(device, pCreateInfo, DE_NULL, &object));
+ return Move<VkSemaphore>(check<VkSemaphore>(object), Deleter<VkSemaphore>(vk, device));
+}
+
+Move<VkEvent> createEvent (const DeviceInterface& vk, VkDevice device, const VkEventCreateInfo* pCreateInfo)
+{
+ VkEvent object = 0;
+ VK_CHECK(vk.createEvent(device, pCreateInfo, DE_NULL, &object));
+ return Move<VkEvent>(check<VkEvent>(object), Deleter<VkEvent>(vk, device));
+}
+
+Move<VkQueryPool> createQueryPool (const DeviceInterface& vk, VkDevice device, const VkQueryPoolCreateInfo* pCreateInfo)
+{
+ VkQueryPool object = 0;
+ VK_CHECK(vk.createQueryPool(device, pCreateInfo, DE_NULL, &object));
+ return Move<VkQueryPool>(check<VkQueryPool>(object), Deleter<VkQueryPool>(vk, device));
+}
+
+Move<VkBuffer> createBuffer (const DeviceInterface& vk, VkDevice device, const VkBufferCreateInfo* pCreateInfo)
+{
+ VkBuffer object = 0;
+ VK_CHECK(vk.createBuffer(device, pCreateInfo, DE_NULL, &object));
+ return Move<VkBuffer>(check<VkBuffer>(object), Deleter<VkBuffer>(vk, device));
+}
+
+Move<VkBufferView> createBufferView (const DeviceInterface& vk, VkDevice device, const VkBufferViewCreateInfo* pCreateInfo)
+{
+ VkBufferView object = 0;
+ VK_CHECK(vk.createBufferView(device, pCreateInfo, DE_NULL, &object));
+ return Move<VkBufferView>(check<VkBufferView>(object), Deleter<VkBufferView>(vk, device));
+}
+
+Move<VkImage> createImage (const DeviceInterface& vk, VkDevice device, const VkImageCreateInfo* pCreateInfo)
+{
+ VkImage object = 0;
+ VK_CHECK(vk.createImage(device, pCreateInfo, DE_NULL, &object));
+ return Move<VkImage>(check<VkImage>(object), Deleter<VkImage>(vk, device));
+}
+
+Move<VkImageView> createImageView (const DeviceInterface& vk, VkDevice device, const VkImageViewCreateInfo* pCreateInfo)
+{
+ VkImageView object = 0;
+ VK_CHECK(vk.createImageView(device, pCreateInfo, DE_NULL, &object));
+ return Move<VkImageView>(check<VkImageView>(object), Deleter<VkImageView>(vk, device));
+}
+
+Move<VkShaderModule> createShaderModule (const DeviceInterface& vk, VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo)
+{
+ VkShaderModule object = 0;
+ VK_CHECK(vk.createShaderModule(device, pCreateInfo, DE_NULL, &object));
+ return Move<VkShaderModule>(check<VkShaderModule>(object), Deleter<VkShaderModule>(vk, device));
+}
+
+Move<VkPipelineCache> createPipelineCache (const DeviceInterface& vk, VkDevice device, const VkPipelineCacheCreateInfo* pCreateInfo)
+{
+ VkPipelineCache object = 0;
+ VK_CHECK(vk.createPipelineCache(device, pCreateInfo, DE_NULL, &object));
+ return Move<VkPipelineCache>(check<VkPipelineCache>(object), Deleter<VkPipelineCache>(vk, device));
+}
+
+Move<VkPipeline> createGraphicsPipelines (const DeviceInterface& vk, VkDevice device, VkPipelineCache pipelineCache, deUint32 createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos)
+{
+ VkPipeline object = 0;
+ VK_CHECK(vk.createGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, DE_NULL, &object));
+ return Move<VkPipeline>(check<VkPipeline>(object), Deleter<VkPipeline>(vk, device));
+}
+
+Move<VkPipeline> createComputePipelines (const DeviceInterface& vk, VkDevice device, VkPipelineCache pipelineCache, deUint32 createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos)
+{
+ VkPipeline object = 0;
+ VK_CHECK(vk.createComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, DE_NULL, &object));
+ return Move<VkPipeline>(check<VkPipeline>(object), Deleter<VkPipeline>(vk, device));
+}
+
+Move<VkPipelineLayout> createPipelineLayout (const DeviceInterface& vk, VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo)
+{
+ VkPipelineLayout object = 0;
+ VK_CHECK(vk.createPipelineLayout(device, pCreateInfo, DE_NULL, &object));
+ return Move<VkPipelineLayout>(check<VkPipelineLayout>(object), Deleter<VkPipelineLayout>(vk, device));
+}
+
+Move<VkSampler> createSampler (const DeviceInterface& vk, VkDevice device, const VkSamplerCreateInfo* pCreateInfo)
+{
+ VkSampler object = 0;
+ VK_CHECK(vk.createSampler(device, pCreateInfo, DE_NULL, &object));
+ return Move<VkSampler>(check<VkSampler>(object), Deleter<VkSampler>(vk, device));
+}
+
+Move<VkDescriptorSetLayout> createDescriptorSetLayout (const DeviceInterface& vk, VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo)
+{
+ VkDescriptorSetLayout object = 0;
+ VK_CHECK(vk.createDescriptorSetLayout(device, pCreateInfo, DE_NULL, &object));
+ return Move<VkDescriptorSetLayout>(check<VkDescriptorSetLayout>(object), Deleter<VkDescriptorSetLayout>(vk, device));
+}
+
+Move<VkDescriptorPool> createDescriptorPool (const DeviceInterface& vk, VkDevice device, const VkDescriptorPoolCreateInfo* pCreateInfo)
+{
+ VkDescriptorPool object = 0;
+ VK_CHECK(vk.createDescriptorPool(device, pCreateInfo, DE_NULL, &object));
+ return Move<VkDescriptorPool>(check<VkDescriptorPool>(object), Deleter<VkDescriptorPool>(vk, device));
+}
+
+Move<VkFramebuffer> createFramebuffer (const DeviceInterface& vk, VkDevice device, const VkFramebufferCreateInfo* pCreateInfo)
+{
+ VkFramebuffer object = 0;
+ VK_CHECK(vk.createFramebuffer(device, pCreateInfo, DE_NULL, &object));
+ return Move<VkFramebuffer>(check<VkFramebuffer>(object), Deleter<VkFramebuffer>(vk, device));
+}
+
+Move<VkRenderPass> createRenderPass (const DeviceInterface& vk, VkDevice device, const VkRenderPassCreateInfo* pCreateInfo)
+{
+ VkRenderPass object = 0;
+ VK_CHECK(vk.createRenderPass(device, pCreateInfo, DE_NULL, &object));
+ return Move<VkRenderPass>(check<VkRenderPass>(object), Deleter<VkRenderPass>(vk, device));
+}
+
+Move<VkCommandPool> createCommandPool (const DeviceInterface& vk, VkDevice device, const VkCommandPoolCreateInfo* pCreateInfo)
+{
+ VkCommandPool object = 0;
+ VK_CHECK(vk.createCommandPool(device, pCreateInfo, DE_NULL, &object));
+ return Move<VkCommandPool>(check<VkCommandPool>(object), Deleter<VkCommandPool>(vk, device));
+}
+
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief SPIR-V assembly to binary.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkSpirVAsm.hpp"
+#include "vkSpirVProgram.hpp"
+#include "deArrayUtil.hpp"
+#include "deMemory.h"
+#include "deClock.h"
+#include "qpDebugOut.h"
+
+#if defined(DEQP_HAVE_SPIRV_TOOLS)
+# include "deSingleton.h"
+
+# include "libspirv/libspirv.h"
+#endif
+
+namespace vk
+{
+
+using std::string;
+using std::vector;
+
+#if defined(DEQP_HAVE_SPIRV_TOOLS)
+
+
+void assembleSpirV (const SpirVAsmSource* program, std::vector<deUint8>* dst, SpirVProgramInfo* buildInfo)
+{
+ spv_context context = spvContextCreate();
+
+ const std::string& spvSource = program->program.str();
+ spv_binary binary = DE_NULL;
+ spv_diagnostic diagnostic = DE_NULL;
+ const deUint64 compileStartTime = deGetMicroseconds();
+ const spv_result_t compileOk = spvTextToBinary(context, spvSource.c_str(), spvSource.size(), &binary, &diagnostic);
+
+ {
+ buildInfo->source = program;
+ buildInfo->infoLog = diagnostic? diagnostic->error : ""; // \todo [2015-07-13 pyry] Include debug log?
+ buildInfo->compileTimeUs = deGetMicroseconds() - compileStartTime;
+ buildInfo->compileOk = (compileOk == SPV_SUCCESS);
+ }
+
+ if (compileOk != SPV_SUCCESS)
+ TCU_FAIL("Failed to compile shader");
+
+ dst->resize((int)binary->wordCount * sizeof(deUint32));
+#if (DE_ENDIANNESS == DE_LITTLE_ENDIAN)
+ deMemcpy(&(*dst)[0], &binary->code[0], dst->size());
+#else
+# error "Big-endian not supported"
+#endif
+ spvBinaryDestroy(binary);
+ spvDiagnosticDestroy(diagnostic);
+ spvContextDestroy(context);
+ return;
+}
+
+#else // defined(DEQP_HAVE_SPIRV_TOOLS)
+
+void assembleSpirV (const SpirVAsmSource*, std::vector<deUint8>*, SpirVProgramInfo*)
+{
+ TCU_THROW(NotSupportedError, "SPIR-V assembly not supported (DEQP_HAVE_SPIRV_TOOLS not defined)");
+}
+
+#endif
+
+} // vk
--- /dev/null
+#ifndef _VKSPIRVASM_HPP
+#define _VKSPIRVASM_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief SPIR-V assembly to binary.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkDefs.hpp"
+#include "vkPrograms.hpp"
+
+namespace vk
+{
+
+//! Assemble SPIR-V program. Will fail with NotSupportedError if compiler is not available.
+void assembleSpirV (const SpirVAsmSource* program, std::vector<deUint8>* dst, SpirVProgramInfo* buildInfo);
+
+} // vk
+
+#endif // _VKSPIRVASM_HPP
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Spirv program and binary info.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkSpirVProgram.hpp"
+
+#include "tcuTestLog.hpp"
+
+namespace vk
+{
+
+tcu::TestLog& operator<< (tcu::TestLog& log, const SpirVProgramInfo& shaderInfo)
+{
+ log << tcu::TestLog::ShaderProgram(shaderInfo.compileOk , shaderInfo.infoLog) << tcu::TestLog::EndShaderProgram;
+
+ // Write statistics
+ log << tcu::TestLog::Float( "SpirVAssemblyTime",
+ "SpirV assembly time",
+ "ms", QP_KEY_TAG_TIME, (float)shaderInfo.compileTimeUs / 1000.0f);
+ return log;
+}
+
+tcu::TestLog& operator<< (tcu::TestLog& log, const SpirVAsmSource& source)
+{
+ log << tcu::TestLog::KernelSource(source.program.str());
+
+ return log;
+}
+
+} // vk
--- /dev/null
+#ifndef _VKSPIRVPROGRAM_HPP
+#define _VKSPIRVPROGRAM_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief SPIR-V program and binary info.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkDefs.hpp"
+#include "tcuTestLog.hpp"
+
+#include <string>
+#include <sstream>
+
+namespace vk
+{
+
+struct SpirVAsmSource
+{
+ template<typename T>
+ SpirVAsmSource& operator<<(const T& val)
+ {
+ program << val;
+ return *this;
+ }
+ std::ostringstream program;
+};
+
+struct SpirVProgramInfo
+{
+ SpirVProgramInfo()
+ : source (DE_NULL)
+ , compileTimeUs (0)
+ , compileOk (false)
+ {
+ }
+
+ const SpirVAsmSource* source;
+ std::string infoLog;
+ deUint64 compileTimeUs;
+ bool compileOk;
+};
+
+tcu::TestLog& operator<< (tcu::TestLog& log, const SpirVProgramInfo& shaderInfo);
+tcu::TestLog& operator<< (tcu::TestLog& log, const SpirVAsmSource& program);
+
+}
+
+#endif // _VKSPIRVPROGRAM_HPP
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Pretty-printing and logging utilities.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkStrUtil.hpp"
+
+namespace vk
+{
+
+struct CharPtr
+{
+ const char* ptr;
+
+ CharPtr (const char* ptr_) : ptr(ptr_) {}
+};
+
+std::ostream& operator<< (std::ostream& str, const CharPtr& ptr)
+{
+ if (!ptr.ptr)
+ return str << "(null)";
+ else
+ return str << '"' << ptr.ptr << '"';
+}
+
+inline CharPtr getCharPtrStr (const char* ptr)
+{
+ return CharPtr(ptr);
+}
+
+#include "vkStrUtilImpl.inl"
+
+} // vk
--- /dev/null
+#ifndef _VKSTRUTIL_HPP
+#define _VKSTRUTIL_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Pretty-printing and logging utilities.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkDefs.hpp"
+#include "tcuFormatUtil.hpp"
+
+namespace vk
+{
+
+#include "vkStrUtil.inl"
+
+template<typename T>
+const char* getTypeName (void);
+
+template<HandleType Type>
+inline std::ostream& operator<< (std::ostream& s, const Handle<Type>& handle)
+{
+ return s << tcu::toHex(handle.getInternal());
+}
+
+} // vk
+
+#endif // _VKSTRUTIL_HPP
--- /dev/null
+/* WARNING: This is auto-generated file. Do not modify, since changes will
+ * be lost! Modify the generating script instead.
+ */
+const char* getResultName (VkResult value);
+const char* getStructureTypeName (VkStructureType value);
+const char* getSystemAllocationScopeName (VkSystemAllocationScope value);
+const char* getInternalAllocationTypeName (VkInternalAllocationType value);
+const char* getFormatName (VkFormat value);
+const char* getImageTypeName (VkImageType value);
+const char* getImageTilingName (VkImageTiling value);
+const char* getPhysicalDeviceTypeName (VkPhysicalDeviceType value);
+const char* getQueryTypeName (VkQueryType value);
+const char* getSharingModeName (VkSharingMode value);
+const char* getImageLayoutName (VkImageLayout value);
+const char* getImageViewTypeName (VkImageViewType value);
+const char* getComponentSwizzleName (VkComponentSwizzle value);
+const char* getVertexInputRateName (VkVertexInputRate value);
+const char* getPrimitiveTopologyName (VkPrimitiveTopology value);
+const char* getPolygonModeName (VkPolygonMode value);
+const char* getFrontFaceName (VkFrontFace value);
+const char* getCompareOpName (VkCompareOp value);
+const char* getStencilOpName (VkStencilOp value);
+const char* getLogicOpName (VkLogicOp value);
+const char* getBlendFactorName (VkBlendFactor value);
+const char* getBlendOpName (VkBlendOp value);
+const char* getDynamicStateName (VkDynamicState value);
+const char* getFilterName (VkFilter value);
+const char* getSamplerMipmapModeName (VkSamplerMipmapMode value);
+const char* getSamplerAddressModeName (VkSamplerAddressMode value);
+const char* getBorderColorName (VkBorderColor value);
+const char* getDescriptorTypeName (VkDescriptorType value);
+const char* getAttachmentLoadOpName (VkAttachmentLoadOp value);
+const char* getAttachmentStoreOpName (VkAttachmentStoreOp value);
+const char* getPipelineBindPointName (VkPipelineBindPoint value);
+const char* getCommandBufferLevelName (VkCommandBufferLevel value);
+const char* getIndexTypeName (VkIndexType value);
+const char* getSubpassContentsName (VkSubpassContents value);
+const char* getColorSpaceKHRName (VkColorSpaceKHR value);
+const char* getPresentModeKHRName (VkPresentModeKHR value);
+
+inline tcu::Format::Enum<VkResult> getResultStr (VkResult value) { return tcu::Format::Enum<VkResult>(getResultName, value); }
+inline tcu::Format::Enum<VkStructureType> getStructureTypeStr (VkStructureType value) { return tcu::Format::Enum<VkStructureType>(getStructureTypeName, value); }
+inline tcu::Format::Enum<VkSystemAllocationScope> getSystemAllocationScopeStr (VkSystemAllocationScope value) { return tcu::Format::Enum<VkSystemAllocationScope>(getSystemAllocationScopeName, value); }
+inline tcu::Format::Enum<VkInternalAllocationType> getInternalAllocationTypeStr (VkInternalAllocationType value) { return tcu::Format::Enum<VkInternalAllocationType>(getInternalAllocationTypeName, value); }
+inline tcu::Format::Enum<VkFormat> getFormatStr (VkFormat value) { return tcu::Format::Enum<VkFormat>(getFormatName, value); }
+inline tcu::Format::Enum<VkImageType> getImageTypeStr (VkImageType value) { return tcu::Format::Enum<VkImageType>(getImageTypeName, value); }
+inline tcu::Format::Enum<VkImageTiling> getImageTilingStr (VkImageTiling value) { return tcu::Format::Enum<VkImageTiling>(getImageTilingName, value); }
+inline tcu::Format::Enum<VkPhysicalDeviceType> getPhysicalDeviceTypeStr (VkPhysicalDeviceType value) { return tcu::Format::Enum<VkPhysicalDeviceType>(getPhysicalDeviceTypeName, value); }
+inline tcu::Format::Enum<VkQueryType> getQueryTypeStr (VkQueryType value) { return tcu::Format::Enum<VkQueryType>(getQueryTypeName, value); }
+inline tcu::Format::Enum<VkSharingMode> getSharingModeStr (VkSharingMode value) { return tcu::Format::Enum<VkSharingMode>(getSharingModeName, value); }
+inline tcu::Format::Enum<VkImageLayout> getImageLayoutStr (VkImageLayout value) { return tcu::Format::Enum<VkImageLayout>(getImageLayoutName, value); }
+inline tcu::Format::Enum<VkImageViewType> getImageViewTypeStr (VkImageViewType value) { return tcu::Format::Enum<VkImageViewType>(getImageViewTypeName, value); }
+inline tcu::Format::Enum<VkComponentSwizzle> getComponentSwizzleStr (VkComponentSwizzle value) { return tcu::Format::Enum<VkComponentSwizzle>(getComponentSwizzleName, value); }
+inline tcu::Format::Enum<VkVertexInputRate> getVertexInputRateStr (VkVertexInputRate value) { return tcu::Format::Enum<VkVertexInputRate>(getVertexInputRateName, value); }
+inline tcu::Format::Enum<VkPrimitiveTopology> getPrimitiveTopologyStr (VkPrimitiveTopology value) { return tcu::Format::Enum<VkPrimitiveTopology>(getPrimitiveTopologyName, value); }
+inline tcu::Format::Enum<VkPolygonMode> getPolygonModeStr (VkPolygonMode value) { return tcu::Format::Enum<VkPolygonMode>(getPolygonModeName, value); }
+inline tcu::Format::Enum<VkFrontFace> getFrontFaceStr (VkFrontFace value) { return tcu::Format::Enum<VkFrontFace>(getFrontFaceName, value); }
+inline tcu::Format::Enum<VkCompareOp> getCompareOpStr (VkCompareOp value) { return tcu::Format::Enum<VkCompareOp>(getCompareOpName, value); }
+inline tcu::Format::Enum<VkStencilOp> getStencilOpStr (VkStencilOp value) { return tcu::Format::Enum<VkStencilOp>(getStencilOpName, value); }
+inline tcu::Format::Enum<VkLogicOp> getLogicOpStr (VkLogicOp value) { return tcu::Format::Enum<VkLogicOp>(getLogicOpName, value); }
+inline tcu::Format::Enum<VkBlendFactor> getBlendFactorStr (VkBlendFactor value) { return tcu::Format::Enum<VkBlendFactor>(getBlendFactorName, value); }
+inline tcu::Format::Enum<VkBlendOp> getBlendOpStr (VkBlendOp value) { return tcu::Format::Enum<VkBlendOp>(getBlendOpName, value); }
+inline tcu::Format::Enum<VkDynamicState> getDynamicStateStr (VkDynamicState value) { return tcu::Format::Enum<VkDynamicState>(getDynamicStateName, value); }
+inline tcu::Format::Enum<VkFilter> getFilterStr (VkFilter value) { return tcu::Format::Enum<VkFilter>(getFilterName, value); }
+inline tcu::Format::Enum<VkSamplerMipmapMode> getSamplerMipmapModeStr (VkSamplerMipmapMode value) { return tcu::Format::Enum<VkSamplerMipmapMode>(getSamplerMipmapModeName, value); }
+inline tcu::Format::Enum<VkSamplerAddressMode> getSamplerAddressModeStr (VkSamplerAddressMode value) { return tcu::Format::Enum<VkSamplerAddressMode>(getSamplerAddressModeName, value); }
+inline tcu::Format::Enum<VkBorderColor> getBorderColorStr (VkBorderColor value) { return tcu::Format::Enum<VkBorderColor>(getBorderColorName, value); }
+inline tcu::Format::Enum<VkDescriptorType> getDescriptorTypeStr (VkDescriptorType value) { return tcu::Format::Enum<VkDescriptorType>(getDescriptorTypeName, value); }
+inline tcu::Format::Enum<VkAttachmentLoadOp> getAttachmentLoadOpStr (VkAttachmentLoadOp value) { return tcu::Format::Enum<VkAttachmentLoadOp>(getAttachmentLoadOpName, value); }
+inline tcu::Format::Enum<VkAttachmentStoreOp> getAttachmentStoreOpStr (VkAttachmentStoreOp value) { return tcu::Format::Enum<VkAttachmentStoreOp>(getAttachmentStoreOpName, value); }
+inline tcu::Format::Enum<VkPipelineBindPoint> getPipelineBindPointStr (VkPipelineBindPoint value) { return tcu::Format::Enum<VkPipelineBindPoint>(getPipelineBindPointName, value); }
+inline tcu::Format::Enum<VkCommandBufferLevel> getCommandBufferLevelStr (VkCommandBufferLevel value) { return tcu::Format::Enum<VkCommandBufferLevel>(getCommandBufferLevelName, value); }
+inline tcu::Format::Enum<VkIndexType> getIndexTypeStr (VkIndexType value) { return tcu::Format::Enum<VkIndexType>(getIndexTypeName, value); }
+inline tcu::Format::Enum<VkSubpassContents> getSubpassContentsStr (VkSubpassContents value) { return tcu::Format::Enum<VkSubpassContents>(getSubpassContentsName, value); }
+inline tcu::Format::Enum<VkColorSpaceKHR> getColorSpaceKHRStr (VkColorSpaceKHR value) { return tcu::Format::Enum<VkColorSpaceKHR>(getColorSpaceKHRName, value); }
+inline tcu::Format::Enum<VkPresentModeKHR> getPresentModeKHRStr (VkPresentModeKHR value) { return tcu::Format::Enum<VkPresentModeKHR>(getPresentModeKHRName, value); }
+
+inline std::ostream& operator<< (std::ostream& s, VkResult value) { return s << getResultStr(value); }
+inline std::ostream& operator<< (std::ostream& s, VkStructureType value) { return s << getStructureTypeStr(value); }
+inline std::ostream& operator<< (std::ostream& s, VkSystemAllocationScope value) { return s << getSystemAllocationScopeStr(value); }
+inline std::ostream& operator<< (std::ostream& s, VkInternalAllocationType value) { return s << getInternalAllocationTypeStr(value); }
+inline std::ostream& operator<< (std::ostream& s, VkFormat value) { return s << getFormatStr(value); }
+inline std::ostream& operator<< (std::ostream& s, VkImageType value) { return s << getImageTypeStr(value); }
+inline std::ostream& operator<< (std::ostream& s, VkImageTiling value) { return s << getImageTilingStr(value); }
+inline std::ostream& operator<< (std::ostream& s, VkPhysicalDeviceType value) { return s << getPhysicalDeviceTypeStr(value); }
+inline std::ostream& operator<< (std::ostream& s, VkQueryType value) { return s << getQueryTypeStr(value); }
+inline std::ostream& operator<< (std::ostream& s, VkSharingMode value) { return s << getSharingModeStr(value); }
+inline std::ostream& operator<< (std::ostream& s, VkImageLayout value) { return s << getImageLayoutStr(value); }
+inline std::ostream& operator<< (std::ostream& s, VkImageViewType value) { return s << getImageViewTypeStr(value); }
+inline std::ostream& operator<< (std::ostream& s, VkComponentSwizzle value) { return s << getComponentSwizzleStr(value); }
+inline std::ostream& operator<< (std::ostream& s, VkVertexInputRate value) { return s << getVertexInputRateStr(value); }
+inline std::ostream& operator<< (std::ostream& s, VkPrimitiveTopology value) { return s << getPrimitiveTopologyStr(value); }
+inline std::ostream& operator<< (std::ostream& s, VkPolygonMode value) { return s << getPolygonModeStr(value); }
+inline std::ostream& operator<< (std::ostream& s, VkFrontFace value) { return s << getFrontFaceStr(value); }
+inline std::ostream& operator<< (std::ostream& s, VkCompareOp value) { return s << getCompareOpStr(value); }
+inline std::ostream& operator<< (std::ostream& s, VkStencilOp value) { return s << getStencilOpStr(value); }
+inline std::ostream& operator<< (std::ostream& s, VkLogicOp value) { return s << getLogicOpStr(value); }
+inline std::ostream& operator<< (std::ostream& s, VkBlendFactor value) { return s << getBlendFactorStr(value); }
+inline std::ostream& operator<< (std::ostream& s, VkBlendOp value) { return s << getBlendOpStr(value); }
+inline std::ostream& operator<< (std::ostream& s, VkDynamicState value) { return s << getDynamicStateStr(value); }
+inline std::ostream& operator<< (std::ostream& s, VkFilter value) { return s << getFilterStr(value); }
+inline std::ostream& operator<< (std::ostream& s, VkSamplerMipmapMode value) { return s << getSamplerMipmapModeStr(value); }
+inline std::ostream& operator<< (std::ostream& s, VkSamplerAddressMode value) { return s << getSamplerAddressModeStr(value); }
+inline std::ostream& operator<< (std::ostream& s, VkBorderColor value) { return s << getBorderColorStr(value); }
+inline std::ostream& operator<< (std::ostream& s, VkDescriptorType value) { return s << getDescriptorTypeStr(value); }
+inline std::ostream& operator<< (std::ostream& s, VkAttachmentLoadOp value) { return s << getAttachmentLoadOpStr(value); }
+inline std::ostream& operator<< (std::ostream& s, VkAttachmentStoreOp value) { return s << getAttachmentStoreOpStr(value); }
+inline std::ostream& operator<< (std::ostream& s, VkPipelineBindPoint value) { return s << getPipelineBindPointStr(value); }
+inline std::ostream& operator<< (std::ostream& s, VkCommandBufferLevel value) { return s << getCommandBufferLevelStr(value); }
+inline std::ostream& operator<< (std::ostream& s, VkIndexType value) { return s << getIndexTypeStr(value); }
+inline std::ostream& operator<< (std::ostream& s, VkSubpassContents value) { return s << getSubpassContentsStr(value); }
+inline std::ostream& operator<< (std::ostream& s, VkColorSpaceKHR value) { return s << getColorSpaceKHRStr(value); }
+inline std::ostream& operator<< (std::ostream& s, VkPresentModeKHR value) { return s << getPresentModeKHRStr(value); }
+
+tcu::Format::Bitfield<32> getFormatFeatureFlagsStr (VkFormatFeatureFlags value);
+tcu::Format::Bitfield<32> getImageUsageFlagsStr (VkImageUsageFlags value);
+tcu::Format::Bitfield<32> getImageCreateFlagsStr (VkImageCreateFlags value);
+tcu::Format::Bitfield<32> getSampleCountFlagsStr (VkSampleCountFlags value);
+tcu::Format::Bitfield<32> getQueueFlagsStr (VkQueueFlags value);
+tcu::Format::Bitfield<32> getMemoryPropertyFlagsStr (VkMemoryPropertyFlags value);
+tcu::Format::Bitfield<32> getMemoryHeapFlagsStr (VkMemoryHeapFlags value);
+tcu::Format::Bitfield<32> getImageAspectFlagsStr (VkImageAspectFlags value);
+tcu::Format::Bitfield<32> getSparseImageFormatFlagsStr (VkSparseImageFormatFlags value);
+tcu::Format::Bitfield<32> getSparseMemoryBindFlagsStr (VkSparseMemoryBindFlags value);
+tcu::Format::Bitfield<32> getFenceCreateFlagsStr (VkFenceCreateFlags value);
+tcu::Format::Bitfield<32> getQueryPipelineStatisticFlagsStr (VkQueryPipelineStatisticFlags value);
+tcu::Format::Bitfield<32> getQueryResultFlagsStr (VkQueryResultFlags value);
+tcu::Format::Bitfield<32> getBufferCreateFlagsStr (VkBufferCreateFlags value);
+tcu::Format::Bitfield<32> getBufferUsageFlagsStr (VkBufferUsageFlags value);
+tcu::Format::Bitfield<32> getPipelineCreateFlagsStr (VkPipelineCreateFlags value);
+tcu::Format::Bitfield<32> getShaderStageFlagsStr (VkShaderStageFlags value);
+tcu::Format::Bitfield<32> getCullModeFlagsStr (VkCullModeFlags value);
+tcu::Format::Bitfield<32> getColorComponentFlagsStr (VkColorComponentFlags value);
+tcu::Format::Bitfield<32> getDescriptorPoolCreateFlagsStr (VkDescriptorPoolCreateFlags value);
+tcu::Format::Bitfield<32> getAttachmentDescriptionFlagsStr (VkAttachmentDescriptionFlags value);
+tcu::Format::Bitfield<32> getPipelineStageFlagsStr (VkPipelineStageFlags value);
+tcu::Format::Bitfield<32> getAccessFlagsStr (VkAccessFlags value);
+tcu::Format::Bitfield<32> getDependencyFlagsStr (VkDependencyFlags value);
+tcu::Format::Bitfield<32> getCommandPoolCreateFlagsStr (VkCommandPoolCreateFlags value);
+tcu::Format::Bitfield<32> getCommandPoolResetFlagsStr (VkCommandPoolResetFlags value);
+tcu::Format::Bitfield<32> getCommandBufferUsageFlagsStr (VkCommandBufferUsageFlags value);
+tcu::Format::Bitfield<32> getQueryControlFlagsStr (VkQueryControlFlags value);
+tcu::Format::Bitfield<32> getCommandBufferResetFlagsStr (VkCommandBufferResetFlags value);
+tcu::Format::Bitfield<32> getStencilFaceFlagsStr (VkStencilFaceFlags value);
+tcu::Format::Bitfield<32> getSurfaceTransformFlagsKHRStr (VkSurfaceTransformFlagsKHR value);
+tcu::Format::Bitfield<32> getCompositeAlphaFlagsKHRStr (VkCompositeAlphaFlagsKHR value);
+tcu::Format::Bitfield<32> getDisplayPlaneAlphaFlagsKHRStr (VkDisplayPlaneAlphaFlagsKHR value);
+tcu::Format::Bitfield<32> getInstanceCreateFlagsStr (VkInstanceCreateFlags value);
+tcu::Format::Bitfield<32> getDeviceCreateFlagsStr (VkDeviceCreateFlags value);
+tcu::Format::Bitfield<32> getDeviceQueueCreateFlagsStr (VkDeviceQueueCreateFlags value);
+tcu::Format::Bitfield<32> getMemoryMapFlagsStr (VkMemoryMapFlags value);
+tcu::Format::Bitfield<32> getSemaphoreCreateFlagsStr (VkSemaphoreCreateFlags value);
+tcu::Format::Bitfield<32> getEventCreateFlagsStr (VkEventCreateFlags value);
+tcu::Format::Bitfield<32> getQueryPoolCreateFlagsStr (VkQueryPoolCreateFlags value);
+tcu::Format::Bitfield<32> getBufferViewCreateFlagsStr (VkBufferViewCreateFlags value);
+tcu::Format::Bitfield<32> getImageViewCreateFlagsStr (VkImageViewCreateFlags value);
+tcu::Format::Bitfield<32> getShaderModuleCreateFlagsStr (VkShaderModuleCreateFlags value);
+tcu::Format::Bitfield<32> getPipelineCacheCreateFlagsStr (VkPipelineCacheCreateFlags value);
+tcu::Format::Bitfield<32> getPipelineShaderStageCreateFlagsStr (VkPipelineShaderStageCreateFlags value);
+tcu::Format::Bitfield<32> getPipelineVertexInputStateCreateFlagsStr (VkPipelineVertexInputStateCreateFlags value);
+tcu::Format::Bitfield<32> getPipelineInputAssemblyStateCreateFlagsStr (VkPipelineInputAssemblyStateCreateFlags value);
+tcu::Format::Bitfield<32> getPipelineTesselationStateCreateFlagsStr (VkPipelineTesselationStateCreateFlags value);
+tcu::Format::Bitfield<32> getPipelineViewportStateCreateFlagsStr (VkPipelineViewportStateCreateFlags value);
+tcu::Format::Bitfield<32> getPipelineRasterizationStateCreateFlagsStr (VkPipelineRasterizationStateCreateFlags value);
+tcu::Format::Bitfield<32> getPipelineMultisampleStateCreateFlagsStr (VkPipelineMultisampleStateCreateFlags value);
+tcu::Format::Bitfield<32> getPipelineDepthStencilStateCreateFlagsStr (VkPipelineDepthStencilStateCreateFlags value);
+tcu::Format::Bitfield<32> getPipelineColorBlendStateCreateFlagsStr (VkPipelineColorBlendStateCreateFlags value);
+tcu::Format::Bitfield<32> getPipelineDynamicStateCreateFlagsStr (VkPipelineDynamicStateCreateFlags value);
+tcu::Format::Bitfield<32> getPipelineLayoutCreateFlagsStr (VkPipelineLayoutCreateFlags value);
+tcu::Format::Bitfield<32> getSamplerCreateFlagsStr (VkSamplerCreateFlags value);
+tcu::Format::Bitfield<32> getDescriptorSetLayoutCreateFlagsStr (VkDescriptorSetLayoutCreateFlags value);
+tcu::Format::Bitfield<32> getDescriptorPoolResetFlagsStr (VkDescriptorPoolResetFlags value);
+tcu::Format::Bitfield<32> getFramebufferCreateFlagsStr (VkFramebufferCreateFlags value);
+tcu::Format::Bitfield<32> getRenderPassCreateFlagsStr (VkRenderPassCreateFlags value);
+tcu::Format::Bitfield<32> getSubpassDescriptionFlagsStr (VkSubpassDescriptionFlags value);
+tcu::Format::Bitfield<32> getSwapchainCreateFlagsKHRStr (VkSwapchainCreateFlagsKHR value);
+tcu::Format::Bitfield<32> getDisplayModeCreateFlagsKHRStr (VkDisplayModeCreateFlagsKHR value);
+tcu::Format::Bitfield<32> getDisplaySurfaceCreateFlagsKHRStr (VkDisplaySurfaceCreateFlagsKHR value);
+
+std::ostream& operator<< (std::ostream& s, const VkApplicationInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkInstanceCreateInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkAllocationCallbacks& value);
+std::ostream& operator<< (std::ostream& s, const VkPhysicalDeviceFeatures& value);
+std::ostream& operator<< (std::ostream& s, const VkFormatProperties& value);
+std::ostream& operator<< (std::ostream& s, const VkExtent3D& value);
+std::ostream& operator<< (std::ostream& s, const VkImageFormatProperties& value);
+std::ostream& operator<< (std::ostream& s, const VkPhysicalDeviceLimits& value);
+std::ostream& operator<< (std::ostream& s, const VkPhysicalDeviceSparseProperties& value);
+std::ostream& operator<< (std::ostream& s, const VkPhysicalDeviceProperties& value);
+std::ostream& operator<< (std::ostream& s, const VkQueueFamilyProperties& value);
+std::ostream& operator<< (std::ostream& s, const VkMemoryType& value);
+std::ostream& operator<< (std::ostream& s, const VkMemoryHeap& value);
+std::ostream& operator<< (std::ostream& s, const VkPhysicalDeviceMemoryProperties& value);
+std::ostream& operator<< (std::ostream& s, const VkDeviceQueueCreateInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkDeviceCreateInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkExtensionProperties& value);
+std::ostream& operator<< (std::ostream& s, const VkLayerProperties& value);
+std::ostream& operator<< (std::ostream& s, const VkSubmitInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkMemoryAllocateInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkMappedMemoryRange& value);
+std::ostream& operator<< (std::ostream& s, const VkMemoryRequirements& value);
+std::ostream& operator<< (std::ostream& s, const VkSparseImageFormatProperties& value);
+std::ostream& operator<< (std::ostream& s, const VkSparseImageMemoryRequirements& value);
+std::ostream& operator<< (std::ostream& s, const VkSparseMemoryBind& value);
+std::ostream& operator<< (std::ostream& s, const VkSparseBufferMemoryBindInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkSparseImageOpaqueMemoryBindInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkImageSubresource& value);
+std::ostream& operator<< (std::ostream& s, const VkOffset3D& value);
+std::ostream& operator<< (std::ostream& s, const VkSparseImageMemoryBind& value);
+std::ostream& operator<< (std::ostream& s, const VkSparseImageMemoryBindInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkBindSparseInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkFenceCreateInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkSemaphoreCreateInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkEventCreateInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkQueryPoolCreateInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkBufferCreateInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkBufferViewCreateInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkImageCreateInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkSubresourceLayout& value);
+std::ostream& operator<< (std::ostream& s, const VkComponentMapping& value);
+std::ostream& operator<< (std::ostream& s, const VkImageSubresourceRange& value);
+std::ostream& operator<< (std::ostream& s, const VkImageViewCreateInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkShaderModuleCreateInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkPipelineCacheCreateInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkSpecializationMapEntry& value);
+std::ostream& operator<< (std::ostream& s, const VkSpecializationInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkPipelineShaderStageCreateInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkVertexInputBindingDescription& value);
+std::ostream& operator<< (std::ostream& s, const VkVertexInputAttributeDescription& value);
+std::ostream& operator<< (std::ostream& s, const VkPipelineVertexInputStateCreateInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkPipelineInputAssemblyStateCreateInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkPipelineTessellationStateCreateInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkViewport& value);
+std::ostream& operator<< (std::ostream& s, const VkOffset2D& value);
+std::ostream& operator<< (std::ostream& s, const VkExtent2D& value);
+std::ostream& operator<< (std::ostream& s, const VkRect2D& value);
+std::ostream& operator<< (std::ostream& s, const VkPipelineViewportStateCreateInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkPipelineRasterizationStateCreateInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkPipelineMultisampleStateCreateInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkStencilOpState& value);
+std::ostream& operator<< (std::ostream& s, const VkPipelineDepthStencilStateCreateInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkPipelineColorBlendAttachmentState& value);
+std::ostream& operator<< (std::ostream& s, const VkPipelineColorBlendStateCreateInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkPipelineDynamicStateCreateInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkGraphicsPipelineCreateInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkComputePipelineCreateInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkPushConstantRange& value);
+std::ostream& operator<< (std::ostream& s, const VkPipelineLayoutCreateInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkSamplerCreateInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkDescriptorSetLayoutBinding& value);
+std::ostream& operator<< (std::ostream& s, const VkDescriptorSetLayoutCreateInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkDescriptorPoolSize& value);
+std::ostream& operator<< (std::ostream& s, const VkDescriptorPoolCreateInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkDescriptorSetAllocateInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkDescriptorImageInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkDescriptorBufferInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkWriteDescriptorSet& value);
+std::ostream& operator<< (std::ostream& s, const VkCopyDescriptorSet& value);
+std::ostream& operator<< (std::ostream& s, const VkFramebufferCreateInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkAttachmentDescription& value);
+std::ostream& operator<< (std::ostream& s, const VkAttachmentReference& value);
+std::ostream& operator<< (std::ostream& s, const VkSubpassDescription& value);
+std::ostream& operator<< (std::ostream& s, const VkSubpassDependency& value);
+std::ostream& operator<< (std::ostream& s, const VkRenderPassCreateInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkCommandPoolCreateInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkCommandBufferAllocateInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkCommandBufferBeginInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkBufferCopy& value);
+std::ostream& operator<< (std::ostream& s, const VkImageSubresourceLayers& value);
+std::ostream& operator<< (std::ostream& s, const VkImageCopy& value);
+std::ostream& operator<< (std::ostream& s, const VkImageBlit& value);
+std::ostream& operator<< (std::ostream& s, const VkBufferImageCopy& value);
+std::ostream& operator<< (std::ostream& s, const VkClearColorValue& value);
+std::ostream& operator<< (std::ostream& s, const VkClearDepthStencilValue& value);
+std::ostream& operator<< (std::ostream& s, const VkClearValue& value);
+std::ostream& operator<< (std::ostream& s, const VkClearAttachment& value);
+std::ostream& operator<< (std::ostream& s, const VkClearRect& value);
+std::ostream& operator<< (std::ostream& s, const VkImageResolve& value);
+std::ostream& operator<< (std::ostream& s, const VkRenderPassBeginInfo& value);
+std::ostream& operator<< (std::ostream& s, const VkBufferMemoryBarrier& value);
+std::ostream& operator<< (std::ostream& s, const VkDispatchIndirectCommand& value);
+std::ostream& operator<< (std::ostream& s, const VkDrawIndexedIndirectCommand& value);
+std::ostream& operator<< (std::ostream& s, const VkDrawIndirectCommand& value);
+std::ostream& operator<< (std::ostream& s, const VkImageMemoryBarrier& value);
+std::ostream& operator<< (std::ostream& s, const VkMemoryBarrier& value);
+std::ostream& operator<< (std::ostream& s, const VkSurfaceCapabilitiesKHR& value);
+std::ostream& operator<< (std::ostream& s, const VkSurfaceFormatKHR& value);
+std::ostream& operator<< (std::ostream& s, const VkSwapchainCreateInfoKHR& value);
+std::ostream& operator<< (std::ostream& s, const VkPresentInfoKHR& value);
+std::ostream& operator<< (std::ostream& s, const VkDisplayPropertiesKHR& value);
+std::ostream& operator<< (std::ostream& s, const VkDisplayModeParametersKHR& value);
+std::ostream& operator<< (std::ostream& s, const VkDisplayModePropertiesKHR& value);
+std::ostream& operator<< (std::ostream& s, const VkDisplayModeCreateInfoKHR& value);
+std::ostream& operator<< (std::ostream& s, const VkDisplayPlaneCapabilitiesKHR& value);
+std::ostream& operator<< (std::ostream& s, const VkDisplayPlanePropertiesKHR& value);
+std::ostream& operator<< (std::ostream& s, const VkDisplaySurfaceCreateInfoKHR& value);
+std::ostream& operator<< (std::ostream& s, const VkDisplayPresentInfoKHR& value);
--- /dev/null
+/* WARNING: This is auto-generated file. Do not modify, since changes will
+ * be lost! Modify the generating script instead.
+ */
+template<> const char* getTypeName<VkInstance> (void) { return "VkInstance"; }
+template<> const char* getTypeName<VkPhysicalDevice> (void) { return "VkPhysicalDevice"; }
+template<> const char* getTypeName<VkDevice> (void) { return "VkDevice"; }
+template<> const char* getTypeName<VkQueue> (void) { return "VkQueue"; }
+template<> const char* getTypeName<VkSemaphore> (void) { return "VkSemaphore"; }
+template<> const char* getTypeName<VkCommandBuffer> (void) { return "VkCommandBuffer"; }
+template<> const char* getTypeName<VkFence> (void) { return "VkFence"; }
+template<> const char* getTypeName<VkDeviceMemory> (void) { return "VkDeviceMemory"; }
+template<> const char* getTypeName<VkBuffer> (void) { return "VkBuffer"; }
+template<> const char* getTypeName<VkImage> (void) { return "VkImage"; }
+template<> const char* getTypeName<VkEvent> (void) { return "VkEvent"; }
+template<> const char* getTypeName<VkQueryPool> (void) { return "VkQueryPool"; }
+template<> const char* getTypeName<VkBufferView> (void) { return "VkBufferView"; }
+template<> const char* getTypeName<VkImageView> (void) { return "VkImageView"; }
+template<> const char* getTypeName<VkShaderModule> (void) { return "VkShaderModule"; }
+template<> const char* getTypeName<VkPipelineCache> (void) { return "VkPipelineCache"; }
+template<> const char* getTypeName<VkPipelineLayout> (void) { return "VkPipelineLayout"; }
+template<> const char* getTypeName<VkRenderPass> (void) { return "VkRenderPass"; }
+template<> const char* getTypeName<VkPipeline> (void) { return "VkPipeline"; }
+template<> const char* getTypeName<VkDescriptorSetLayout> (void) { return "VkDescriptorSetLayout"; }
+template<> const char* getTypeName<VkSampler> (void) { return "VkSampler"; }
+template<> const char* getTypeName<VkDescriptorPool> (void) { return "VkDescriptorPool"; }
+template<> const char* getTypeName<VkDescriptorSet> (void) { return "VkDescriptorSet"; }
+template<> const char* getTypeName<VkFramebuffer> (void) { return "VkFramebuffer"; }
+template<> const char* getTypeName<VkCommandPool> (void) { return "VkCommandPool"; }
+template<> const char* getTypeName<VkSurfaceKHR> (void) { return "VkSurfaceKHR"; }
+template<> const char* getTypeName<VkSwapchainKHR> (void) { return "VkSwapchainKHR"; }
+template<> const char* getTypeName<VkDisplayKHR> (void) { return "VkDisplayKHR"; }
+template<> const char* getTypeName<VkDisplayModeKHR> (void) { return "VkDisplayModeKHR"; }
+
+const char* getResultName (VkResult value)
+{
+ switch (value)
+ {
+ case VK_SUCCESS: return "VK_SUCCESS";
+ case VK_NOT_READY: return "VK_NOT_READY";
+ case VK_TIMEOUT: return "VK_TIMEOUT";
+ case VK_EVENT_SET: return "VK_EVENT_SET";
+ case VK_EVENT_RESET: return "VK_EVENT_RESET";
+ case VK_INCOMPLETE: return "VK_INCOMPLETE";
+ case VK_ERROR_OUT_OF_HOST_MEMORY: return "VK_ERROR_OUT_OF_HOST_MEMORY";
+ case VK_ERROR_OUT_OF_DEVICE_MEMORY: return "VK_ERROR_OUT_OF_DEVICE_MEMORY";
+ case VK_ERROR_INITIALIZATION_FAILED: return "VK_ERROR_INITIALIZATION_FAILED";
+ case VK_ERROR_DEVICE_LOST: return "VK_ERROR_DEVICE_LOST";
+ case VK_ERROR_MEMORY_MAP_FAILED: return "VK_ERROR_MEMORY_MAP_FAILED";
+ case VK_ERROR_LAYER_NOT_PRESENT: return "VK_ERROR_LAYER_NOT_PRESENT";
+ case VK_ERROR_EXTENSION_NOT_PRESENT: return "VK_ERROR_EXTENSION_NOT_PRESENT";
+ case VK_ERROR_FEATURE_NOT_PRESENT: return "VK_ERROR_FEATURE_NOT_PRESENT";
+ case VK_ERROR_INCOMPATIBLE_DRIVER: return "VK_ERROR_INCOMPATIBLE_DRIVER";
+ case VK_ERROR_TOO_MANY_OBJECTS: return "VK_ERROR_TOO_MANY_OBJECTS";
+ case VK_ERROR_FORMAT_NOT_SUPPORTED: return "VK_ERROR_FORMAT_NOT_SUPPORTED";
+ case VK_ERROR_SURFACE_LOST_KHR: return "VK_ERROR_SURFACE_LOST_KHR";
+ case VK_SUBOPTIMAL_KHR: return "VK_SUBOPTIMAL_KHR";
+ case VK_ERROR_OUT_OF_DATE_KHR: return "VK_ERROR_OUT_OF_DATE_KHR";
+ case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR: return "VK_ERROR_INCOMPATIBLE_DISPLAY_KHR";
+ case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: return "VK_ERROR_NATIVE_WINDOW_IN_USE_KHR";
+ default: return DE_NULL;
+ }
+}
+
+const char* getStructureTypeName (VkStructureType value)
+{
+ switch (value)
+ {
+ case VK_STRUCTURE_TYPE_APPLICATION_INFO: return "VK_STRUCTURE_TYPE_APPLICATION_INFO";
+ case VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO: return "VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO: return "VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO: return "VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_SUBMIT_INFO: return "VK_STRUCTURE_TYPE_SUBMIT_INFO";
+ case VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO: return "VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO";
+ case VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE: return "VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE";
+ case VK_STRUCTURE_TYPE_BIND_SPARSE_INFO: return "VK_STRUCTURE_TYPE_BIND_SPARSE_INFO";
+ case VK_STRUCTURE_TYPE_FENCE_CREATE_INFO: return "VK_STRUCTURE_TYPE_FENCE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO: return "VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_EVENT_CREATE_INFO: return "VK_STRUCTURE_TYPE_EVENT_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO: return "VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO: return "VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO: return "VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO: return "VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO: return "VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO: return "VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO: return "VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO: return "VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO: return "VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO: return "VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO: return "VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO: return "VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO: return "VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO: return "VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO: return "VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO: return "VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO: return "VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO: return "VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO: return "VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO: return "VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO: return "VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO: return "VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO: return "VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO: return "VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO";
+ case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET: return "VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET";
+ case VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET: return "VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET";
+ case VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO: return "VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO: return "VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO: return "VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO: return "VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO";
+ case VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO: return "VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO";
+ case VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO: return "VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO";
+ case VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER: return "VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER";
+ case VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER: return "VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER";
+ case VK_STRUCTURE_TYPE_MEMORY_BARRIER: return "VK_STRUCTURE_TYPE_MEMORY_BARRIER";
+ case VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO: return "VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO: return "VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR: return "VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR";
+ case VK_STRUCTURE_TYPE_PRESENT_INFO_KHR: return "VK_STRUCTURE_TYPE_PRESENT_INFO_KHR";
+ case VK_STRUCTURE_TYPE_DISPLAY_MODE_CREATE_INFO_KHR: return "VK_STRUCTURE_TYPE_DISPLAY_MODE_CREATE_INFO_KHR";
+ case VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR: return "VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR";
+ case VK_STRUCTURE_TYPE_DISPLAY_PRESENT_INFO_KHR: return "VK_STRUCTURE_TYPE_DISPLAY_PRESENT_INFO_KHR";
+ default: return DE_NULL;
+ }
+}
+
+const char* getSystemAllocationScopeName (VkSystemAllocationScope value)
+{
+ switch (value)
+ {
+ case VK_SYSTEM_ALLOCATION_SCOPE_COMMAND: return "VK_SYSTEM_ALLOCATION_SCOPE_COMMAND";
+ case VK_SYSTEM_ALLOCATION_SCOPE_OBJECT: return "VK_SYSTEM_ALLOCATION_SCOPE_OBJECT";
+ case VK_SYSTEM_ALLOCATION_SCOPE_CACHE: return "VK_SYSTEM_ALLOCATION_SCOPE_CACHE";
+ case VK_SYSTEM_ALLOCATION_SCOPE_DEVICE: return "VK_SYSTEM_ALLOCATION_SCOPE_DEVICE";
+ case VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE: return "VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE";
+ default: return DE_NULL;
+ }
+}
+
+const char* getInternalAllocationTypeName (VkInternalAllocationType value)
+{
+ switch (value)
+ {
+ case VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE: return "VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE";
+ default: return DE_NULL;
+ }
+}
+
+const char* getFormatName (VkFormat value)
+{
+ switch (value)
+ {
+ case VK_FORMAT_UNDEFINED: return "VK_FORMAT_UNDEFINED";
+ case VK_FORMAT_R4G4_UNORM_PACK8: return "VK_FORMAT_R4G4_UNORM_PACK8";
+ case VK_FORMAT_R4G4B4A4_UNORM_PACK16: return "VK_FORMAT_R4G4B4A4_UNORM_PACK16";
+ case VK_FORMAT_B4G4R4A4_UNORM_PACK16: return "VK_FORMAT_B4G4R4A4_UNORM_PACK16";
+ case VK_FORMAT_R5G6B5_UNORM_PACK16: return "VK_FORMAT_R5G6B5_UNORM_PACK16";
+ case VK_FORMAT_B5G6R5_UNORM_PACK16: return "VK_FORMAT_B5G6R5_UNORM_PACK16";
+ case VK_FORMAT_R5G5B5A1_UNORM_PACK16: return "VK_FORMAT_R5G5B5A1_UNORM_PACK16";
+ case VK_FORMAT_B5G5R5A1_UNORM_PACK16: return "VK_FORMAT_B5G5R5A1_UNORM_PACK16";
+ case VK_FORMAT_A1R5G5B5_UNORM_PACK16: return "VK_FORMAT_A1R5G5B5_UNORM_PACK16";
+ case VK_FORMAT_R8_UNORM: return "VK_FORMAT_R8_UNORM";
+ case VK_FORMAT_R8_SNORM: return "VK_FORMAT_R8_SNORM";
+ case VK_FORMAT_R8_USCALED: return "VK_FORMAT_R8_USCALED";
+ case VK_FORMAT_R8_SSCALED: return "VK_FORMAT_R8_SSCALED";
+ case VK_FORMAT_R8_UINT: return "VK_FORMAT_R8_UINT";
+ case VK_FORMAT_R8_SINT: return "VK_FORMAT_R8_SINT";
+ case VK_FORMAT_R8_SRGB: return "VK_FORMAT_R8_SRGB";
+ case VK_FORMAT_R8G8_UNORM: return "VK_FORMAT_R8G8_UNORM";
+ case VK_FORMAT_R8G8_SNORM: return "VK_FORMAT_R8G8_SNORM";
+ case VK_FORMAT_R8G8_USCALED: return "VK_FORMAT_R8G8_USCALED";
+ case VK_FORMAT_R8G8_SSCALED: return "VK_FORMAT_R8G8_SSCALED";
+ case VK_FORMAT_R8G8_UINT: return "VK_FORMAT_R8G8_UINT";
+ case VK_FORMAT_R8G8_SINT: return "VK_FORMAT_R8G8_SINT";
+ case VK_FORMAT_R8G8_SRGB: return "VK_FORMAT_R8G8_SRGB";
+ case VK_FORMAT_R8G8B8_UNORM: return "VK_FORMAT_R8G8B8_UNORM";
+ case VK_FORMAT_R8G8B8_SNORM: return "VK_FORMAT_R8G8B8_SNORM";
+ case VK_FORMAT_R8G8B8_USCALED: return "VK_FORMAT_R8G8B8_USCALED";
+ case VK_FORMAT_R8G8B8_SSCALED: return "VK_FORMAT_R8G8B8_SSCALED";
+ case VK_FORMAT_R8G8B8_UINT: return "VK_FORMAT_R8G8B8_UINT";
+ case VK_FORMAT_R8G8B8_SINT: return "VK_FORMAT_R8G8B8_SINT";
+ case VK_FORMAT_R8G8B8_SRGB: return "VK_FORMAT_R8G8B8_SRGB";
+ case VK_FORMAT_B8G8R8_UNORM: return "VK_FORMAT_B8G8R8_UNORM";
+ case VK_FORMAT_B8G8R8_SNORM: return "VK_FORMAT_B8G8R8_SNORM";
+ case VK_FORMAT_B8G8R8_USCALED: return "VK_FORMAT_B8G8R8_USCALED";
+ case VK_FORMAT_B8G8R8_SSCALED: return "VK_FORMAT_B8G8R8_SSCALED";
+ case VK_FORMAT_B8G8R8_UINT: return "VK_FORMAT_B8G8R8_UINT";
+ case VK_FORMAT_B8G8R8_SINT: return "VK_FORMAT_B8G8R8_SINT";
+ case VK_FORMAT_B8G8R8_SRGB: return "VK_FORMAT_B8G8R8_SRGB";
+ case VK_FORMAT_R8G8B8A8_UNORM: return "VK_FORMAT_R8G8B8A8_UNORM";
+ case VK_FORMAT_R8G8B8A8_SNORM: return "VK_FORMAT_R8G8B8A8_SNORM";
+ case VK_FORMAT_R8G8B8A8_USCALED: return "VK_FORMAT_R8G8B8A8_USCALED";
+ case VK_FORMAT_R8G8B8A8_SSCALED: return "VK_FORMAT_R8G8B8A8_SSCALED";
+ case VK_FORMAT_R8G8B8A8_UINT: return "VK_FORMAT_R8G8B8A8_UINT";
+ case VK_FORMAT_R8G8B8A8_SINT: return "VK_FORMAT_R8G8B8A8_SINT";
+ case VK_FORMAT_R8G8B8A8_SRGB: return "VK_FORMAT_R8G8B8A8_SRGB";
+ case VK_FORMAT_B8G8R8A8_UNORM: return "VK_FORMAT_B8G8R8A8_UNORM";
+ case VK_FORMAT_B8G8R8A8_SNORM: return "VK_FORMAT_B8G8R8A8_SNORM";
+ case VK_FORMAT_B8G8R8A8_USCALED: return "VK_FORMAT_B8G8R8A8_USCALED";
+ case VK_FORMAT_B8G8R8A8_SSCALED: return "VK_FORMAT_B8G8R8A8_SSCALED";
+ case VK_FORMAT_B8G8R8A8_UINT: return "VK_FORMAT_B8G8R8A8_UINT";
+ case VK_FORMAT_B8G8R8A8_SINT: return "VK_FORMAT_B8G8R8A8_SINT";
+ case VK_FORMAT_B8G8R8A8_SRGB: return "VK_FORMAT_B8G8R8A8_SRGB";
+ case VK_FORMAT_A8B8G8R8_UNORM_PACK32: return "VK_FORMAT_A8B8G8R8_UNORM_PACK32";
+ case VK_FORMAT_A8B8G8R8_SNORM_PACK32: return "VK_FORMAT_A8B8G8R8_SNORM_PACK32";
+ case VK_FORMAT_A8B8G8R8_USCALED_PACK32: return "VK_FORMAT_A8B8G8R8_USCALED_PACK32";
+ case VK_FORMAT_A8B8G8R8_SSCALED_PACK32: return "VK_FORMAT_A8B8G8R8_SSCALED_PACK32";
+ case VK_FORMAT_A8B8G8R8_UINT_PACK32: return "VK_FORMAT_A8B8G8R8_UINT_PACK32";
+ case VK_FORMAT_A8B8G8R8_SINT_PACK32: return "VK_FORMAT_A8B8G8R8_SINT_PACK32";
+ case VK_FORMAT_A8B8G8R8_SRGB_PACK32: return "VK_FORMAT_A8B8G8R8_SRGB_PACK32";
+ case VK_FORMAT_A2R10G10B10_UNORM_PACK32: return "VK_FORMAT_A2R10G10B10_UNORM_PACK32";
+ case VK_FORMAT_A2R10G10B10_SNORM_PACK32: return "VK_FORMAT_A2R10G10B10_SNORM_PACK32";
+ case VK_FORMAT_A2R10G10B10_USCALED_PACK32: return "VK_FORMAT_A2R10G10B10_USCALED_PACK32";
+ case VK_FORMAT_A2R10G10B10_SSCALED_PACK32: return "VK_FORMAT_A2R10G10B10_SSCALED_PACK32";
+ case VK_FORMAT_A2R10G10B10_UINT_PACK32: return "VK_FORMAT_A2R10G10B10_UINT_PACK32";
+ case VK_FORMAT_A2R10G10B10_SINT_PACK32: return "VK_FORMAT_A2R10G10B10_SINT_PACK32";
+ case VK_FORMAT_A2B10G10R10_UNORM_PACK32: return "VK_FORMAT_A2B10G10R10_UNORM_PACK32";
+ case VK_FORMAT_A2B10G10R10_SNORM_PACK32: return "VK_FORMAT_A2B10G10R10_SNORM_PACK32";
+ case VK_FORMAT_A2B10G10R10_USCALED_PACK32: return "VK_FORMAT_A2B10G10R10_USCALED_PACK32";
+ case VK_FORMAT_A2B10G10R10_SSCALED_PACK32: return "VK_FORMAT_A2B10G10R10_SSCALED_PACK32";
+ case VK_FORMAT_A2B10G10R10_UINT_PACK32: return "VK_FORMAT_A2B10G10R10_UINT_PACK32";
+ case VK_FORMAT_A2B10G10R10_SINT_PACK32: return "VK_FORMAT_A2B10G10R10_SINT_PACK32";
+ case VK_FORMAT_R16_UNORM: return "VK_FORMAT_R16_UNORM";
+ case VK_FORMAT_R16_SNORM: return "VK_FORMAT_R16_SNORM";
+ case VK_FORMAT_R16_USCALED: return "VK_FORMAT_R16_USCALED";
+ case VK_FORMAT_R16_SSCALED: return "VK_FORMAT_R16_SSCALED";
+ case VK_FORMAT_R16_UINT: return "VK_FORMAT_R16_UINT";
+ case VK_FORMAT_R16_SINT: return "VK_FORMAT_R16_SINT";
+ case VK_FORMAT_R16_SFLOAT: return "VK_FORMAT_R16_SFLOAT";
+ case VK_FORMAT_R16G16_UNORM: return "VK_FORMAT_R16G16_UNORM";
+ case VK_FORMAT_R16G16_SNORM: return "VK_FORMAT_R16G16_SNORM";
+ case VK_FORMAT_R16G16_USCALED: return "VK_FORMAT_R16G16_USCALED";
+ case VK_FORMAT_R16G16_SSCALED: return "VK_FORMAT_R16G16_SSCALED";
+ case VK_FORMAT_R16G16_UINT: return "VK_FORMAT_R16G16_UINT";
+ case VK_FORMAT_R16G16_SINT: return "VK_FORMAT_R16G16_SINT";
+ case VK_FORMAT_R16G16_SFLOAT: return "VK_FORMAT_R16G16_SFLOAT";
+ case VK_FORMAT_R16G16B16_UNORM: return "VK_FORMAT_R16G16B16_UNORM";
+ case VK_FORMAT_R16G16B16_SNORM: return "VK_FORMAT_R16G16B16_SNORM";
+ case VK_FORMAT_R16G16B16_USCALED: return "VK_FORMAT_R16G16B16_USCALED";
+ case VK_FORMAT_R16G16B16_SSCALED: return "VK_FORMAT_R16G16B16_SSCALED";
+ case VK_FORMAT_R16G16B16_UINT: return "VK_FORMAT_R16G16B16_UINT";
+ case VK_FORMAT_R16G16B16_SINT: return "VK_FORMAT_R16G16B16_SINT";
+ case VK_FORMAT_R16G16B16_SFLOAT: return "VK_FORMAT_R16G16B16_SFLOAT";
+ case VK_FORMAT_R16G16B16A16_UNORM: return "VK_FORMAT_R16G16B16A16_UNORM";
+ case VK_FORMAT_R16G16B16A16_SNORM: return "VK_FORMAT_R16G16B16A16_SNORM";
+ case VK_FORMAT_R16G16B16A16_USCALED: return "VK_FORMAT_R16G16B16A16_USCALED";
+ case VK_FORMAT_R16G16B16A16_SSCALED: return "VK_FORMAT_R16G16B16A16_SSCALED";
+ case VK_FORMAT_R16G16B16A16_UINT: return "VK_FORMAT_R16G16B16A16_UINT";
+ case VK_FORMAT_R16G16B16A16_SINT: return "VK_FORMAT_R16G16B16A16_SINT";
+ case VK_FORMAT_R16G16B16A16_SFLOAT: return "VK_FORMAT_R16G16B16A16_SFLOAT";
+ case VK_FORMAT_R32_UINT: return "VK_FORMAT_R32_UINT";
+ case VK_FORMAT_R32_SINT: return "VK_FORMAT_R32_SINT";
+ case VK_FORMAT_R32_SFLOAT: return "VK_FORMAT_R32_SFLOAT";
+ case VK_FORMAT_R32G32_UINT: return "VK_FORMAT_R32G32_UINT";
+ case VK_FORMAT_R32G32_SINT: return "VK_FORMAT_R32G32_SINT";
+ case VK_FORMAT_R32G32_SFLOAT: return "VK_FORMAT_R32G32_SFLOAT";
+ case VK_FORMAT_R32G32B32_UINT: return "VK_FORMAT_R32G32B32_UINT";
+ case VK_FORMAT_R32G32B32_SINT: return "VK_FORMAT_R32G32B32_SINT";
+ case VK_FORMAT_R32G32B32_SFLOAT: return "VK_FORMAT_R32G32B32_SFLOAT";
+ case VK_FORMAT_R32G32B32A32_UINT: return "VK_FORMAT_R32G32B32A32_UINT";
+ case VK_FORMAT_R32G32B32A32_SINT: return "VK_FORMAT_R32G32B32A32_SINT";
+ case VK_FORMAT_R32G32B32A32_SFLOAT: return "VK_FORMAT_R32G32B32A32_SFLOAT";
+ case VK_FORMAT_R64_UINT: return "VK_FORMAT_R64_UINT";
+ case VK_FORMAT_R64_SINT: return "VK_FORMAT_R64_SINT";
+ case VK_FORMAT_R64_SFLOAT: return "VK_FORMAT_R64_SFLOAT";
+ case VK_FORMAT_R64G64_UINT: return "VK_FORMAT_R64G64_UINT";
+ case VK_FORMAT_R64G64_SINT: return "VK_FORMAT_R64G64_SINT";
+ case VK_FORMAT_R64G64_SFLOAT: return "VK_FORMAT_R64G64_SFLOAT";
+ case VK_FORMAT_R64G64B64_UINT: return "VK_FORMAT_R64G64B64_UINT";
+ case VK_FORMAT_R64G64B64_SINT: return "VK_FORMAT_R64G64B64_SINT";
+ case VK_FORMAT_R64G64B64_SFLOAT: return "VK_FORMAT_R64G64B64_SFLOAT";
+ case VK_FORMAT_R64G64B64A64_UINT: return "VK_FORMAT_R64G64B64A64_UINT";
+ case VK_FORMAT_R64G64B64A64_SINT: return "VK_FORMAT_R64G64B64A64_SINT";
+ case VK_FORMAT_R64G64B64A64_SFLOAT: return "VK_FORMAT_R64G64B64A64_SFLOAT";
+ case VK_FORMAT_B10G11R11_UFLOAT_PACK32: return "VK_FORMAT_B10G11R11_UFLOAT_PACK32";
+ case VK_FORMAT_E5B9G9R9_UFLOAT_PACK32: return "VK_FORMAT_E5B9G9R9_UFLOAT_PACK32";
+ case VK_FORMAT_D16_UNORM: return "VK_FORMAT_D16_UNORM";
+ case VK_FORMAT_X8_D24_UNORM_PACK32: return "VK_FORMAT_X8_D24_UNORM_PACK32";
+ case VK_FORMAT_D32_SFLOAT: return "VK_FORMAT_D32_SFLOAT";
+ case VK_FORMAT_S8_UINT: return "VK_FORMAT_S8_UINT";
+ case VK_FORMAT_D16_UNORM_S8_UINT: return "VK_FORMAT_D16_UNORM_S8_UINT";
+ case VK_FORMAT_D24_UNORM_S8_UINT: return "VK_FORMAT_D24_UNORM_S8_UINT";
+ case VK_FORMAT_D32_SFLOAT_S8_UINT: return "VK_FORMAT_D32_SFLOAT_S8_UINT";
+ case VK_FORMAT_BC1_RGB_UNORM_BLOCK: return "VK_FORMAT_BC1_RGB_UNORM_BLOCK";
+ case VK_FORMAT_BC1_RGB_SRGB_BLOCK: return "VK_FORMAT_BC1_RGB_SRGB_BLOCK";
+ case VK_FORMAT_BC1_RGBA_UNORM_BLOCK: return "VK_FORMAT_BC1_RGBA_UNORM_BLOCK";
+ case VK_FORMAT_BC1_RGBA_SRGB_BLOCK: return "VK_FORMAT_BC1_RGBA_SRGB_BLOCK";
+ case VK_FORMAT_BC2_UNORM_BLOCK: return "VK_FORMAT_BC2_UNORM_BLOCK";
+ case VK_FORMAT_BC2_SRGB_BLOCK: return "VK_FORMAT_BC2_SRGB_BLOCK";
+ case VK_FORMAT_BC3_UNORM_BLOCK: return "VK_FORMAT_BC3_UNORM_BLOCK";
+ case VK_FORMAT_BC3_SRGB_BLOCK: return "VK_FORMAT_BC3_SRGB_BLOCK";
+ case VK_FORMAT_BC4_UNORM_BLOCK: return "VK_FORMAT_BC4_UNORM_BLOCK";
+ case VK_FORMAT_BC4_SNORM_BLOCK: return "VK_FORMAT_BC4_SNORM_BLOCK";
+ case VK_FORMAT_BC5_UNORM_BLOCK: return "VK_FORMAT_BC5_UNORM_BLOCK";
+ case VK_FORMAT_BC5_SNORM_BLOCK: return "VK_FORMAT_BC5_SNORM_BLOCK";
+ case VK_FORMAT_BC6H_UFLOAT_BLOCK: return "VK_FORMAT_BC6H_UFLOAT_BLOCK";
+ case VK_FORMAT_BC6H_SFLOAT_BLOCK: return "VK_FORMAT_BC6H_SFLOAT_BLOCK";
+ case VK_FORMAT_BC7_UNORM_BLOCK: return "VK_FORMAT_BC7_UNORM_BLOCK";
+ case VK_FORMAT_BC7_SRGB_BLOCK: return "VK_FORMAT_BC7_SRGB_BLOCK";
+ case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK: return "VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK";
+ case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK: return "VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK";
+ case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK: return "VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK";
+ case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK: return "VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK";
+ case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK: return "VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK";
+ case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK: return "VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK";
+ case VK_FORMAT_EAC_R11_UNORM_BLOCK: return "VK_FORMAT_EAC_R11_UNORM_BLOCK";
+ case VK_FORMAT_EAC_R11_SNORM_BLOCK: return "VK_FORMAT_EAC_R11_SNORM_BLOCK";
+ case VK_FORMAT_EAC_R11G11_UNORM_BLOCK: return "VK_FORMAT_EAC_R11G11_UNORM_BLOCK";
+ case VK_FORMAT_EAC_R11G11_SNORM_BLOCK: return "VK_FORMAT_EAC_R11G11_SNORM_BLOCK";
+ case VK_FORMAT_ASTC_4x4_UNORM_BLOCK: return "VK_FORMAT_ASTC_4x4_UNORM_BLOCK";
+ case VK_FORMAT_ASTC_4x4_SRGB_BLOCK: return "VK_FORMAT_ASTC_4x4_SRGB_BLOCK";
+ case VK_FORMAT_ASTC_5x4_UNORM_BLOCK: return "VK_FORMAT_ASTC_5x4_UNORM_BLOCK";
+ case VK_FORMAT_ASTC_5x4_SRGB_BLOCK: return "VK_FORMAT_ASTC_5x4_SRGB_BLOCK";
+ case VK_FORMAT_ASTC_5x5_UNORM_BLOCK: return "VK_FORMAT_ASTC_5x5_UNORM_BLOCK";
+ case VK_FORMAT_ASTC_5x5_SRGB_BLOCK: return "VK_FORMAT_ASTC_5x5_SRGB_BLOCK";
+ case VK_FORMAT_ASTC_6x5_UNORM_BLOCK: return "VK_FORMAT_ASTC_6x5_UNORM_BLOCK";
+ case VK_FORMAT_ASTC_6x5_SRGB_BLOCK: return "VK_FORMAT_ASTC_6x5_SRGB_BLOCK";
+ case VK_FORMAT_ASTC_6x6_UNORM_BLOCK: return "VK_FORMAT_ASTC_6x6_UNORM_BLOCK";
+ case VK_FORMAT_ASTC_6x6_SRGB_BLOCK: return "VK_FORMAT_ASTC_6x6_SRGB_BLOCK";
+ case VK_FORMAT_ASTC_8x5_UNORM_BLOCK: return "VK_FORMAT_ASTC_8x5_UNORM_BLOCK";
+ case VK_FORMAT_ASTC_8x5_SRGB_BLOCK: return "VK_FORMAT_ASTC_8x5_SRGB_BLOCK";
+ case VK_FORMAT_ASTC_8x6_UNORM_BLOCK: return "VK_FORMAT_ASTC_8x6_UNORM_BLOCK";
+ case VK_FORMAT_ASTC_8x6_SRGB_BLOCK: return "VK_FORMAT_ASTC_8x6_SRGB_BLOCK";
+ case VK_FORMAT_ASTC_8x8_UNORM_BLOCK: return "VK_FORMAT_ASTC_8x8_UNORM_BLOCK";
+ case VK_FORMAT_ASTC_8x8_SRGB_BLOCK: return "VK_FORMAT_ASTC_8x8_SRGB_BLOCK";
+ case VK_FORMAT_ASTC_10x5_UNORM_BLOCK: return "VK_FORMAT_ASTC_10x5_UNORM_BLOCK";
+ case VK_FORMAT_ASTC_10x5_SRGB_BLOCK: return "VK_FORMAT_ASTC_10x5_SRGB_BLOCK";
+ case VK_FORMAT_ASTC_10x6_UNORM_BLOCK: return "VK_FORMAT_ASTC_10x6_UNORM_BLOCK";
+ case VK_FORMAT_ASTC_10x6_SRGB_BLOCK: return "VK_FORMAT_ASTC_10x6_SRGB_BLOCK";
+ case VK_FORMAT_ASTC_10x8_UNORM_BLOCK: return "VK_FORMAT_ASTC_10x8_UNORM_BLOCK";
+ case VK_FORMAT_ASTC_10x8_SRGB_BLOCK: return "VK_FORMAT_ASTC_10x8_SRGB_BLOCK";
+ case VK_FORMAT_ASTC_10x10_UNORM_BLOCK: return "VK_FORMAT_ASTC_10x10_UNORM_BLOCK";
+ case VK_FORMAT_ASTC_10x10_SRGB_BLOCK: return "VK_FORMAT_ASTC_10x10_SRGB_BLOCK";
+ case VK_FORMAT_ASTC_12x10_UNORM_BLOCK: return "VK_FORMAT_ASTC_12x10_UNORM_BLOCK";
+ case VK_FORMAT_ASTC_12x10_SRGB_BLOCK: return "VK_FORMAT_ASTC_12x10_SRGB_BLOCK";
+ case VK_FORMAT_ASTC_12x12_UNORM_BLOCK: return "VK_FORMAT_ASTC_12x12_UNORM_BLOCK";
+ case VK_FORMAT_ASTC_12x12_SRGB_BLOCK: return "VK_FORMAT_ASTC_12x12_SRGB_BLOCK";
+ default: return DE_NULL;
+ }
+}
+
+const char* getImageTypeName (VkImageType value)
+{
+ switch (value)
+ {
+ case VK_IMAGE_TYPE_1D: return "VK_IMAGE_TYPE_1D";
+ case VK_IMAGE_TYPE_2D: return "VK_IMAGE_TYPE_2D";
+ case VK_IMAGE_TYPE_3D: return "VK_IMAGE_TYPE_3D";
+ default: return DE_NULL;
+ }
+}
+
+const char* getImageTilingName (VkImageTiling value)
+{
+ switch (value)
+ {
+ case VK_IMAGE_TILING_OPTIMAL: return "VK_IMAGE_TILING_OPTIMAL";
+ case VK_IMAGE_TILING_LINEAR: return "VK_IMAGE_TILING_LINEAR";
+ default: return DE_NULL;
+ }
+}
+
+const char* getPhysicalDeviceTypeName (VkPhysicalDeviceType value)
+{
+ switch (value)
+ {
+ case VK_PHYSICAL_DEVICE_TYPE_OTHER: return "VK_PHYSICAL_DEVICE_TYPE_OTHER";
+ case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: return "VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU";
+ case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: return "VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU";
+ case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: return "VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU";
+ case VK_PHYSICAL_DEVICE_TYPE_CPU: return "VK_PHYSICAL_DEVICE_TYPE_CPU";
+ default: return DE_NULL;
+ }
+}
+
+const char* getQueryTypeName (VkQueryType value)
+{
+ switch (value)
+ {
+ case VK_QUERY_TYPE_OCCLUSION: return "VK_QUERY_TYPE_OCCLUSION";
+ case VK_QUERY_TYPE_PIPELINE_STATISTICS: return "VK_QUERY_TYPE_PIPELINE_STATISTICS";
+ case VK_QUERY_TYPE_TIMESTAMP: return "VK_QUERY_TYPE_TIMESTAMP";
+ default: return DE_NULL;
+ }
+}
+
+const char* getSharingModeName (VkSharingMode value)
+{
+ switch (value)
+ {
+ case VK_SHARING_MODE_EXCLUSIVE: return "VK_SHARING_MODE_EXCLUSIVE";
+ case VK_SHARING_MODE_CONCURRENT: return "VK_SHARING_MODE_CONCURRENT";
+ default: return DE_NULL;
+ }
+}
+
+const char* getImageLayoutName (VkImageLayout value)
+{
+ switch (value)
+ {
+ case VK_IMAGE_LAYOUT_UNDEFINED: return "VK_IMAGE_LAYOUT_UNDEFINED";
+ case VK_IMAGE_LAYOUT_GENERAL: return "VK_IMAGE_LAYOUT_GENERAL";
+ case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: return "VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL";
+ case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: return "VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL";
+ case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: return "VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL";
+ case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: return "VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL";
+ case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: return "VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL";
+ case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: return "VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL";
+ case VK_IMAGE_LAYOUT_PREINITIALIZED: return "VK_IMAGE_LAYOUT_PREINITIALIZED";
+ case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: return "VK_IMAGE_LAYOUT_PRESENT_SRC_KHR";
+ default: return DE_NULL;
+ }
+}
+
+const char* getImageViewTypeName (VkImageViewType value)
+{
+ switch (value)
+ {
+ case VK_IMAGE_VIEW_TYPE_1D: return "VK_IMAGE_VIEW_TYPE_1D";
+ case VK_IMAGE_VIEW_TYPE_2D: return "VK_IMAGE_VIEW_TYPE_2D";
+ case VK_IMAGE_VIEW_TYPE_3D: return "VK_IMAGE_VIEW_TYPE_3D";
+ case VK_IMAGE_VIEW_TYPE_CUBE: return "VK_IMAGE_VIEW_TYPE_CUBE";
+ case VK_IMAGE_VIEW_TYPE_1D_ARRAY: return "VK_IMAGE_VIEW_TYPE_1D_ARRAY";
+ case VK_IMAGE_VIEW_TYPE_2D_ARRAY: return "VK_IMAGE_VIEW_TYPE_2D_ARRAY";
+ case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: return "VK_IMAGE_VIEW_TYPE_CUBE_ARRAY";
+ default: return DE_NULL;
+ }
+}
+
+const char* getComponentSwizzleName (VkComponentSwizzle value)
+{
+ switch (value)
+ {
+ case VK_COMPONENT_SWIZZLE_IDENTITY: return "VK_COMPONENT_SWIZZLE_IDENTITY";
+ case VK_COMPONENT_SWIZZLE_ZERO: return "VK_COMPONENT_SWIZZLE_ZERO";
+ case VK_COMPONENT_SWIZZLE_ONE: return "VK_COMPONENT_SWIZZLE_ONE";
+ case VK_COMPONENT_SWIZZLE_R: return "VK_COMPONENT_SWIZZLE_R";
+ case VK_COMPONENT_SWIZZLE_G: return "VK_COMPONENT_SWIZZLE_G";
+ case VK_COMPONENT_SWIZZLE_B: return "VK_COMPONENT_SWIZZLE_B";
+ case VK_COMPONENT_SWIZZLE_A: return "VK_COMPONENT_SWIZZLE_A";
+ default: return DE_NULL;
+ }
+}
+
+const char* getVertexInputRateName (VkVertexInputRate value)
+{
+ switch (value)
+ {
+ case VK_VERTEX_INPUT_RATE_VERTEX: return "VK_VERTEX_INPUT_RATE_VERTEX";
+ case VK_VERTEX_INPUT_RATE_INSTANCE: return "VK_VERTEX_INPUT_RATE_INSTANCE";
+ default: return DE_NULL;
+ }
+}
+
+const char* getPrimitiveTopologyName (VkPrimitiveTopology value)
+{
+ switch (value)
+ {
+ case VK_PRIMITIVE_TOPOLOGY_POINT_LIST: return "VK_PRIMITIVE_TOPOLOGY_POINT_LIST";
+ case VK_PRIMITIVE_TOPOLOGY_LINE_LIST: return "VK_PRIMITIVE_TOPOLOGY_LINE_LIST";
+ case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: return "VK_PRIMITIVE_TOPOLOGY_LINE_STRIP";
+ case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: return "VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST";
+ case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: return "VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP";
+ case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: return "VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN";
+ case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY: return "VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY";
+ case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY: return "VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY";
+ case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: return "VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY";
+ case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: return "VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY";
+ case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST: return "VK_PRIMITIVE_TOPOLOGY_PATCH_LIST";
+ default: return DE_NULL;
+ }
+}
+
+const char* getPolygonModeName (VkPolygonMode value)
+{
+ switch (value)
+ {
+ case VK_POLYGON_MODE_FILL: return "VK_POLYGON_MODE_FILL";
+ case VK_POLYGON_MODE_LINE: return "VK_POLYGON_MODE_LINE";
+ case VK_POLYGON_MODE_POINT: return "VK_POLYGON_MODE_POINT";
+ default: return DE_NULL;
+ }
+}
+
+const char* getFrontFaceName (VkFrontFace value)
+{
+ switch (value)
+ {
+ case VK_FRONT_FACE_COUNTER_CLOCKWISE: return "VK_FRONT_FACE_COUNTER_CLOCKWISE";
+ case VK_FRONT_FACE_CLOCKWISE: return "VK_FRONT_FACE_CLOCKWISE";
+ default: return DE_NULL;
+ }
+}
+
+const char* getCompareOpName (VkCompareOp value)
+{
+ switch (value)
+ {
+ case VK_COMPARE_OP_NEVER: return "VK_COMPARE_OP_NEVER";
+ case VK_COMPARE_OP_LESS: return "VK_COMPARE_OP_LESS";
+ case VK_COMPARE_OP_EQUAL: return "VK_COMPARE_OP_EQUAL";
+ case VK_COMPARE_OP_LESS_OR_EQUAL: return "VK_COMPARE_OP_LESS_OR_EQUAL";
+ case VK_COMPARE_OP_GREATER: return "VK_COMPARE_OP_GREATER";
+ case VK_COMPARE_OP_NOT_EQUAL: return "VK_COMPARE_OP_NOT_EQUAL";
+ case VK_COMPARE_OP_GREATER_OR_EQUAL: return "VK_COMPARE_OP_GREATER_OR_EQUAL";
+ case VK_COMPARE_OP_ALWAYS: return "VK_COMPARE_OP_ALWAYS";
+ default: return DE_NULL;
+ }
+}
+
+const char* getStencilOpName (VkStencilOp value)
+{
+ switch (value)
+ {
+ case VK_STENCIL_OP_KEEP: return "VK_STENCIL_OP_KEEP";
+ case VK_STENCIL_OP_ZERO: return "VK_STENCIL_OP_ZERO";
+ case VK_STENCIL_OP_REPLACE: return "VK_STENCIL_OP_REPLACE";
+ case VK_STENCIL_OP_INCREMENT_AND_CLAMP: return "VK_STENCIL_OP_INCREMENT_AND_CLAMP";
+ case VK_STENCIL_OP_DECREMENT_AND_CLAMP: return "VK_STENCIL_OP_DECREMENT_AND_CLAMP";
+ case VK_STENCIL_OP_INVERT: return "VK_STENCIL_OP_INVERT";
+ case VK_STENCIL_OP_INCREMENT_AND_WRAP: return "VK_STENCIL_OP_INCREMENT_AND_WRAP";
+ case VK_STENCIL_OP_DECREMENT_AND_WRAP: return "VK_STENCIL_OP_DECREMENT_AND_WRAP";
+ default: return DE_NULL;
+ }
+}
+
+const char* getLogicOpName (VkLogicOp value)
+{
+ switch (value)
+ {
+ case VK_LOGIC_OP_CLEAR: return "VK_LOGIC_OP_CLEAR";
+ case VK_LOGIC_OP_AND: return "VK_LOGIC_OP_AND";
+ case VK_LOGIC_OP_AND_REVERSE: return "VK_LOGIC_OP_AND_REVERSE";
+ case VK_LOGIC_OP_COPY: return "VK_LOGIC_OP_COPY";
+ case VK_LOGIC_OP_AND_INVERTED: return "VK_LOGIC_OP_AND_INVERTED";
+ case VK_LOGIC_OP_NO_OP: return "VK_LOGIC_OP_NO_OP";
+ case VK_LOGIC_OP_XOR: return "VK_LOGIC_OP_XOR";
+ case VK_LOGIC_OP_OR: return "VK_LOGIC_OP_OR";
+ case VK_LOGIC_OP_NOR: return "VK_LOGIC_OP_NOR";
+ case VK_LOGIC_OP_EQUIVALENT: return "VK_LOGIC_OP_EQUIVALENT";
+ case VK_LOGIC_OP_INVERT: return "VK_LOGIC_OP_INVERT";
+ case VK_LOGIC_OP_OR_REVERSE: return "VK_LOGIC_OP_OR_REVERSE";
+ case VK_LOGIC_OP_COPY_INVERTED: return "VK_LOGIC_OP_COPY_INVERTED";
+ case VK_LOGIC_OP_OR_INVERTED: return "VK_LOGIC_OP_OR_INVERTED";
+ case VK_LOGIC_OP_NAND: return "VK_LOGIC_OP_NAND";
+ case VK_LOGIC_OP_SET: return "VK_LOGIC_OP_SET";
+ default: return DE_NULL;
+ }
+}
+
+const char* getBlendFactorName (VkBlendFactor value)
+{
+ switch (value)
+ {
+ case VK_BLEND_FACTOR_ZERO: return "VK_BLEND_FACTOR_ZERO";
+ case VK_BLEND_FACTOR_ONE: return "VK_BLEND_FACTOR_ONE";
+ case VK_BLEND_FACTOR_SRC_COLOR: return "VK_BLEND_FACTOR_SRC_COLOR";
+ case VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR: return "VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR";
+ case VK_BLEND_FACTOR_DST_COLOR: return "VK_BLEND_FACTOR_DST_COLOR";
+ case VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR: return "VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR";
+ case VK_BLEND_FACTOR_SRC_ALPHA: return "VK_BLEND_FACTOR_SRC_ALPHA";
+ case VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA: return "VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA";
+ case VK_BLEND_FACTOR_DST_ALPHA: return "VK_BLEND_FACTOR_DST_ALPHA";
+ case VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA: return "VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA";
+ case VK_BLEND_FACTOR_CONSTANT_COLOR: return "VK_BLEND_FACTOR_CONSTANT_COLOR";
+ case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR: return "VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR";
+ case VK_BLEND_FACTOR_CONSTANT_ALPHA: return "VK_BLEND_FACTOR_CONSTANT_ALPHA";
+ case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA: return "VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA";
+ case VK_BLEND_FACTOR_SRC_ALPHA_SATURATE: return "VK_BLEND_FACTOR_SRC_ALPHA_SATURATE";
+ case VK_BLEND_FACTOR_SRC1_COLOR: return "VK_BLEND_FACTOR_SRC1_COLOR";
+ case VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR: return "VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR";
+ case VK_BLEND_FACTOR_SRC1_ALPHA: return "VK_BLEND_FACTOR_SRC1_ALPHA";
+ case VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA: return "VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA";
+ default: return DE_NULL;
+ }
+}
+
+const char* getBlendOpName (VkBlendOp value)
+{
+ switch (value)
+ {
+ case VK_BLEND_OP_ADD: return "VK_BLEND_OP_ADD";
+ case VK_BLEND_OP_SUBTRACT: return "VK_BLEND_OP_SUBTRACT";
+ case VK_BLEND_OP_REVERSE_SUBTRACT: return "VK_BLEND_OP_REVERSE_SUBTRACT";
+ case VK_BLEND_OP_MIN: return "VK_BLEND_OP_MIN";
+ case VK_BLEND_OP_MAX: return "VK_BLEND_OP_MAX";
+ default: return DE_NULL;
+ }
+}
+
+const char* getDynamicStateName (VkDynamicState value)
+{
+ switch (value)
+ {
+ case VK_DYNAMIC_STATE_VIEWPORT: return "VK_DYNAMIC_STATE_VIEWPORT";
+ case VK_DYNAMIC_STATE_SCISSOR: return "VK_DYNAMIC_STATE_SCISSOR";
+ case VK_DYNAMIC_STATE_LINE_WIDTH: return "VK_DYNAMIC_STATE_LINE_WIDTH";
+ case VK_DYNAMIC_STATE_DEPTH_BIAS: return "VK_DYNAMIC_STATE_DEPTH_BIAS";
+ case VK_DYNAMIC_STATE_BLEND_CONSTANTS: return "VK_DYNAMIC_STATE_BLEND_CONSTANTS";
+ case VK_DYNAMIC_STATE_DEPTH_BOUNDS: return "VK_DYNAMIC_STATE_DEPTH_BOUNDS";
+ case VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK: return "VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK";
+ case VK_DYNAMIC_STATE_STENCIL_WRITE_MASK: return "VK_DYNAMIC_STATE_STENCIL_WRITE_MASK";
+ case VK_DYNAMIC_STATE_STENCIL_REFERENCE: return "VK_DYNAMIC_STATE_STENCIL_REFERENCE";
+ default: return DE_NULL;
+ }
+}
+
+const char* getFilterName (VkFilter value)
+{
+ switch (value)
+ {
+ case VK_FILTER_NEAREST: return "VK_FILTER_NEAREST";
+ case VK_FILTER_LINEAR: return "VK_FILTER_LINEAR";
+ default: return DE_NULL;
+ }
+}
+
+const char* getSamplerMipmapModeName (VkSamplerMipmapMode value)
+{
+ switch (value)
+ {
+ case VK_SAMPLER_MIPMAP_MODE_BASE: return "VK_SAMPLER_MIPMAP_MODE_BASE";
+ case VK_SAMPLER_MIPMAP_MODE_NEAREST: return "VK_SAMPLER_MIPMAP_MODE_NEAREST";
+ case VK_SAMPLER_MIPMAP_MODE_LINEAR: return "VK_SAMPLER_MIPMAP_MODE_LINEAR";
+ default: return DE_NULL;
+ }
+}
+
+const char* getSamplerAddressModeName (VkSamplerAddressMode value)
+{
+ switch (value)
+ {
+ case VK_SAMPLER_ADDRESS_MODE_REPEAT: return "VK_SAMPLER_ADDRESS_MODE_REPEAT";
+ case VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT: return "VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT";
+ case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE: return "VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE";
+ case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER: return "VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER";
+ case VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE: return "VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE";
+ default: return DE_NULL;
+ }
+}
+
+const char* getBorderColorName (VkBorderColor value)
+{
+ switch (value)
+ {
+ case VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK: return "VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK";
+ case VK_BORDER_COLOR_INT_TRANSPARENT_BLACK: return "VK_BORDER_COLOR_INT_TRANSPARENT_BLACK";
+ case VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK: return "VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK";
+ case VK_BORDER_COLOR_INT_OPAQUE_BLACK: return "VK_BORDER_COLOR_INT_OPAQUE_BLACK";
+ case VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE: return "VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE";
+ case VK_BORDER_COLOR_INT_OPAQUE_WHITE: return "VK_BORDER_COLOR_INT_OPAQUE_WHITE";
+ default: return DE_NULL;
+ }
+}
+
+const char* getDescriptorTypeName (VkDescriptorType value)
+{
+ switch (value)
+ {
+ case VK_DESCRIPTOR_TYPE_SAMPLER: return "VK_DESCRIPTOR_TYPE_SAMPLER";
+ case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: return "VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER";
+ case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: return "VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE";
+ case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: return "VK_DESCRIPTOR_TYPE_STORAGE_IMAGE";
+ case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: return "VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER";
+ case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: return "VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER";
+ case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: return "VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER";
+ case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: return "VK_DESCRIPTOR_TYPE_STORAGE_BUFFER";
+ case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: return "VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC";
+ case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: return "VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC";
+ case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: return "VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT";
+ default: return DE_NULL;
+ }
+}
+
+const char* getAttachmentLoadOpName (VkAttachmentLoadOp value)
+{
+ switch (value)
+ {
+ case VK_ATTACHMENT_LOAD_OP_LOAD: return "VK_ATTACHMENT_LOAD_OP_LOAD";
+ case VK_ATTACHMENT_LOAD_OP_CLEAR: return "VK_ATTACHMENT_LOAD_OP_CLEAR";
+ case VK_ATTACHMENT_LOAD_OP_DONT_CARE: return "VK_ATTACHMENT_LOAD_OP_DONT_CARE";
+ default: return DE_NULL;
+ }
+}
+
+const char* getAttachmentStoreOpName (VkAttachmentStoreOp value)
+{
+ switch (value)
+ {
+ case VK_ATTACHMENT_STORE_OP_STORE: return "VK_ATTACHMENT_STORE_OP_STORE";
+ case VK_ATTACHMENT_STORE_OP_DONT_CARE: return "VK_ATTACHMENT_STORE_OP_DONT_CARE";
+ default: return DE_NULL;
+ }
+}
+
+const char* getPipelineBindPointName (VkPipelineBindPoint value)
+{
+ switch (value)
+ {
+ case VK_PIPELINE_BIND_POINT_GRAPHICS: return "VK_PIPELINE_BIND_POINT_GRAPHICS";
+ case VK_PIPELINE_BIND_POINT_COMPUTE: return "VK_PIPELINE_BIND_POINT_COMPUTE";
+ default: return DE_NULL;
+ }
+}
+
+const char* getCommandBufferLevelName (VkCommandBufferLevel value)
+{
+ switch (value)
+ {
+ case VK_COMMAND_BUFFER_LEVEL_PRIMARY: return "VK_COMMAND_BUFFER_LEVEL_PRIMARY";
+ case VK_COMMAND_BUFFER_LEVEL_SECONDARY: return "VK_COMMAND_BUFFER_LEVEL_SECONDARY";
+ default: return DE_NULL;
+ }
+}
+
+const char* getIndexTypeName (VkIndexType value)
+{
+ switch (value)
+ {
+ case VK_INDEX_TYPE_UINT16: return "VK_INDEX_TYPE_UINT16";
+ case VK_INDEX_TYPE_UINT32: return "VK_INDEX_TYPE_UINT32";
+ default: return DE_NULL;
+ }
+}
+
+const char* getSubpassContentsName (VkSubpassContents value)
+{
+ switch (value)
+ {
+ case VK_SUBPASS_CONTENTS_INLINE: return "VK_SUBPASS_CONTENTS_INLINE";
+ case VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS: return "VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS";
+ default: return DE_NULL;
+ }
+}
+
+const char* getColorSpaceKHRName (VkColorSpaceKHR value)
+{
+ switch (value)
+ {
+ case VK_COLORSPACE_SRGB_NONLINEAR_KHR: return "VK_COLORSPACE_SRGB_NONLINEAR_KHR";
+ default: return DE_NULL;
+ }
+}
+
+const char* getPresentModeKHRName (VkPresentModeKHR value)
+{
+ switch (value)
+ {
+ case VK_PRESENT_MODE_IMMEDIATE_KHR: return "VK_PRESENT_MODE_IMMEDIATE_KHR";
+ case VK_PRESENT_MODE_MAILBOX_KHR: return "VK_PRESENT_MODE_MAILBOX_KHR";
+ case VK_PRESENT_MODE_FIFO_KHR: return "VK_PRESENT_MODE_FIFO_KHR";
+ case VK_PRESENT_MODE_FIFO_RELAXED_KHR: return "VK_PRESENT_MODE_FIFO_RELAXED_KHR";
+ default: return DE_NULL;
+ }
+}
+
+tcu::Format::Bitfield<32> getFormatFeatureFlagsStr (VkFormatFeatureFlags value)
+{
+ static const tcu::Format::BitDesc s_desc[] =
+ {
+ tcu::Format::BitDesc(VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT, "VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT"),
+ tcu::Format::BitDesc(VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT, "VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT"),
+ tcu::Format::BitDesc(VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT, "VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT"),
+ tcu::Format::BitDesc(VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT, "VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT"),
+ tcu::Format::BitDesc(VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT, "VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT"),
+ tcu::Format::BitDesc(VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT, "VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT"),
+ tcu::Format::BitDesc(VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT, "VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT"),
+ tcu::Format::BitDesc(VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT, "VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT"),
+ tcu::Format::BitDesc(VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT, "VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT"),
+ tcu::Format::BitDesc(VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT, "VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT"),
+ tcu::Format::BitDesc(VK_FORMAT_FEATURE_BLIT_SRC_BIT, "VK_FORMAT_FEATURE_BLIT_SRC_BIT"),
+ tcu::Format::BitDesc(VK_FORMAT_FEATURE_BLIT_DST_BIT, "VK_FORMAT_FEATURE_BLIT_DST_BIT"),
+ };
+ return tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));
+}
+
+tcu::Format::Bitfield<32> getImageUsageFlagsStr (VkImageUsageFlags value)
+{
+ static const tcu::Format::BitDesc s_desc[] =
+ {
+ tcu::Format::BitDesc(VK_IMAGE_USAGE_TRANSFER_SRC_BIT, "VK_IMAGE_USAGE_TRANSFER_SRC_BIT"),
+ tcu::Format::BitDesc(VK_IMAGE_USAGE_TRANSFER_DST_BIT, "VK_IMAGE_USAGE_TRANSFER_DST_BIT"),
+ tcu::Format::BitDesc(VK_IMAGE_USAGE_SAMPLED_BIT, "VK_IMAGE_USAGE_SAMPLED_BIT"),
+ tcu::Format::BitDesc(VK_IMAGE_USAGE_STORAGE_BIT, "VK_IMAGE_USAGE_STORAGE_BIT"),
+ tcu::Format::BitDesc(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, "VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT"),
+ tcu::Format::BitDesc(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, "VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT"),
+ tcu::Format::BitDesc(VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT, "VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT"),
+ tcu::Format::BitDesc(VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, "VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT"),
+ };
+ return tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));
+}
+
+tcu::Format::Bitfield<32> getImageCreateFlagsStr (VkImageCreateFlags value)
+{
+ static const tcu::Format::BitDesc s_desc[] =
+ {
+ tcu::Format::BitDesc(VK_IMAGE_CREATE_SPARSE_BINDING_BIT, "VK_IMAGE_CREATE_SPARSE_BINDING_BIT"),
+ tcu::Format::BitDesc(VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT, "VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT"),
+ tcu::Format::BitDesc(VK_IMAGE_CREATE_SPARSE_ALIASED_BIT, "VK_IMAGE_CREATE_SPARSE_ALIASED_BIT"),
+ tcu::Format::BitDesc(VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, "VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT"),
+ tcu::Format::BitDesc(VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT, "VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT"),
+ };
+ return tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));
+}
+
+tcu::Format::Bitfield<32> getSampleCountFlagsStr (VkSampleCountFlags value)
+{
+ static const tcu::Format::BitDesc s_desc[] =
+ {
+ tcu::Format::BitDesc(VK_SAMPLE_COUNT_1_BIT, "VK_SAMPLE_COUNT_1_BIT"),
+ tcu::Format::BitDesc(VK_SAMPLE_COUNT_2_BIT, "VK_SAMPLE_COUNT_2_BIT"),
+ tcu::Format::BitDesc(VK_SAMPLE_COUNT_4_BIT, "VK_SAMPLE_COUNT_4_BIT"),
+ tcu::Format::BitDesc(VK_SAMPLE_COUNT_8_BIT, "VK_SAMPLE_COUNT_8_BIT"),
+ tcu::Format::BitDesc(VK_SAMPLE_COUNT_16_BIT, "VK_SAMPLE_COUNT_16_BIT"),
+ tcu::Format::BitDesc(VK_SAMPLE_COUNT_32_BIT, "VK_SAMPLE_COUNT_32_BIT"),
+ tcu::Format::BitDesc(VK_SAMPLE_COUNT_64_BIT, "VK_SAMPLE_COUNT_64_BIT"),
+ };
+ return tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));
+}
+
+tcu::Format::Bitfield<32> getQueueFlagsStr (VkQueueFlags value)
+{
+ static const tcu::Format::BitDesc s_desc[] =
+ {
+ tcu::Format::BitDesc(VK_QUEUE_GRAPHICS_BIT, "VK_QUEUE_GRAPHICS_BIT"),
+ tcu::Format::BitDesc(VK_QUEUE_COMPUTE_BIT, "VK_QUEUE_COMPUTE_BIT"),
+ tcu::Format::BitDesc(VK_QUEUE_TRANSFER_BIT, "VK_QUEUE_TRANSFER_BIT"),
+ tcu::Format::BitDesc(VK_QUEUE_SPARSE_BINDING_BIT, "VK_QUEUE_SPARSE_BINDING_BIT"),
+ };
+ return tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));
+}
+
+tcu::Format::Bitfield<32> getMemoryPropertyFlagsStr (VkMemoryPropertyFlags value)
+{
+ static const tcu::Format::BitDesc s_desc[] =
+ {
+ tcu::Format::BitDesc(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, "VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT"),
+ tcu::Format::BitDesc(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, "VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT"),
+ tcu::Format::BitDesc(VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, "VK_MEMORY_PROPERTY_HOST_COHERENT_BIT"),
+ tcu::Format::BitDesc(VK_MEMORY_PROPERTY_HOST_CACHED_BIT, "VK_MEMORY_PROPERTY_HOST_CACHED_BIT"),
+ tcu::Format::BitDesc(VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT, "VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT"),
+ };
+ return tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));
+}
+
+tcu::Format::Bitfield<32> getMemoryHeapFlagsStr (VkMemoryHeapFlags value)
+{
+ static const tcu::Format::BitDesc s_desc[] =
+ {
+ tcu::Format::BitDesc(VK_MEMORY_HEAP_DEVICE_LOCAL_BIT, "VK_MEMORY_HEAP_DEVICE_LOCAL_BIT"),
+ };
+ return tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));
+}
+
+tcu::Format::Bitfield<32> getImageAspectFlagsStr (VkImageAspectFlags value)
+{
+ static const tcu::Format::BitDesc s_desc[] =
+ {
+ tcu::Format::BitDesc(VK_IMAGE_ASPECT_COLOR_BIT, "VK_IMAGE_ASPECT_COLOR_BIT"),
+ tcu::Format::BitDesc(VK_IMAGE_ASPECT_DEPTH_BIT, "VK_IMAGE_ASPECT_DEPTH_BIT"),
+ tcu::Format::BitDesc(VK_IMAGE_ASPECT_STENCIL_BIT, "VK_IMAGE_ASPECT_STENCIL_BIT"),
+ tcu::Format::BitDesc(VK_IMAGE_ASPECT_METADATA_BIT, "VK_IMAGE_ASPECT_METADATA_BIT"),
+ };
+ return tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));
+}
+
+tcu::Format::Bitfield<32> getSparseImageFormatFlagsStr (VkSparseImageFormatFlags value)
+{
+ static const tcu::Format::BitDesc s_desc[] =
+ {
+ tcu::Format::BitDesc(VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT, "VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT"),
+ tcu::Format::BitDesc(VK_SPARSE_IMAGE_FORMAT_ALIGNED_MIP_SIZE_BIT, "VK_SPARSE_IMAGE_FORMAT_ALIGNED_MIP_SIZE_BIT"),
+ tcu::Format::BitDesc(VK_SPARSE_IMAGE_FORMAT_NONSTANDARD_BLOCK_SIZE_BIT, "VK_SPARSE_IMAGE_FORMAT_NONSTANDARD_BLOCK_SIZE_BIT"),
+ };
+ return tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));
+}
+
+tcu::Format::Bitfield<32> getSparseMemoryBindFlagsStr (VkSparseMemoryBindFlags value)
+{
+ static const tcu::Format::BitDesc s_desc[] =
+ {
+ tcu::Format::BitDesc(VK_SPARSE_MEMORY_BIND_METADATA_BIT, "VK_SPARSE_MEMORY_BIND_METADATA_BIT"),
+ };
+ return tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));
+}
+
+tcu::Format::Bitfield<32> getFenceCreateFlagsStr (VkFenceCreateFlags value)
+{
+ static const tcu::Format::BitDesc s_desc[] =
+ {
+ tcu::Format::BitDesc(VK_FENCE_CREATE_SIGNALED_BIT, "VK_FENCE_CREATE_SIGNALED_BIT"),
+ };
+ return tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));
+}
+
+tcu::Format::Bitfield<32> getQueryPipelineStatisticFlagsStr (VkQueryPipelineStatisticFlags value)
+{
+ static const tcu::Format::BitDesc s_desc[] =
+ {
+ tcu::Format::BitDesc(VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT, "VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT"),
+ tcu::Format::BitDesc(VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT, "VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT"),
+ tcu::Format::BitDesc(VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT, "VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT"),
+ tcu::Format::BitDesc(VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_INVOCATIONS_BIT, "VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_INVOCATIONS_BIT"),
+ tcu::Format::BitDesc(VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_PRIMITIVES_BIT, "VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_PRIMITIVES_BIT"),
+ tcu::Format::BitDesc(VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT, "VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT"),
+ tcu::Format::BitDesc(VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT, "VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT"),
+ tcu::Format::BitDesc(VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT, "VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT"),
+ tcu::Format::BitDesc(VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT, "VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT"),
+ tcu::Format::BitDesc(VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT, "VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT"),
+ tcu::Format::BitDesc(VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT, "VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT"),
+ };
+ return tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));
+}
+
+tcu::Format::Bitfield<32> getQueryResultFlagsStr (VkQueryResultFlags value)
+{
+ static const tcu::Format::BitDesc s_desc[] =
+ {
+ tcu::Format::BitDesc(VK_QUERY_RESULT_DEFAULT, "VK_QUERY_RESULT_DEFAULT"),
+ tcu::Format::BitDesc(VK_QUERY_RESULT_64_BIT, "VK_QUERY_RESULT_64_BIT"),
+ tcu::Format::BitDesc(VK_QUERY_RESULT_WAIT_BIT, "VK_QUERY_RESULT_WAIT_BIT"),
+ tcu::Format::BitDesc(VK_QUERY_RESULT_WITH_AVAILABILITY_BIT, "VK_QUERY_RESULT_WITH_AVAILABILITY_BIT"),
+ tcu::Format::BitDesc(VK_QUERY_RESULT_PARTIAL_BIT, "VK_QUERY_RESULT_PARTIAL_BIT"),
+ };
+ return tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));
+}
+
+tcu::Format::Bitfield<32> getBufferCreateFlagsStr (VkBufferCreateFlags value)
+{
+ static const tcu::Format::BitDesc s_desc[] =
+ {
+ tcu::Format::BitDesc(VK_BUFFER_CREATE_SPARSE_BINDING_BIT, "VK_BUFFER_CREATE_SPARSE_BINDING_BIT"),
+ tcu::Format::BitDesc(VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT, "VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT"),
+ tcu::Format::BitDesc(VK_BUFFER_CREATE_SPARSE_ALIASED_BIT, "VK_BUFFER_CREATE_SPARSE_ALIASED_BIT"),
+ };
+ return tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));
+}
+
+tcu::Format::Bitfield<32> getBufferUsageFlagsStr (VkBufferUsageFlags value)
+{
+ static const tcu::Format::BitDesc s_desc[] =
+ {
+ tcu::Format::BitDesc(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, "VK_BUFFER_USAGE_TRANSFER_SRC_BIT"),
+ tcu::Format::BitDesc(VK_BUFFER_USAGE_TRANSFER_DST_BIT, "VK_BUFFER_USAGE_TRANSFER_DST_BIT"),
+ tcu::Format::BitDesc(VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, "VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT"),
+ tcu::Format::BitDesc(VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT, "VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT"),
+ tcu::Format::BitDesc(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, "VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT"),
+ tcu::Format::BitDesc(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, "VK_BUFFER_USAGE_STORAGE_BUFFER_BIT"),
+ tcu::Format::BitDesc(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, "VK_BUFFER_USAGE_INDEX_BUFFER_BIT"),
+ tcu::Format::BitDesc(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, "VK_BUFFER_USAGE_VERTEX_BUFFER_BIT"),
+ tcu::Format::BitDesc(VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, "VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT"),
+ };
+ return tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));
+}
+
+tcu::Format::Bitfield<32> getPipelineCreateFlagsStr (VkPipelineCreateFlags value)
+{
+ static const tcu::Format::BitDesc s_desc[] =
+ {
+ tcu::Format::BitDesc(VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT, "VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT"),
+ tcu::Format::BitDesc(VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT, "VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT"),
+ tcu::Format::BitDesc(VK_PIPELINE_CREATE_DERIVATIVE_BIT, "VK_PIPELINE_CREATE_DERIVATIVE_BIT"),
+ };
+ return tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));
+}
+
+tcu::Format::Bitfield<32> getShaderStageFlagsStr (VkShaderStageFlags value)
+{
+ static const tcu::Format::BitDesc s_desc[] =
+ {
+ tcu::Format::BitDesc(VK_SHADER_STAGE_VERTEX_BIT, "VK_SHADER_STAGE_VERTEX_BIT"),
+ tcu::Format::BitDesc(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, "VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT"),
+ tcu::Format::BitDesc(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, "VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT"),
+ tcu::Format::BitDesc(VK_SHADER_STAGE_GEOMETRY_BIT, "VK_SHADER_STAGE_GEOMETRY_BIT"),
+ tcu::Format::BitDesc(VK_SHADER_STAGE_FRAGMENT_BIT, "VK_SHADER_STAGE_FRAGMENT_BIT"),
+ tcu::Format::BitDesc(VK_SHADER_STAGE_COMPUTE_BIT, "VK_SHADER_STAGE_COMPUTE_BIT"),
+ tcu::Format::BitDesc(VK_SHADER_STAGE_ALL_GRAPHICS, "VK_SHADER_STAGE_ALL_GRAPHICS"),
+ tcu::Format::BitDesc(VK_SHADER_STAGE_ALL, "VK_SHADER_STAGE_ALL"),
+ };
+ return tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));
+}
+
+tcu::Format::Bitfield<32> getCullModeFlagsStr (VkCullModeFlags value)
+{
+ static const tcu::Format::BitDesc s_desc[] =
+ {
+ tcu::Format::BitDesc(VK_CULL_MODE_NONE, "VK_CULL_MODE_NONE"),
+ tcu::Format::BitDesc(VK_CULL_MODE_FRONT_BIT, "VK_CULL_MODE_FRONT_BIT"),
+ tcu::Format::BitDesc(VK_CULL_MODE_BACK_BIT, "VK_CULL_MODE_BACK_BIT"),
+ tcu::Format::BitDesc(VK_CULL_MODE_FRONT_AND_BACK, "VK_CULL_MODE_FRONT_AND_BACK"),
+ };
+ return tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));
+}
+
+tcu::Format::Bitfield<32> getColorComponentFlagsStr (VkColorComponentFlags value)
+{
+ static const tcu::Format::BitDesc s_desc[] =
+ {
+ tcu::Format::BitDesc(VK_COLOR_COMPONENT_R_BIT, "VK_COLOR_COMPONENT_R_BIT"),
+ tcu::Format::BitDesc(VK_COLOR_COMPONENT_G_BIT, "VK_COLOR_COMPONENT_G_BIT"),
+ tcu::Format::BitDesc(VK_COLOR_COMPONENT_B_BIT, "VK_COLOR_COMPONENT_B_BIT"),
+ tcu::Format::BitDesc(VK_COLOR_COMPONENT_A_BIT, "VK_COLOR_COMPONENT_A_BIT"),
+ };
+ return tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));
+}
+
+tcu::Format::Bitfield<32> getDescriptorPoolCreateFlagsStr (VkDescriptorPoolCreateFlags value)
+{
+ static const tcu::Format::BitDesc s_desc[] =
+ {
+ tcu::Format::BitDesc(VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, "VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT"),
+ };
+ return tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));
+}
+
+tcu::Format::Bitfield<32> getAttachmentDescriptionFlagsStr (VkAttachmentDescriptionFlags value)
+{
+ static const tcu::Format::BitDesc s_desc[] =
+ {
+ tcu::Format::BitDesc(VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT, "VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT"),
+ };
+ return tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));
+}
+
+tcu::Format::Bitfield<32> getPipelineStageFlagsStr (VkPipelineStageFlags value)
+{
+ static const tcu::Format::BitDesc s_desc[] =
+ {
+ tcu::Format::BitDesc(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT"),
+ tcu::Format::BitDesc(VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, "VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT"),
+ tcu::Format::BitDesc(VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, "VK_PIPELINE_STAGE_VERTEX_INPUT_BIT"),
+ tcu::Format::BitDesc(VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, "VK_PIPELINE_STAGE_VERTEX_SHADER_BIT"),
+ tcu::Format::BitDesc(VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT, "VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT"),
+ tcu::Format::BitDesc(VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT, "VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT"),
+ tcu::Format::BitDesc(VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT, "VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT"),
+ tcu::Format::BitDesc(VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, "VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT"),
+ tcu::Format::BitDesc(VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, "VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT"),
+ tcu::Format::BitDesc(VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, "VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT"),
+ tcu::Format::BitDesc(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, "VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT"),
+ tcu::Format::BitDesc(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, "VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT"),
+ tcu::Format::BitDesc(VK_PIPELINE_STAGE_TRANSFER_BIT, "VK_PIPELINE_STAGE_TRANSFER_BIT"),
+ tcu::Format::BitDesc(VK_PIPELINE_STAGE_HOST_BIT, "VK_PIPELINE_STAGE_HOST_BIT"),
+ tcu::Format::BitDesc(VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, "VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT"),
+ tcu::Format::BitDesc(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, "VK_PIPELINE_STAGE_ALL_COMMANDS_BIT"),
+ };
+ return tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));
+}
+
+tcu::Format::Bitfield<32> getAccessFlagsStr (VkAccessFlags value)
+{
+ static const tcu::Format::BitDesc s_desc[] =
+ {
+ tcu::Format::BitDesc(VK_ACCESS_INDIRECT_COMMAND_READ_BIT, "VK_ACCESS_INDIRECT_COMMAND_READ_BIT"),
+ tcu::Format::BitDesc(VK_ACCESS_INDEX_READ_BIT, "VK_ACCESS_INDEX_READ_BIT"),
+ tcu::Format::BitDesc(VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, "VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT"),
+ tcu::Format::BitDesc(VK_ACCESS_UNIFORM_READ_BIT, "VK_ACCESS_UNIFORM_READ_BIT"),
+ tcu::Format::BitDesc(VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, "VK_ACCESS_INPUT_ATTACHMENT_READ_BIT"),
+ tcu::Format::BitDesc(VK_ACCESS_SHADER_READ_BIT, "VK_ACCESS_SHADER_READ_BIT"),
+ tcu::Format::BitDesc(VK_ACCESS_SHADER_WRITE_BIT, "VK_ACCESS_SHADER_WRITE_BIT"),
+ tcu::Format::BitDesc(VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, "VK_ACCESS_COLOR_ATTACHMENT_READ_BIT"),
+ tcu::Format::BitDesc(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, "VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT"),
+ tcu::Format::BitDesc(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, "VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT"),
+ tcu::Format::BitDesc(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, "VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT"),
+ tcu::Format::BitDesc(VK_ACCESS_TRANSFER_READ_BIT, "VK_ACCESS_TRANSFER_READ_BIT"),
+ tcu::Format::BitDesc(VK_ACCESS_TRANSFER_WRITE_BIT, "VK_ACCESS_TRANSFER_WRITE_BIT"),
+ tcu::Format::BitDesc(VK_ACCESS_HOST_READ_BIT, "VK_ACCESS_HOST_READ_BIT"),
+ tcu::Format::BitDesc(VK_ACCESS_HOST_WRITE_BIT, "VK_ACCESS_HOST_WRITE_BIT"),
+ tcu::Format::BitDesc(VK_ACCESS_MEMORY_READ_BIT, "VK_ACCESS_MEMORY_READ_BIT"),
+ tcu::Format::BitDesc(VK_ACCESS_MEMORY_WRITE_BIT, "VK_ACCESS_MEMORY_WRITE_BIT"),
+ };
+ return tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));
+}
+
+tcu::Format::Bitfield<32> getDependencyFlagsStr (VkDependencyFlags value)
+{
+ static const tcu::Format::BitDesc s_desc[] =
+ {
+ tcu::Format::BitDesc(VK_DEPENDENCY_BY_REGION_BIT, "VK_DEPENDENCY_BY_REGION_BIT"),
+ };
+ return tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));
+}
+
+tcu::Format::Bitfield<32> getCommandPoolCreateFlagsStr (VkCommandPoolCreateFlags value)
+{
+ static const tcu::Format::BitDesc s_desc[] =
+ {
+ tcu::Format::BitDesc(VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, "VK_COMMAND_POOL_CREATE_TRANSIENT_BIT"),
+ tcu::Format::BitDesc(VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, "VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT"),
+ };
+ return tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));
+}
+
+tcu::Format::Bitfield<32> getCommandPoolResetFlagsStr (VkCommandPoolResetFlags value)
+{
+ static const tcu::Format::BitDesc s_desc[] =
+ {
+ tcu::Format::BitDesc(VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT, "VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT"),
+ };
+ return tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));
+}
+
+tcu::Format::Bitfield<32> getCommandBufferUsageFlagsStr (VkCommandBufferUsageFlags value)
+{
+ static const tcu::Format::BitDesc s_desc[] =
+ {
+ tcu::Format::BitDesc(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, "VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT"),
+ tcu::Format::BitDesc(VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, "VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT"),
+ tcu::Format::BitDesc(VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, "VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT"),
+ };
+ return tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));
+}
+
+tcu::Format::Bitfield<32> getQueryControlFlagsStr (VkQueryControlFlags value)
+{
+ static const tcu::Format::BitDesc s_desc[] =
+ {
+ tcu::Format::BitDesc(VK_QUERY_CONTROL_PRECISE_BIT, "VK_QUERY_CONTROL_PRECISE_BIT"),
+ };
+ return tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));
+}
+
+tcu::Format::Bitfield<32> getCommandBufferResetFlagsStr (VkCommandBufferResetFlags value)
+{
+ static const tcu::Format::BitDesc s_desc[] =
+ {
+ tcu::Format::BitDesc(VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT, "VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT"),
+ };
+ return tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));
+}
+
+tcu::Format::Bitfield<32> getStencilFaceFlagsStr (VkStencilFaceFlags value)
+{
+ static const tcu::Format::BitDesc s_desc[] =
+ {
+ tcu::Format::BitDesc(VK_STENCIL_FACE_NONE, "VK_STENCIL_FACE_NONE"),
+ tcu::Format::BitDesc(VK_STENCIL_FACE_FRONT_BIT, "VK_STENCIL_FACE_FRONT_BIT"),
+ tcu::Format::BitDesc(VK_STENCIL_FACE_BACK_BIT, "VK_STENCIL_FACE_BACK_BIT"),
+ tcu::Format::BitDesc(VK_STENCIL_FRONT_AND_BACK, "VK_STENCIL_FRONT_AND_BACK"),
+ };
+ return tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));
+}
+
+tcu::Format::Bitfield<32> getSurfaceTransformFlagsKHRStr (VkSurfaceTransformFlagsKHR value)
+{
+ static const tcu::Format::BitDesc s_desc[] =
+ {
+ tcu::Format::BitDesc(VK_SURFACE_TRANSFORM_NONE_BIT_KHR, "VK_SURFACE_TRANSFORM_NONE_BIT_KHR"),
+ tcu::Format::BitDesc(VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR, "VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR"),
+ tcu::Format::BitDesc(VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR, "VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR"),
+ tcu::Format::BitDesc(VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR, "VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR"),
+ tcu::Format::BitDesc(VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR, "VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR"),
+ tcu::Format::BitDesc(VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR, "VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR"),
+ tcu::Format::BitDesc(VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR, "VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR"),
+ tcu::Format::BitDesc(VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR, "VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR"),
+ tcu::Format::BitDesc(VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR, "VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR"),
+ };
+ return tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));
+}
+
+tcu::Format::Bitfield<32> getCompositeAlphaFlagsKHRStr (VkCompositeAlphaFlagsKHR value)
+{
+ static const tcu::Format::BitDesc s_desc[] =
+ {
+ tcu::Format::BitDesc(VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, "VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR"),
+ tcu::Format::BitDesc(VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR, "VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR"),
+ tcu::Format::BitDesc(VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR, "VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR"),
+ tcu::Format::BitDesc(VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR, "VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR"),
+ };
+ return tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));
+}
+
+tcu::Format::Bitfield<32> getDisplayPlaneAlphaFlagsKHRStr (VkDisplayPlaneAlphaFlagsKHR value)
+{
+ static const tcu::Format::BitDesc s_desc[] =
+ {
+ tcu::Format::BitDesc(VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR, "VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR"),
+ tcu::Format::BitDesc(VK_DISPLAY_PLANE_ALPHA_GLOBAL_BIT_KHR, "VK_DISPLAY_PLANE_ALPHA_GLOBAL_BIT_KHR"),
+ tcu::Format::BitDesc(VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR, "VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR"),
+ tcu::Format::BitDesc(VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR, "VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR"),
+ };
+ return tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));
+}
+
+tcu::Format::Bitfield<32> getInstanceCreateFlagsStr (VkInstanceCreateFlags value)
+{
+ return tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);
+}
+
+tcu::Format::Bitfield<32> getDeviceCreateFlagsStr (VkDeviceCreateFlags value)
+{
+ return tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);
+}
+
+tcu::Format::Bitfield<32> getDeviceQueueCreateFlagsStr (VkDeviceQueueCreateFlags value)
+{
+ return tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);
+}
+
+tcu::Format::Bitfield<32> getMemoryMapFlagsStr (VkMemoryMapFlags value)
+{
+ return tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);
+}
+
+tcu::Format::Bitfield<32> getSemaphoreCreateFlagsStr (VkSemaphoreCreateFlags value)
+{
+ return tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);
+}
+
+tcu::Format::Bitfield<32> getEventCreateFlagsStr (VkEventCreateFlags value)
+{
+ return tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);
+}
+
+tcu::Format::Bitfield<32> getQueryPoolCreateFlagsStr (VkQueryPoolCreateFlags value)
+{
+ return tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);
+}
+
+tcu::Format::Bitfield<32> getBufferViewCreateFlagsStr (VkBufferViewCreateFlags value)
+{
+ return tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);
+}
+
+tcu::Format::Bitfield<32> getImageViewCreateFlagsStr (VkImageViewCreateFlags value)
+{
+ return tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);
+}
+
+tcu::Format::Bitfield<32> getShaderModuleCreateFlagsStr (VkShaderModuleCreateFlags value)
+{
+ return tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);
+}
+
+tcu::Format::Bitfield<32> getPipelineCacheCreateFlagsStr (VkPipelineCacheCreateFlags value)
+{
+ return tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);
+}
+
+tcu::Format::Bitfield<32> getPipelineShaderStageCreateFlagsStr (VkPipelineShaderStageCreateFlags value)
+{
+ return tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);
+}
+
+tcu::Format::Bitfield<32> getPipelineVertexInputStateCreateFlagsStr (VkPipelineVertexInputStateCreateFlags value)
+{
+ return tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);
+}
+
+tcu::Format::Bitfield<32> getPipelineInputAssemblyStateCreateFlagsStr (VkPipelineInputAssemblyStateCreateFlags value)
+{
+ return tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);
+}
+
+tcu::Format::Bitfield<32> getPipelineTesselationStateCreateFlagsStr (VkPipelineTesselationStateCreateFlags value)
+{
+ return tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);
+}
+
+tcu::Format::Bitfield<32> getPipelineViewportStateCreateFlagsStr (VkPipelineViewportStateCreateFlags value)
+{
+ return tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);
+}
+
+tcu::Format::Bitfield<32> getPipelineRasterizationStateCreateFlagsStr (VkPipelineRasterizationStateCreateFlags value)
+{
+ return tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);
+}
+
+tcu::Format::Bitfield<32> getPipelineMultisampleStateCreateFlagsStr (VkPipelineMultisampleStateCreateFlags value)
+{
+ return tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);
+}
+
+tcu::Format::Bitfield<32> getPipelineDepthStencilStateCreateFlagsStr (VkPipelineDepthStencilStateCreateFlags value)
+{
+ return tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);
+}
+
+tcu::Format::Bitfield<32> getPipelineColorBlendStateCreateFlagsStr (VkPipelineColorBlendStateCreateFlags value)
+{
+ return tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);
+}
+
+tcu::Format::Bitfield<32> getPipelineDynamicStateCreateFlagsStr (VkPipelineDynamicStateCreateFlags value)
+{
+ return tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);
+}
+
+tcu::Format::Bitfield<32> getPipelineLayoutCreateFlagsStr (VkPipelineLayoutCreateFlags value)
+{
+ return tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);
+}
+
+tcu::Format::Bitfield<32> getSamplerCreateFlagsStr (VkSamplerCreateFlags value)
+{
+ return tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);
+}
+
+tcu::Format::Bitfield<32> getDescriptorSetLayoutCreateFlagsStr (VkDescriptorSetLayoutCreateFlags value)
+{
+ return tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);
+}
+
+tcu::Format::Bitfield<32> getDescriptorPoolResetFlagsStr (VkDescriptorPoolResetFlags value)
+{
+ return tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);
+}
+
+tcu::Format::Bitfield<32> getFramebufferCreateFlagsStr (VkFramebufferCreateFlags value)
+{
+ return tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);
+}
+
+tcu::Format::Bitfield<32> getRenderPassCreateFlagsStr (VkRenderPassCreateFlags value)
+{
+ return tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);
+}
+
+tcu::Format::Bitfield<32> getSubpassDescriptionFlagsStr (VkSubpassDescriptionFlags value)
+{
+ return tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);
+}
+
+tcu::Format::Bitfield<32> getSwapchainCreateFlagsKHRStr (VkSwapchainCreateFlagsKHR value)
+{
+ return tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);
+}
+
+tcu::Format::Bitfield<32> getDisplayModeCreateFlagsKHRStr (VkDisplayModeCreateFlagsKHR value)
+{
+ return tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);
+}
+
+tcu::Format::Bitfield<32> getDisplaySurfaceCreateFlagsKHRStr (VkDisplaySurfaceCreateFlagsKHR value)
+{
+ return tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);
+}
+
+std::ostream& operator<< (std::ostream& s, const VkApplicationInfo& value)
+{
+ s << "VkApplicationInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tpApplicationName = " << getCharPtrStr(value.pApplicationName) << '\n';
+ s << "\tapplicationVersion = " << value.applicationVersion << '\n';
+ s << "\tpEngineName = " << getCharPtrStr(value.pEngineName) << '\n';
+ s << "\tengineVersion = " << value.engineVersion << '\n';
+ s << "\tapiVersion = " << value.apiVersion << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkInstanceCreateInfo& value)
+{
+ s << "VkInstanceCreateInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tflags = " << getInstanceCreateFlagsStr(value.flags) << '\n';
+ s << "\tpApplicationInfo = " << value.pApplicationInfo << '\n';
+ s << "\tenabledLayerNameCount = " << value.enabledLayerNameCount << '\n';
+ s << "\tppEnabledLayerNames = " << value.ppEnabledLayerNames << '\n';
+ s << "\tenabledExtensionNameCount = " << value.enabledExtensionNameCount << '\n';
+ s << "\tppEnabledExtensionNames = " << value.ppEnabledExtensionNames << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkAllocationCallbacks& value)
+{
+ s << "VkAllocationCallbacks = {\n";
+ s << "\tpUserData = " << value.pUserData << '\n';
+ s << "\tpfnAllocation = " << value.pfnAllocation << '\n';
+ s << "\tpfnReallocation = " << value.pfnReallocation << '\n';
+ s << "\tpfnFree = " << value.pfnFree << '\n';
+ s << "\tpfnInternalAllocation = " << value.pfnInternalAllocation << '\n';
+ s << "\tpfnInternalFree = " << value.pfnInternalFree << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkPhysicalDeviceFeatures& value)
+{
+ s << "VkPhysicalDeviceFeatures = {\n";
+ s << "\trobustBufferAccess = " << value.robustBufferAccess << '\n';
+ s << "\tfullDrawIndexUint32 = " << value.fullDrawIndexUint32 << '\n';
+ s << "\timageCubeArray = " << value.imageCubeArray << '\n';
+ s << "\tindependentBlend = " << value.independentBlend << '\n';
+ s << "\tgeometryShader = " << value.geometryShader << '\n';
+ s << "\ttessellationShader = " << value.tessellationShader << '\n';
+ s << "\tsampleRateShading = " << value.sampleRateShading << '\n';
+ s << "\tdualSrcBlend = " << value.dualSrcBlend << '\n';
+ s << "\tlogicOp = " << value.logicOp << '\n';
+ s << "\tmultiDrawIndirect = " << value.multiDrawIndirect << '\n';
+ s << "\tdepthClamp = " << value.depthClamp << '\n';
+ s << "\tdepthBiasClamp = " << value.depthBiasClamp << '\n';
+ s << "\tfillModeNonSolid = " << value.fillModeNonSolid << '\n';
+ s << "\tdepthBounds = " << value.depthBounds << '\n';
+ s << "\twideLines = " << value.wideLines << '\n';
+ s << "\tlargePoints = " << value.largePoints << '\n';
+ s << "\talphaToOne = " << value.alphaToOne << '\n';
+ s << "\tmultiViewport = " << value.multiViewport << '\n';
+ s << "\tsamplerAnisotropy = " << value.samplerAnisotropy << '\n';
+ s << "\ttextureCompressionETC2 = " << value.textureCompressionETC2 << '\n';
+ s << "\ttextureCompressionASTC_LDR = " << value.textureCompressionASTC_LDR << '\n';
+ s << "\ttextureCompressionBC = " << value.textureCompressionBC << '\n';
+ s << "\tocclusionQueryPrecise = " << value.occlusionQueryPrecise << '\n';
+ s << "\tpipelineStatisticsQuery = " << value.pipelineStatisticsQuery << '\n';
+ s << "\tvertexPipelineStoresAndAtomics = " << value.vertexPipelineStoresAndAtomics << '\n';
+ s << "\tfragmentStoresAndAtomics = " << value.fragmentStoresAndAtomics << '\n';
+ s << "\tshaderTessellationAndGeometryPointSize = " << value.shaderTessellationAndGeometryPointSize << '\n';
+ s << "\tshaderImageGatherExtended = " << value.shaderImageGatherExtended << '\n';
+ s << "\tshaderStorageImageExtendedFormats = " << value.shaderStorageImageExtendedFormats << '\n';
+ s << "\tshaderStorageImageMultisample = " << value.shaderStorageImageMultisample << '\n';
+ s << "\tshaderStorageImageReadWithoutFormat = " << value.shaderStorageImageReadWithoutFormat << '\n';
+ s << "\tshaderStorageImageWriteWithoutFormat = " << value.shaderStorageImageWriteWithoutFormat << '\n';
+ s << "\tshaderUniformBufferArrayDynamicIndexing = " << value.shaderUniformBufferArrayDynamicIndexing << '\n';
+ s << "\tshaderSampledImageArrayDynamicIndexing = " << value.shaderSampledImageArrayDynamicIndexing << '\n';
+ s << "\tshaderStorageBufferArrayDynamicIndexing = " << value.shaderStorageBufferArrayDynamicIndexing << '\n';
+ s << "\tshaderStorageImageArrayDynamicIndexing = " << value.shaderStorageImageArrayDynamicIndexing << '\n';
+ s << "\tshaderClipDistance = " << value.shaderClipDistance << '\n';
+ s << "\tshaderCullDistance = " << value.shaderCullDistance << '\n';
+ s << "\tshaderFloat64 = " << value.shaderFloat64 << '\n';
+ s << "\tshaderInt64 = " << value.shaderInt64 << '\n';
+ s << "\tshaderInt16 = " << value.shaderInt16 << '\n';
+ s << "\tshaderResourceResidency = " << value.shaderResourceResidency << '\n';
+ s << "\tshaderResourceMinLod = " << value.shaderResourceMinLod << '\n';
+ s << "\tsparseBinding = " << value.sparseBinding << '\n';
+ s << "\tsparseResidencyBuffer = " << value.sparseResidencyBuffer << '\n';
+ s << "\tsparseResidencyImage2D = " << value.sparseResidencyImage2D << '\n';
+ s << "\tsparseResidencyImage3D = " << value.sparseResidencyImage3D << '\n';
+ s << "\tsparseResidency2Samples = " << value.sparseResidency2Samples << '\n';
+ s << "\tsparseResidency4Samples = " << value.sparseResidency4Samples << '\n';
+ s << "\tsparseResidency8Samples = " << value.sparseResidency8Samples << '\n';
+ s << "\tsparseResidency16Samples = " << value.sparseResidency16Samples << '\n';
+ s << "\tsparseResidencyAliased = " << value.sparseResidencyAliased << '\n';
+ s << "\tvariableMultisampleRate = " << value.variableMultisampleRate << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkFormatProperties& value)
+{
+ s << "VkFormatProperties = {\n";
+ s << "\tlinearTilingFeatures = " << getFormatFeatureFlagsStr(value.linearTilingFeatures) << '\n';
+ s << "\toptimalTilingFeatures = " << getFormatFeatureFlagsStr(value.optimalTilingFeatures) << '\n';
+ s << "\tbufferFeatures = " << getFormatFeatureFlagsStr(value.bufferFeatures) << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkExtent3D& value)
+{
+ s << "VkExtent3D = {\n";
+ s << "\twidth = " << value.width << '\n';
+ s << "\theight = " << value.height << '\n';
+ s << "\tdepth = " << value.depth << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkImageFormatProperties& value)
+{
+ s << "VkImageFormatProperties = {\n";
+ s << "\tmaxExtent = " << value.maxExtent << '\n';
+ s << "\tmaxMipLevels = " << value.maxMipLevels << '\n';
+ s << "\tmaxArrayLayers = " << value.maxArrayLayers << '\n';
+ s << "\tsampleCounts = " << getSampleCountFlagsStr(value.sampleCounts) << '\n';
+ s << "\tmaxResourceSize = " << value.maxResourceSize << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkPhysicalDeviceLimits& value)
+{
+ s << "VkPhysicalDeviceLimits = {\n";
+ s << "\tmaxImageDimension1D = " << value.maxImageDimension1D << '\n';
+ s << "\tmaxImageDimension2D = " << value.maxImageDimension2D << '\n';
+ s << "\tmaxImageDimension3D = " << value.maxImageDimension3D << '\n';
+ s << "\tmaxImageDimensionCube = " << value.maxImageDimensionCube << '\n';
+ s << "\tmaxImageArrayLayers = " << value.maxImageArrayLayers << '\n';
+ s << "\tmaxTexelBufferElements = " << value.maxTexelBufferElements << '\n';
+ s << "\tmaxUniformBufferRange = " << value.maxUniformBufferRange << '\n';
+ s << "\tmaxStorageBufferRange = " << value.maxStorageBufferRange << '\n';
+ s << "\tmaxPushConstantsSize = " << value.maxPushConstantsSize << '\n';
+ s << "\tmaxMemoryAllocationCount = " << value.maxMemoryAllocationCount << '\n';
+ s << "\tmaxSamplerAllocationCount = " << value.maxSamplerAllocationCount << '\n';
+ s << "\tbufferImageGranularity = " << value.bufferImageGranularity << '\n';
+ s << "\tsparseAddressSpaceSize = " << value.sparseAddressSpaceSize << '\n';
+ s << "\tmaxBoundDescriptorSets = " << value.maxBoundDescriptorSets << '\n';
+ s << "\tmaxPerStageDescriptorSamplers = " << value.maxPerStageDescriptorSamplers << '\n';
+ s << "\tmaxPerStageDescriptorUniformBuffers = " << value.maxPerStageDescriptorUniformBuffers << '\n';
+ s << "\tmaxPerStageDescriptorStorageBuffers = " << value.maxPerStageDescriptorStorageBuffers << '\n';
+ s << "\tmaxPerStageDescriptorSampledImages = " << value.maxPerStageDescriptorSampledImages << '\n';
+ s << "\tmaxPerStageDescriptorStorageImages = " << value.maxPerStageDescriptorStorageImages << '\n';
+ s << "\tmaxPerStageDescriptorInputAttachments = " << value.maxPerStageDescriptorInputAttachments << '\n';
+ s << "\tmaxPerStageResources = " << value.maxPerStageResources << '\n';
+ s << "\tmaxDescriptorSetSamplers = " << value.maxDescriptorSetSamplers << '\n';
+ s << "\tmaxDescriptorSetUniformBuffers = " << value.maxDescriptorSetUniformBuffers << '\n';
+ s << "\tmaxDescriptorSetUniformBuffersDynamic = " << value.maxDescriptorSetUniformBuffersDynamic << '\n';
+ s << "\tmaxDescriptorSetStorageBuffers = " << value.maxDescriptorSetStorageBuffers << '\n';
+ s << "\tmaxDescriptorSetStorageBuffersDynamic = " << value.maxDescriptorSetStorageBuffersDynamic << '\n';
+ s << "\tmaxDescriptorSetSampledImages = " << value.maxDescriptorSetSampledImages << '\n';
+ s << "\tmaxDescriptorSetStorageImages = " << value.maxDescriptorSetStorageImages << '\n';
+ s << "\tmaxDescriptorSetInputAttachments = " << value.maxDescriptorSetInputAttachments << '\n';
+ s << "\tmaxVertexInputAttributes = " << value.maxVertexInputAttributes << '\n';
+ s << "\tmaxVertexInputBindings = " << value.maxVertexInputBindings << '\n';
+ s << "\tmaxVertexInputAttributeOffset = " << value.maxVertexInputAttributeOffset << '\n';
+ s << "\tmaxVertexInputBindingStride = " << value.maxVertexInputBindingStride << '\n';
+ s << "\tmaxVertexOutputComponents = " << value.maxVertexOutputComponents << '\n';
+ s << "\tmaxTessellationGenerationLevel = " << value.maxTessellationGenerationLevel << '\n';
+ s << "\tmaxTessellationPatchSize = " << value.maxTessellationPatchSize << '\n';
+ s << "\tmaxTessellationControlPerVertexInputComponents = " << value.maxTessellationControlPerVertexInputComponents << '\n';
+ s << "\tmaxTessellationControlPerVertexOutputComponents = " << value.maxTessellationControlPerVertexOutputComponents << '\n';
+ s << "\tmaxTessellationControlPerPatchOutputComponents = " << value.maxTessellationControlPerPatchOutputComponents << '\n';
+ s << "\tmaxTessellationControlTotalOutputComponents = " << value.maxTessellationControlTotalOutputComponents << '\n';
+ s << "\tmaxTessellationEvaluationInputComponents = " << value.maxTessellationEvaluationInputComponents << '\n';
+ s << "\tmaxTessellationEvaluationOutputComponents = " << value.maxTessellationEvaluationOutputComponents << '\n';
+ s << "\tmaxGeometryShaderInvocations = " << value.maxGeometryShaderInvocations << '\n';
+ s << "\tmaxGeometryInputComponents = " << value.maxGeometryInputComponents << '\n';
+ s << "\tmaxGeometryOutputComponents = " << value.maxGeometryOutputComponents << '\n';
+ s << "\tmaxGeometryOutputVertices = " << value.maxGeometryOutputVertices << '\n';
+ s << "\tmaxGeometryTotalOutputComponents = " << value.maxGeometryTotalOutputComponents << '\n';
+ s << "\tmaxFragmentInputComponents = " << value.maxFragmentInputComponents << '\n';
+ s << "\tmaxFragmentOutputAttachments = " << value.maxFragmentOutputAttachments << '\n';
+ s << "\tmaxFragmentDualSrcAttachments = " << value.maxFragmentDualSrcAttachments << '\n';
+ s << "\tmaxFragmentCombinedOutputResources = " << value.maxFragmentCombinedOutputResources << '\n';
+ s << "\tmaxComputeSharedMemorySize = " << value.maxComputeSharedMemorySize << '\n';
+ s << "\tmaxComputeWorkGroupCount = " << '\n' << tcu::formatArray(DE_ARRAY_BEGIN(value.maxComputeWorkGroupCount), DE_ARRAY_END(value.maxComputeWorkGroupCount)) << '\n';
+ s << "\tmaxComputeWorkGroupInvocations = " << value.maxComputeWorkGroupInvocations << '\n';
+ s << "\tmaxComputeWorkGroupSize = " << '\n' << tcu::formatArray(DE_ARRAY_BEGIN(value.maxComputeWorkGroupSize), DE_ARRAY_END(value.maxComputeWorkGroupSize)) << '\n';
+ s << "\tsubPixelPrecisionBits = " << value.subPixelPrecisionBits << '\n';
+ s << "\tsubTexelPrecisionBits = " << value.subTexelPrecisionBits << '\n';
+ s << "\tmipmapPrecisionBits = " << value.mipmapPrecisionBits << '\n';
+ s << "\tmaxDrawIndexedIndexValue = " << value.maxDrawIndexedIndexValue << '\n';
+ s << "\tmaxDrawIndirectCount = " << value.maxDrawIndirectCount << '\n';
+ s << "\tmaxSamplerLodBias = " << value.maxSamplerLodBias << '\n';
+ s << "\tmaxSamplerAnisotropy = " << value.maxSamplerAnisotropy << '\n';
+ s << "\tmaxViewports = " << value.maxViewports << '\n';
+ s << "\tmaxViewportDimensions = " << '\n' << tcu::formatArray(DE_ARRAY_BEGIN(value.maxViewportDimensions), DE_ARRAY_END(value.maxViewportDimensions)) << '\n';
+ s << "\tviewportBoundsRange = " << '\n' << tcu::formatArray(DE_ARRAY_BEGIN(value.viewportBoundsRange), DE_ARRAY_END(value.viewportBoundsRange)) << '\n';
+ s << "\tviewportSubPixelBits = " << value.viewportSubPixelBits << '\n';
+ s << "\tminMemoryMapAlignment = " << value.minMemoryMapAlignment << '\n';
+ s << "\tminTexelBufferOffsetAlignment = " << value.minTexelBufferOffsetAlignment << '\n';
+ s << "\tminUniformBufferOffsetAlignment = " << value.minUniformBufferOffsetAlignment << '\n';
+ s << "\tminStorageBufferOffsetAlignment = " << value.minStorageBufferOffsetAlignment << '\n';
+ s << "\tminTexelOffset = " << value.minTexelOffset << '\n';
+ s << "\tmaxTexelOffset = " << value.maxTexelOffset << '\n';
+ s << "\tminTexelGatherOffset = " << value.minTexelGatherOffset << '\n';
+ s << "\tmaxTexelGatherOffset = " << value.maxTexelGatherOffset << '\n';
+ s << "\tminInterpolationOffset = " << value.minInterpolationOffset << '\n';
+ s << "\tmaxInterpolationOffset = " << value.maxInterpolationOffset << '\n';
+ s << "\tsubPixelInterpolationOffsetBits = " << value.subPixelInterpolationOffsetBits << '\n';
+ s << "\tmaxFramebufferWidth = " << value.maxFramebufferWidth << '\n';
+ s << "\tmaxFramebufferHeight = " << value.maxFramebufferHeight << '\n';
+ s << "\tmaxFramebufferLayers = " << value.maxFramebufferLayers << '\n';
+ s << "\tframebufferColorSampleCounts = " << getSampleCountFlagsStr(value.framebufferColorSampleCounts) << '\n';
+ s << "\tframebufferDepthSampleCounts = " << getSampleCountFlagsStr(value.framebufferDepthSampleCounts) << '\n';
+ s << "\tframebufferStencilSampleCounts = " << getSampleCountFlagsStr(value.framebufferStencilSampleCounts) << '\n';
+ s << "\tframebufferNoAttachmentsSampleCounts = " << getSampleCountFlagsStr(value.framebufferNoAttachmentsSampleCounts) << '\n';
+ s << "\tmaxColorAttachments = " << value.maxColorAttachments << '\n';
+ s << "\tsampledImageColorSampleCounts = " << getSampleCountFlagsStr(value.sampledImageColorSampleCounts) << '\n';
+ s << "\tsampledImageIntegerSampleCounts = " << getSampleCountFlagsStr(value.sampledImageIntegerSampleCounts) << '\n';
+ s << "\tsampledImageDepthSampleCounts = " << getSampleCountFlagsStr(value.sampledImageDepthSampleCounts) << '\n';
+ s << "\tsampledImageStencilSampleCounts = " << getSampleCountFlagsStr(value.sampledImageStencilSampleCounts) << '\n';
+ s << "\tstorageImageSampleCounts = " << getSampleCountFlagsStr(value.storageImageSampleCounts) << '\n';
+ s << "\tmaxSampleMaskWords = " << value.maxSampleMaskWords << '\n';
+ s << "\ttimestampPeriod = " << value.timestampPeriod << '\n';
+ s << "\tmaxClipDistances = " << value.maxClipDistances << '\n';
+ s << "\tmaxCullDistances = " << value.maxCullDistances << '\n';
+ s << "\tmaxCombinedClipAndCullDistances = " << value.maxCombinedClipAndCullDistances << '\n';
+ s << "\tdiscreteQueuePriorities = " << value.discreteQueuePriorities << '\n';
+ s << "\tpointSizeRange = " << '\n' << tcu::formatArray(DE_ARRAY_BEGIN(value.pointSizeRange), DE_ARRAY_END(value.pointSizeRange)) << '\n';
+ s << "\tlineWidthRange = " << '\n' << tcu::formatArray(DE_ARRAY_BEGIN(value.lineWidthRange), DE_ARRAY_END(value.lineWidthRange)) << '\n';
+ s << "\tpointSizeGranularity = " << value.pointSizeGranularity << '\n';
+ s << "\tlineWidthGranularity = " << value.lineWidthGranularity << '\n';
+ s << "\tstrictLines = " << value.strictLines << '\n';
+ s << "\tstandardSampleLocations = " << value.standardSampleLocations << '\n';
+ s << "\toptimalBufferCopyOffsetAlignment = " << value.optimalBufferCopyOffsetAlignment << '\n';
+ s << "\toptimalBufferCopyRowPitchAlignment = " << value.optimalBufferCopyRowPitchAlignment << '\n';
+ s << "\tnonCoherentAtomSize = " << value.nonCoherentAtomSize << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkPhysicalDeviceSparseProperties& value)
+{
+ s << "VkPhysicalDeviceSparseProperties = {\n";
+ s << "\tresidencyStandard2DBlockShape = " << value.residencyStandard2DBlockShape << '\n';
+ s << "\tresidencyStandard2DMultisampleBlockShape = " << value.residencyStandard2DMultisampleBlockShape << '\n';
+ s << "\tresidencyStandard3DBlockShape = " << value.residencyStandard3DBlockShape << '\n';
+ s << "\tresidencyAlignedMipSize = " << value.residencyAlignedMipSize << '\n';
+ s << "\tresidencyNonResidentStrict = " << value.residencyNonResidentStrict << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkPhysicalDeviceProperties& value)
+{
+ s << "VkPhysicalDeviceProperties = {\n";
+ s << "\tapiVersion = " << value.apiVersion << '\n';
+ s << "\tdriverVersion = " << value.driverVersion << '\n';
+ s << "\tvendorID = " << value.vendorID << '\n';
+ s << "\tdeviceID = " << value.deviceID << '\n';
+ s << "\tdeviceType = " << value.deviceType << '\n';
+ s << "\tdeviceName = " << (const char*)value.deviceName << '\n';
+ s << "\tpipelineCacheUUID = " << '\n' << tcu::formatArray(tcu::Format::HexIterator<deUint8>(DE_ARRAY_BEGIN(value.pipelineCacheUUID)), tcu::Format::HexIterator<deUint8>(DE_ARRAY_END(value.pipelineCacheUUID))) << '\n';
+ s << "\tlimits = " << value.limits << '\n';
+ s << "\tsparseProperties = " << value.sparseProperties << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkQueueFamilyProperties& value)
+{
+ s << "VkQueueFamilyProperties = {\n";
+ s << "\tqueueFlags = " << getQueueFlagsStr(value.queueFlags) << '\n';
+ s << "\tqueueCount = " << value.queueCount << '\n';
+ s << "\ttimestampValidBits = " << value.timestampValidBits << '\n';
+ s << "\tminImageTransferGranularity = " << value.minImageTransferGranularity << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkMemoryType& value)
+{
+ s << "VkMemoryType = {\n";
+ s << "\tpropertyFlags = " << getMemoryPropertyFlagsStr(value.propertyFlags) << '\n';
+ s << "\theapIndex = " << value.heapIndex << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkMemoryHeap& value)
+{
+ s << "VkMemoryHeap = {\n";
+ s << "\tsize = " << value.size << '\n';
+ s << "\tflags = " << getMemoryHeapFlagsStr(value.flags) << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkPhysicalDeviceMemoryProperties& value)
+{
+ s << "VkPhysicalDeviceMemoryProperties = {\n";
+ s << "\tmemoryTypeCount = " << value.memoryTypeCount << '\n';
+ s << "\tmemoryTypes = " << '\n' << tcu::formatArray(DE_ARRAY_BEGIN(value.memoryTypes), DE_ARRAY_END(value.memoryTypes)) << '\n';
+ s << "\tmemoryHeapCount = " << value.memoryHeapCount << '\n';
+ s << "\tmemoryHeaps = " << '\n' << tcu::formatArray(DE_ARRAY_BEGIN(value.memoryHeaps), DE_ARRAY_END(value.memoryHeaps)) << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkDeviceQueueCreateInfo& value)
+{
+ s << "VkDeviceQueueCreateInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tflags = " << getDeviceQueueCreateFlagsStr(value.flags) << '\n';
+ s << "\tqueueFamilyIndex = " << value.queueFamilyIndex << '\n';
+ s << "\tqueueCount = " << value.queueCount << '\n';
+ s << "\tpQueuePriorities = " << value.pQueuePriorities << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkDeviceCreateInfo& value)
+{
+ s << "VkDeviceCreateInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tflags = " << getDeviceCreateFlagsStr(value.flags) << '\n';
+ s << "\tqueueCreateInfoCount = " << value.queueCreateInfoCount << '\n';
+ s << "\tpQueueCreateInfos = " << value.pQueueCreateInfos << '\n';
+ s << "\tenabledLayerNameCount = " << value.enabledLayerNameCount << '\n';
+ s << "\tppEnabledLayerNames = " << value.ppEnabledLayerNames << '\n';
+ s << "\tenabledExtensionNameCount = " << value.enabledExtensionNameCount << '\n';
+ s << "\tppEnabledExtensionNames = " << value.ppEnabledExtensionNames << '\n';
+ s << "\tpEnabledFeatures = " << value.pEnabledFeatures << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkExtensionProperties& value)
+{
+ s << "VkExtensionProperties = {\n";
+ s << "\textensionName = " << (const char*)value.extensionName << '\n';
+ s << "\tspecVersion = " << value.specVersion << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkLayerProperties& value)
+{
+ s << "VkLayerProperties = {\n";
+ s << "\tlayerName = " << (const char*)value.layerName << '\n';
+ s << "\tspecVersion = " << value.specVersion << '\n';
+ s << "\timplementationVersion = " << value.implementationVersion << '\n';
+ s << "\tdescription = " << (const char*)value.description << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkSubmitInfo& value)
+{
+ s << "VkSubmitInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\twaitSemaphoreCount = " << value.waitSemaphoreCount << '\n';
+ s << "\tpWaitSemaphores = " << value.pWaitSemaphores << '\n';
+ s << "\tcommandBufferCount = " << value.commandBufferCount << '\n';
+ s << "\tpCommandBuffers = " << value.pCommandBuffers << '\n';
+ s << "\tsignalSemaphoreCount = " << value.signalSemaphoreCount << '\n';
+ s << "\tpSignalSemaphores = " << value.pSignalSemaphores << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkMemoryAllocateInfo& value)
+{
+ s << "VkMemoryAllocateInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tallocationSize = " << value.allocationSize << '\n';
+ s << "\tmemoryTypeIndex = " << value.memoryTypeIndex << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkMappedMemoryRange& value)
+{
+ s << "VkMappedMemoryRange = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tmemory = " << value.memory << '\n';
+ s << "\toffset = " << value.offset << '\n';
+ s << "\tsize = " << value.size << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkMemoryRequirements& value)
+{
+ s << "VkMemoryRequirements = {\n";
+ s << "\tsize = " << value.size << '\n';
+ s << "\talignment = " << value.alignment << '\n';
+ s << "\tmemoryTypeBits = " << value.memoryTypeBits << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkSparseImageFormatProperties& value)
+{
+ s << "VkSparseImageFormatProperties = {\n";
+ s << "\taspectMask = " << getImageAspectFlagsStr(value.aspectMask) << '\n';
+ s << "\timageGranularity = " << value.imageGranularity << '\n';
+ s << "\tflags = " << getSparseImageFormatFlagsStr(value.flags) << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkSparseImageMemoryRequirements& value)
+{
+ s << "VkSparseImageMemoryRequirements = {\n";
+ s << "\tformatProperties = " << value.formatProperties << '\n';
+ s << "\timageMipTailStartLod = " << value.imageMipTailStartLod << '\n';
+ s << "\timageMipTailSize = " << value.imageMipTailSize << '\n';
+ s << "\timageMipTailOffset = " << value.imageMipTailOffset << '\n';
+ s << "\timageMipTailStride = " << value.imageMipTailStride << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkSparseMemoryBind& value)
+{
+ s << "VkSparseMemoryBind = {\n";
+ s << "\tresourceOffset = " << value.resourceOffset << '\n';
+ s << "\tsize = " << value.size << '\n';
+ s << "\tmemory = " << value.memory << '\n';
+ s << "\tmemoryOffset = " << value.memoryOffset << '\n';
+ s << "\tflags = " << getSparseMemoryBindFlagsStr(value.flags) << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkSparseBufferMemoryBindInfo& value)
+{
+ s << "VkSparseBufferMemoryBindInfo = {\n";
+ s << "\tbuffer = " << value.buffer << '\n';
+ s << "\tbindCount = " << value.bindCount << '\n';
+ s << "\tpBinds = " << value.pBinds << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkSparseImageOpaqueMemoryBindInfo& value)
+{
+ s << "VkSparseImageOpaqueMemoryBindInfo = {\n";
+ s << "\timage = " << value.image << '\n';
+ s << "\tbindCount = " << value.bindCount << '\n';
+ s << "\tpBinds = " << value.pBinds << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkImageSubresource& value)
+{
+ s << "VkImageSubresource = {\n";
+ s << "\taspectMask = " << getImageAspectFlagsStr(value.aspectMask) << '\n';
+ s << "\tmipLevel = " << value.mipLevel << '\n';
+ s << "\tarrayLayer = " << value.arrayLayer << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkOffset3D& value)
+{
+ s << "VkOffset3D = {\n";
+ s << "\tx = " << value.x << '\n';
+ s << "\ty = " << value.y << '\n';
+ s << "\tz = " << value.z << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkSparseImageMemoryBind& value)
+{
+ s << "VkSparseImageMemoryBind = {\n";
+ s << "\tsubresource = " << value.subresource << '\n';
+ s << "\toffset = " << value.offset << '\n';
+ s << "\textent = " << value.extent << '\n';
+ s << "\tmemory = " << value.memory << '\n';
+ s << "\tmemoryOffset = " << value.memoryOffset << '\n';
+ s << "\tflags = " << getSparseMemoryBindFlagsStr(value.flags) << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkSparseImageMemoryBindInfo& value)
+{
+ s << "VkSparseImageMemoryBindInfo = {\n";
+ s << "\timage = " << value.image << '\n';
+ s << "\tbindCount = " << value.bindCount << '\n';
+ s << "\tpBinds = " << value.pBinds << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkBindSparseInfo& value)
+{
+ s << "VkBindSparseInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\twaitSemaphoreCount = " << value.waitSemaphoreCount << '\n';
+ s << "\tpWaitSemaphores = " << value.pWaitSemaphores << '\n';
+ s << "\tbufferBindCount = " << value.bufferBindCount << '\n';
+ s << "\tpBufferBinds = " << value.pBufferBinds << '\n';
+ s << "\timageOpaqueBindCount = " << value.imageOpaqueBindCount << '\n';
+ s << "\tpImageOpaqueBinds = " << value.pImageOpaqueBinds << '\n';
+ s << "\timageBindCount = " << value.imageBindCount << '\n';
+ s << "\tpImageBinds = " << value.pImageBinds << '\n';
+ s << "\tsignalSemaphoreCount = " << value.signalSemaphoreCount << '\n';
+ s << "\tpSignalSemaphores = " << value.pSignalSemaphores << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkFenceCreateInfo& value)
+{
+ s << "VkFenceCreateInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tflags = " << getFenceCreateFlagsStr(value.flags) << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkSemaphoreCreateInfo& value)
+{
+ s << "VkSemaphoreCreateInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tflags = " << getSemaphoreCreateFlagsStr(value.flags) << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkEventCreateInfo& value)
+{
+ s << "VkEventCreateInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tflags = " << getEventCreateFlagsStr(value.flags) << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkQueryPoolCreateInfo& value)
+{
+ s << "VkQueryPoolCreateInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tflags = " << getQueryPoolCreateFlagsStr(value.flags) << '\n';
+ s << "\tqueryType = " << value.queryType << '\n';
+ s << "\tentryCount = " << value.entryCount << '\n';
+ s << "\tpipelineStatistics = " << getQueryPipelineStatisticFlagsStr(value.pipelineStatistics) << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkBufferCreateInfo& value)
+{
+ s << "VkBufferCreateInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tflags = " << getBufferCreateFlagsStr(value.flags) << '\n';
+ s << "\tsize = " << value.size << '\n';
+ s << "\tusage = " << getBufferUsageFlagsStr(value.usage) << '\n';
+ s << "\tsharingMode = " << value.sharingMode << '\n';
+ s << "\tqueueFamilyIndexCount = " << value.queueFamilyIndexCount << '\n';
+ s << "\tpQueueFamilyIndices = " << value.pQueueFamilyIndices << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkBufferViewCreateInfo& value)
+{
+ s << "VkBufferViewCreateInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tflags = " << getBufferViewCreateFlagsStr(value.flags) << '\n';
+ s << "\tbuffer = " << value.buffer << '\n';
+ s << "\tformat = " << value.format << '\n';
+ s << "\toffset = " << value.offset << '\n';
+ s << "\trange = " << value.range << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkImageCreateInfo& value)
+{
+ s << "VkImageCreateInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tflags = " << getImageCreateFlagsStr(value.flags) << '\n';
+ s << "\timageType = " << value.imageType << '\n';
+ s << "\tformat = " << value.format << '\n';
+ s << "\textent = " << value.extent << '\n';
+ s << "\tmipLevels = " << value.mipLevels << '\n';
+ s << "\tarrayLayers = " << value.arrayLayers << '\n';
+ s << "\tsamples = " << value.samples << '\n';
+ s << "\ttiling = " << value.tiling << '\n';
+ s << "\tusage = " << getImageUsageFlagsStr(value.usage) << '\n';
+ s << "\tsharingMode = " << value.sharingMode << '\n';
+ s << "\tqueueFamilyIndexCount = " << value.queueFamilyIndexCount << '\n';
+ s << "\tpQueueFamilyIndices = " << value.pQueueFamilyIndices << '\n';
+ s << "\tinitialLayout = " << value.initialLayout << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkSubresourceLayout& value)
+{
+ s << "VkSubresourceLayout = {\n";
+ s << "\toffset = " << value.offset << '\n';
+ s << "\tsize = " << value.size << '\n';
+ s << "\trowPitch = " << value.rowPitch << '\n';
+ s << "\tdepthPitch = " << value.depthPitch << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkComponentMapping& value)
+{
+ s << "VkComponentMapping = {\n";
+ s << "\tr = " << value.r << '\n';
+ s << "\tg = " << value.g << '\n';
+ s << "\tb = " << value.b << '\n';
+ s << "\ta = " << value.a << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkImageSubresourceRange& value)
+{
+ s << "VkImageSubresourceRange = {\n";
+ s << "\taspectMask = " << getImageAspectFlagsStr(value.aspectMask) << '\n';
+ s << "\tbaseMipLevel = " << value.baseMipLevel << '\n';
+ s << "\tlevelCount = " << value.levelCount << '\n';
+ s << "\tbaseArrayLayer = " << value.baseArrayLayer << '\n';
+ s << "\tlayerCount = " << value.layerCount << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkImageViewCreateInfo& value)
+{
+ s << "VkImageViewCreateInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tflags = " << getImageViewCreateFlagsStr(value.flags) << '\n';
+ s << "\timage = " << value.image << '\n';
+ s << "\tviewType = " << value.viewType << '\n';
+ s << "\tformat = " << value.format << '\n';
+ s << "\tcomponents = " << value.components << '\n';
+ s << "\tsubresourceRange = " << value.subresourceRange << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkShaderModuleCreateInfo& value)
+{
+ s << "VkShaderModuleCreateInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tflags = " << getShaderModuleCreateFlagsStr(value.flags) << '\n';
+ s << "\tcodeSize = " << value.codeSize << '\n';
+ s << "\tpCode = " << value.pCode << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkPipelineCacheCreateInfo& value)
+{
+ s << "VkPipelineCacheCreateInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tflags = " << getPipelineCacheCreateFlagsStr(value.flags) << '\n';
+ s << "\tinitialDataSize = " << value.initialDataSize << '\n';
+ s << "\tpInitialData = " << value.pInitialData << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkSpecializationMapEntry& value)
+{
+ s << "VkSpecializationMapEntry = {\n";
+ s << "\tconstantID = " << value.constantID << '\n';
+ s << "\toffset = " << value.offset << '\n';
+ s << "\tsize = " << value.size << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkSpecializationInfo& value)
+{
+ s << "VkSpecializationInfo = {\n";
+ s << "\tmapEntryCount = " << value.mapEntryCount << '\n';
+ s << "\tpMapEntries = " << value.pMapEntries << '\n';
+ s << "\tdataSize = " << value.dataSize << '\n';
+ s << "\tpData = " << value.pData << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkPipelineShaderStageCreateInfo& value)
+{
+ s << "VkPipelineShaderStageCreateInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tflags = " << getPipelineShaderStageCreateFlagsStr(value.flags) << '\n';
+ s << "\tstage = " << value.stage << '\n';
+ s << "\tmodule = " << value.module << '\n';
+ s << "\tpName = " << getCharPtrStr(value.pName) << '\n';
+ s << "\tpSpecializationInfo = " << value.pSpecializationInfo << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkVertexInputBindingDescription& value)
+{
+ s << "VkVertexInputBindingDescription = {\n";
+ s << "\tbinding = " << value.binding << '\n';
+ s << "\tstride = " << value.stride << '\n';
+ s << "\tinputRate = " << value.inputRate << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkVertexInputAttributeDescription& value)
+{
+ s << "VkVertexInputAttributeDescription = {\n";
+ s << "\tlocation = " << value.location << '\n';
+ s << "\tbinding = " << value.binding << '\n';
+ s << "\tformat = " << value.format << '\n';
+ s << "\toffset = " << value.offset << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkPipelineVertexInputStateCreateInfo& value)
+{
+ s << "VkPipelineVertexInputStateCreateInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tflags = " << getPipelineVertexInputStateCreateFlagsStr(value.flags) << '\n';
+ s << "\tvertexBindingDescriptionCount = " << value.vertexBindingDescriptionCount << '\n';
+ s << "\tpVertexBindingDescriptions = " << value.pVertexBindingDescriptions << '\n';
+ s << "\tvertexAttributeDescriptionCount = " << value.vertexAttributeDescriptionCount << '\n';
+ s << "\tpVertexAttributeDescriptions = " << value.pVertexAttributeDescriptions << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkPipelineInputAssemblyStateCreateInfo& value)
+{
+ s << "VkPipelineInputAssemblyStateCreateInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tflags = " << getPipelineInputAssemblyStateCreateFlagsStr(value.flags) << '\n';
+ s << "\ttopology = " << value.topology << '\n';
+ s << "\tprimitiveRestartEnable = " << value.primitiveRestartEnable << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkPipelineTessellationStateCreateInfo& value)
+{
+ s << "VkPipelineTessellationStateCreateInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tflags = " << getPipelineTesselationStateCreateFlagsStr(value.flags) << '\n';
+ s << "\tpatchControlPoints = " << value.patchControlPoints << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkViewport& value)
+{
+ s << "VkViewport = {\n";
+ s << "\tx = " << value.x << '\n';
+ s << "\ty = " << value.y << '\n';
+ s << "\twidth = " << value.width << '\n';
+ s << "\theight = " << value.height << '\n';
+ s << "\tminDepth = " << value.minDepth << '\n';
+ s << "\tmaxDepth = " << value.maxDepth << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkOffset2D& value)
+{
+ s << "VkOffset2D = {\n";
+ s << "\tx = " << value.x << '\n';
+ s << "\ty = " << value.y << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkExtent2D& value)
+{
+ s << "VkExtent2D = {\n";
+ s << "\twidth = " << value.width << '\n';
+ s << "\theight = " << value.height << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkRect2D& value)
+{
+ s << "VkRect2D = {\n";
+ s << "\toffset = " << value.offset << '\n';
+ s << "\textent = " << value.extent << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkPipelineViewportStateCreateInfo& value)
+{
+ s << "VkPipelineViewportStateCreateInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tflags = " << getPipelineViewportStateCreateFlagsStr(value.flags) << '\n';
+ s << "\tviewportCount = " << value.viewportCount << '\n';
+ s << "\tpViewports = " << value.pViewports << '\n';
+ s << "\tscissorCount = " << value.scissorCount << '\n';
+ s << "\tpScissors = " << value.pScissors << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkPipelineRasterizationStateCreateInfo& value)
+{
+ s << "VkPipelineRasterizationStateCreateInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tflags = " << getPipelineRasterizationStateCreateFlagsStr(value.flags) << '\n';
+ s << "\tdepthClampEnable = " << value.depthClampEnable << '\n';
+ s << "\trasterizerDiscardEnable = " << value.rasterizerDiscardEnable << '\n';
+ s << "\tpolygonMode = " << value.polygonMode << '\n';
+ s << "\tcullMode = " << getCullModeFlagsStr(value.cullMode) << '\n';
+ s << "\tfrontFace = " << value.frontFace << '\n';
+ s << "\tdepthBiasEnable = " << value.depthBiasEnable << '\n';
+ s << "\tdepthBiasConstantFactor = " << value.depthBiasConstantFactor << '\n';
+ s << "\tdepthBiasClamp = " << value.depthBiasClamp << '\n';
+ s << "\tdepthBiasSlopeFactor = " << value.depthBiasSlopeFactor << '\n';
+ s << "\tlineWidth = " << value.lineWidth << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkPipelineMultisampleStateCreateInfo& value)
+{
+ s << "VkPipelineMultisampleStateCreateInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tflags = " << getPipelineMultisampleStateCreateFlagsStr(value.flags) << '\n';
+ s << "\trasterizationSamples = " << value.rasterizationSamples << '\n';
+ s << "\tsampleShadingEnable = " << value.sampleShadingEnable << '\n';
+ s << "\tminSampleShading = " << value.minSampleShading << '\n';
+ s << "\tpSampleMask = " << value.pSampleMask << '\n';
+ s << "\talphaToCoverageEnable = " << value.alphaToCoverageEnable << '\n';
+ s << "\talphaToOneEnable = " << value.alphaToOneEnable << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkStencilOpState& value)
+{
+ s << "VkStencilOpState = {\n";
+ s << "\tfailOp = " << value.failOp << '\n';
+ s << "\tpassOp = " << value.passOp << '\n';
+ s << "\tdepthFailOp = " << value.depthFailOp << '\n';
+ s << "\tcompareOp = " << value.compareOp << '\n';
+ s << "\tcompareMask = " << value.compareMask << '\n';
+ s << "\twriteMask = " << value.writeMask << '\n';
+ s << "\treference = " << value.reference << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkPipelineDepthStencilStateCreateInfo& value)
+{
+ s << "VkPipelineDepthStencilStateCreateInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tflags = " << getPipelineDepthStencilStateCreateFlagsStr(value.flags) << '\n';
+ s << "\tdepthTestEnable = " << value.depthTestEnable << '\n';
+ s << "\tdepthWriteEnable = " << value.depthWriteEnable << '\n';
+ s << "\tdepthCompareOp = " << value.depthCompareOp << '\n';
+ s << "\tdepthBoundsTestEnable = " << value.depthBoundsTestEnable << '\n';
+ s << "\tstencilTestEnable = " << value.stencilTestEnable << '\n';
+ s << "\tfront = " << value.front << '\n';
+ s << "\tback = " << value.back << '\n';
+ s << "\tminDepthBounds = " << value.minDepthBounds << '\n';
+ s << "\tmaxDepthBounds = " << value.maxDepthBounds << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkPipelineColorBlendAttachmentState& value)
+{
+ s << "VkPipelineColorBlendAttachmentState = {\n";
+ s << "\tblendEnable = " << value.blendEnable << '\n';
+ s << "\tsrcColorBlendFactor = " << value.srcColorBlendFactor << '\n';
+ s << "\tdstColorBlendFactor = " << value.dstColorBlendFactor << '\n';
+ s << "\tcolorBlendOp = " << value.colorBlendOp << '\n';
+ s << "\tsrcAlphaBlendFactor = " << value.srcAlphaBlendFactor << '\n';
+ s << "\tdstAlphaBlendFactor = " << value.dstAlphaBlendFactor << '\n';
+ s << "\talphaBlendOp = " << value.alphaBlendOp << '\n';
+ s << "\tcolorWriteMask = " << getColorComponentFlagsStr(value.colorWriteMask) << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkPipelineColorBlendStateCreateInfo& value)
+{
+ s << "VkPipelineColorBlendStateCreateInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tflags = " << getPipelineColorBlendStateCreateFlagsStr(value.flags) << '\n';
+ s << "\tlogicOpEnable = " << value.logicOpEnable << '\n';
+ s << "\tlogicOp = " << value.logicOp << '\n';
+ s << "\tattachmentCount = " << value.attachmentCount << '\n';
+ s << "\tpAttachments = " << value.pAttachments << '\n';
+ s << "\tblendConstants = " << '\n' << tcu::formatArray(DE_ARRAY_BEGIN(value.blendConstants), DE_ARRAY_END(value.blendConstants)) << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkPipelineDynamicStateCreateInfo& value)
+{
+ s << "VkPipelineDynamicStateCreateInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tflags = " << getPipelineDynamicStateCreateFlagsStr(value.flags) << '\n';
+ s << "\tdynamicStateCount = " << value.dynamicStateCount << '\n';
+ s << "\tpDynamicStates = " << value.pDynamicStates << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkGraphicsPipelineCreateInfo& value)
+{
+ s << "VkGraphicsPipelineCreateInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tflags = " << getPipelineCreateFlagsStr(value.flags) << '\n';
+ s << "\tstageCount = " << value.stageCount << '\n';
+ s << "\tpStages = " << value.pStages << '\n';
+ s << "\tpVertexInputState = " << value.pVertexInputState << '\n';
+ s << "\tpInputAssemblyState = " << value.pInputAssemblyState << '\n';
+ s << "\tpTessellationState = " << value.pTessellationState << '\n';
+ s << "\tpViewportState = " << value.pViewportState << '\n';
+ s << "\tpRasterizationState = " << value.pRasterizationState << '\n';
+ s << "\tpMultisampleState = " << value.pMultisampleState << '\n';
+ s << "\tpDepthStencilState = " << value.pDepthStencilState << '\n';
+ s << "\tpColorBlendState = " << value.pColorBlendState << '\n';
+ s << "\tpDynamicState = " << value.pDynamicState << '\n';
+ s << "\tlayout = " << value.layout << '\n';
+ s << "\trenderPass = " << value.renderPass << '\n';
+ s << "\tsubpass = " << value.subpass << '\n';
+ s << "\tbasePipelineHandle = " << value.basePipelineHandle << '\n';
+ s << "\tbasePipelineIndex = " << value.basePipelineIndex << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkComputePipelineCreateInfo& value)
+{
+ s << "VkComputePipelineCreateInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tflags = " << getPipelineCreateFlagsStr(value.flags) << '\n';
+ s << "\tstage = " << value.stage << '\n';
+ s << "\tlayout = " << value.layout << '\n';
+ s << "\tbasePipelineHandle = " << value.basePipelineHandle << '\n';
+ s << "\tbasePipelineIndex = " << value.basePipelineIndex << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkPushConstantRange& value)
+{
+ s << "VkPushConstantRange = {\n";
+ s << "\tstageFlags = " << getShaderStageFlagsStr(value.stageFlags) << '\n';
+ s << "\toffset = " << value.offset << '\n';
+ s << "\tsize = " << value.size << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkPipelineLayoutCreateInfo& value)
+{
+ s << "VkPipelineLayoutCreateInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tflags = " << getPipelineLayoutCreateFlagsStr(value.flags) << '\n';
+ s << "\tsetLayoutCount = " << value.setLayoutCount << '\n';
+ s << "\tpSetLayouts = " << value.pSetLayouts << '\n';
+ s << "\tpushConstantRangeCount = " << value.pushConstantRangeCount << '\n';
+ s << "\tpPushConstantRanges = " << value.pPushConstantRanges << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkSamplerCreateInfo& value)
+{
+ s << "VkSamplerCreateInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tflags = " << getSamplerCreateFlagsStr(value.flags) << '\n';
+ s << "\tmagFilter = " << value.magFilter << '\n';
+ s << "\tminFilter = " << value.minFilter << '\n';
+ s << "\tmipmapMode = " << value.mipmapMode << '\n';
+ s << "\taddressModeU = " << value.addressModeU << '\n';
+ s << "\taddressModeV = " << value.addressModeV << '\n';
+ s << "\taddressModeW = " << value.addressModeW << '\n';
+ s << "\tmipLodBias = " << value.mipLodBias << '\n';
+ s << "\tmaxAnisotropy = " << value.maxAnisotropy << '\n';
+ s << "\tcompareEnable = " << value.compareEnable << '\n';
+ s << "\tcompareOp = " << value.compareOp << '\n';
+ s << "\tminLod = " << value.minLod << '\n';
+ s << "\tmaxLod = " << value.maxLod << '\n';
+ s << "\tborderColor = " << value.borderColor << '\n';
+ s << "\tunnormalizedCoordinates = " << value.unnormalizedCoordinates << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkDescriptorSetLayoutBinding& value)
+{
+ s << "VkDescriptorSetLayoutBinding = {\n";
+ s << "\tbinding = " << value.binding << '\n';
+ s << "\tdescriptorType = " << value.descriptorType << '\n';
+ s << "\tdescriptorCount = " << value.descriptorCount << '\n';
+ s << "\tstageFlags = " << getShaderStageFlagsStr(value.stageFlags) << '\n';
+ s << "\tpImmutableSamplers = " << value.pImmutableSamplers << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkDescriptorSetLayoutCreateInfo& value)
+{
+ s << "VkDescriptorSetLayoutCreateInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tflags = " << getDescriptorSetLayoutCreateFlagsStr(value.flags) << '\n';
+ s << "\tbindingCount = " << value.bindingCount << '\n';
+ s << "\tpBinding = " << value.pBinding << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkDescriptorPoolSize& value)
+{
+ s << "VkDescriptorPoolSize = {\n";
+ s << "\ttype = " << value.type << '\n';
+ s << "\tdescriptorCount = " << value.descriptorCount << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkDescriptorPoolCreateInfo& value)
+{
+ s << "VkDescriptorPoolCreateInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tflags = " << getDescriptorPoolCreateFlagsStr(value.flags) << '\n';
+ s << "\tmaxSets = " << value.maxSets << '\n';
+ s << "\tpoolSizeCount = " << value.poolSizeCount << '\n';
+ s << "\tpPoolSizes = " << value.pPoolSizes << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkDescriptorSetAllocateInfo& value)
+{
+ s << "VkDescriptorSetAllocateInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tdescriptorPool = " << value.descriptorPool << '\n';
+ s << "\tsetLayoutCount = " << value.setLayoutCount << '\n';
+ s << "\tpSetLayouts = " << value.pSetLayouts << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkDescriptorImageInfo& value)
+{
+ s << "VkDescriptorImageInfo = {\n";
+ s << "\tsampler = " << value.sampler << '\n';
+ s << "\timageView = " << value.imageView << '\n';
+ s << "\timageLayout = " << value.imageLayout << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkDescriptorBufferInfo& value)
+{
+ s << "VkDescriptorBufferInfo = {\n";
+ s << "\tbuffer = " << value.buffer << '\n';
+ s << "\toffset = " << value.offset << '\n';
+ s << "\trange = " << value.range << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkWriteDescriptorSet& value)
+{
+ s << "VkWriteDescriptorSet = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tdstSet = " << value.dstSet << '\n';
+ s << "\tdstBinding = " << value.dstBinding << '\n';
+ s << "\tdstArrayElement = " << value.dstArrayElement << '\n';
+ s << "\tdescriptorCount = " << value.descriptorCount << '\n';
+ s << "\tdescriptorType = " << value.descriptorType << '\n';
+ s << "\tpImageInfo = " << value.pImageInfo << '\n';
+ s << "\tpBufferInfo = " << value.pBufferInfo << '\n';
+ s << "\tpTexelBufferView = " << value.pTexelBufferView << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkCopyDescriptorSet& value)
+{
+ s << "VkCopyDescriptorSet = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tsrcSet = " << value.srcSet << '\n';
+ s << "\tsrcBinding = " << value.srcBinding << '\n';
+ s << "\tsrcArrayElement = " << value.srcArrayElement << '\n';
+ s << "\tdstSet = " << value.dstSet << '\n';
+ s << "\tdstBinding = " << value.dstBinding << '\n';
+ s << "\tdstArrayElement = " << value.dstArrayElement << '\n';
+ s << "\tdescriptorCount = " << value.descriptorCount << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkFramebufferCreateInfo& value)
+{
+ s << "VkFramebufferCreateInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tflags = " << getFramebufferCreateFlagsStr(value.flags) << '\n';
+ s << "\trenderPass = " << value.renderPass << '\n';
+ s << "\tattachmentCount = " << value.attachmentCount << '\n';
+ s << "\tpAttachments = " << value.pAttachments << '\n';
+ s << "\twidth = " << value.width << '\n';
+ s << "\theight = " << value.height << '\n';
+ s << "\tlayers = " << value.layers << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkAttachmentDescription& value)
+{
+ s << "VkAttachmentDescription = {\n";
+ s << "\tflags = " << getAttachmentDescriptionFlagsStr(value.flags) << '\n';
+ s << "\tformat = " << value.format << '\n';
+ s << "\tsamples = " << value.samples << '\n';
+ s << "\tloadOp = " << value.loadOp << '\n';
+ s << "\tstoreOp = " << value.storeOp << '\n';
+ s << "\tstencilLoadOp = " << value.stencilLoadOp << '\n';
+ s << "\tstencilStoreOp = " << value.stencilStoreOp << '\n';
+ s << "\tinitialLayout = " << value.initialLayout << '\n';
+ s << "\tfinalLayout = " << value.finalLayout << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkAttachmentReference& value)
+{
+ s << "VkAttachmentReference = {\n";
+ s << "\tattachment = " << value.attachment << '\n';
+ s << "\tlayout = " << value.layout << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkSubpassDescription& value)
+{
+ s << "VkSubpassDescription = {\n";
+ s << "\tflags = " << getSubpassDescriptionFlagsStr(value.flags) << '\n';
+ s << "\tpipelineBindPoint = " << value.pipelineBindPoint << '\n';
+ s << "\tinputAttachmentCount = " << value.inputAttachmentCount << '\n';
+ s << "\tpInputAttachments = " << value.pInputAttachments << '\n';
+ s << "\tcolorAttachmentCount = " << value.colorAttachmentCount << '\n';
+ s << "\tpColorAttachments = " << value.pColorAttachments << '\n';
+ s << "\tpResolveAttachments = " << value.pResolveAttachments << '\n';
+ s << "\tpDepthStencilAttachment = " << value.pDepthStencilAttachment << '\n';
+ s << "\tpreserveAttachmentCount = " << value.preserveAttachmentCount << '\n';
+ s << "\tpPreserveAttachments = " << value.pPreserveAttachments << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkSubpassDependency& value)
+{
+ s << "VkSubpassDependency = {\n";
+ s << "\tsrcSubpass = " << value.srcSubpass << '\n';
+ s << "\tdstSubpass = " << value.dstSubpass << '\n';
+ s << "\tsrcStageMask = " << getPipelineStageFlagsStr(value.srcStageMask) << '\n';
+ s << "\tdstStageMask = " << getPipelineStageFlagsStr(value.dstStageMask) << '\n';
+ s << "\tsrcAccessMask = " << getAccessFlagsStr(value.srcAccessMask) << '\n';
+ s << "\tdstAccessMask = " << getAccessFlagsStr(value.dstAccessMask) << '\n';
+ s << "\tdependencyFlags = " << getDependencyFlagsStr(value.dependencyFlags) << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkRenderPassCreateInfo& value)
+{
+ s << "VkRenderPassCreateInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tflags = " << getRenderPassCreateFlagsStr(value.flags) << '\n';
+ s << "\tattachmentCount = " << value.attachmentCount << '\n';
+ s << "\tpAttachments = " << value.pAttachments << '\n';
+ s << "\tsubpassCount = " << value.subpassCount << '\n';
+ s << "\tpSubpasses = " << value.pSubpasses << '\n';
+ s << "\tdependencyCount = " << value.dependencyCount << '\n';
+ s << "\tpDependencies = " << value.pDependencies << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkCommandPoolCreateInfo& value)
+{
+ s << "VkCommandPoolCreateInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tflags = " << getCommandPoolCreateFlagsStr(value.flags) << '\n';
+ s << "\tqueueFamilyIndex = " << value.queueFamilyIndex << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkCommandBufferAllocateInfo& value)
+{
+ s << "VkCommandBufferAllocateInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tcommandPool = " << value.commandPool << '\n';
+ s << "\tlevel = " << value.level << '\n';
+ s << "\tbufferCount = " << value.bufferCount << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkCommandBufferBeginInfo& value)
+{
+ s << "VkCommandBufferBeginInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tflags = " << getCommandBufferUsageFlagsStr(value.flags) << '\n';
+ s << "\trenderPass = " << value.renderPass << '\n';
+ s << "\tsubpass = " << value.subpass << '\n';
+ s << "\tframebuffer = " << value.framebuffer << '\n';
+ s << "\tocclusionQueryEnable = " << value.occlusionQueryEnable << '\n';
+ s << "\tqueryFlags = " << getQueryControlFlagsStr(value.queryFlags) << '\n';
+ s << "\tpipelineStatistics = " << getQueryPipelineStatisticFlagsStr(value.pipelineStatistics) << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkBufferCopy& value)
+{
+ s << "VkBufferCopy = {\n";
+ s << "\tsrcOffset = " << value.srcOffset << '\n';
+ s << "\tdstOffset = " << value.dstOffset << '\n';
+ s << "\tsize = " << value.size << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkImageSubresourceLayers& value)
+{
+ s << "VkImageSubresourceLayers = {\n";
+ s << "\taspectMask = " << getImageAspectFlagsStr(value.aspectMask) << '\n';
+ s << "\tmipLevel = " << value.mipLevel << '\n';
+ s << "\tbaseArrayLayer = " << value.baseArrayLayer << '\n';
+ s << "\tlayerCount = " << value.layerCount << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkImageCopy& value)
+{
+ s << "VkImageCopy = {\n";
+ s << "\tsrcSubresource = " << value.srcSubresource << '\n';
+ s << "\tsrcOffset = " << value.srcOffset << '\n';
+ s << "\tdstSubresource = " << value.dstSubresource << '\n';
+ s << "\tdstOffset = " << value.dstOffset << '\n';
+ s << "\textent = " << value.extent << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkImageBlit& value)
+{
+ s << "VkImageBlit = {\n";
+ s << "\tsrcSubresource = " << value.srcSubresource << '\n';
+ s << "\tsrcOffset = " << value.srcOffset << '\n';
+ s << "\tsrcExtent = " << value.srcExtent << '\n';
+ s << "\tdstSubresource = " << value.dstSubresource << '\n';
+ s << "\tdstOffset = " << value.dstOffset << '\n';
+ s << "\tdstExtent = " << value.dstExtent << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkBufferImageCopy& value)
+{
+ s << "VkBufferImageCopy = {\n";
+ s << "\tbufferOffset = " << value.bufferOffset << '\n';
+ s << "\tbufferRowLength = " << value.bufferRowLength << '\n';
+ s << "\tbufferImageHeight = " << value.bufferImageHeight << '\n';
+ s << "\timageSubresource = " << value.imageSubresource << '\n';
+ s << "\timageOffset = " << value.imageOffset << '\n';
+ s << "\timageExtent = " << value.imageExtent << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkClearColorValue& value)
+{
+ s << "VkClearColorValue = {\n";
+ s << "\tfloat32 = " << '\n' << tcu::formatArray(DE_ARRAY_BEGIN(value.float32), DE_ARRAY_END(value.float32)) << '\n';
+ s << "\tint32 = " << '\n' << tcu::formatArray(DE_ARRAY_BEGIN(value.int32), DE_ARRAY_END(value.int32)) << '\n';
+ s << "\tuint32 = " << '\n' << tcu::formatArray(DE_ARRAY_BEGIN(value.uint32), DE_ARRAY_END(value.uint32)) << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkClearDepthStencilValue& value)
+{
+ s << "VkClearDepthStencilValue = {\n";
+ s << "\tdepth = " << value.depth << '\n';
+ s << "\tstencil = " << value.stencil << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkClearValue& value)
+{
+ s << "VkClearValue = {\n";
+ s << "\tcolor = " << value.color << '\n';
+ s << "\tdepthStencil = " << value.depthStencil << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkClearAttachment& value)
+{
+ s << "VkClearAttachment = {\n";
+ s << "\taspectMask = " << getImageAspectFlagsStr(value.aspectMask) << '\n';
+ s << "\tcolorAttachment = " << value.colorAttachment << '\n';
+ s << "\tclearValue = " << value.clearValue << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkClearRect& value)
+{
+ s << "VkClearRect = {\n";
+ s << "\trect = " << value.rect << '\n';
+ s << "\tbaseArrayLayer = " << value.baseArrayLayer << '\n';
+ s << "\tlayerCount = " << value.layerCount << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkImageResolve& value)
+{
+ s << "VkImageResolve = {\n";
+ s << "\tsrcSubresource = " << value.srcSubresource << '\n';
+ s << "\tsrcOffset = " << value.srcOffset << '\n';
+ s << "\tdstSubresource = " << value.dstSubresource << '\n';
+ s << "\tdstOffset = " << value.dstOffset << '\n';
+ s << "\textent = " << value.extent << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkRenderPassBeginInfo& value)
+{
+ s << "VkRenderPassBeginInfo = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\trenderPass = " << value.renderPass << '\n';
+ s << "\tframebuffer = " << value.framebuffer << '\n';
+ s << "\trenderArea = " << value.renderArea << '\n';
+ s << "\tclearValueCount = " << value.clearValueCount << '\n';
+ s << "\tpClearValues = " << value.pClearValues << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkBufferMemoryBarrier& value)
+{
+ s << "VkBufferMemoryBarrier = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tsrcAccessMask = " << getAccessFlagsStr(value.srcAccessMask) << '\n';
+ s << "\tdstAccessMask = " << getAccessFlagsStr(value.dstAccessMask) << '\n';
+ s << "\tsrcQueueFamilyIndex = " << value.srcQueueFamilyIndex << '\n';
+ s << "\tdstQueueFamilyIndex = " << value.dstQueueFamilyIndex << '\n';
+ s << "\tbuffer = " << value.buffer << '\n';
+ s << "\toffset = " << value.offset << '\n';
+ s << "\tsize = " << value.size << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkDispatchIndirectCommand& value)
+{
+ s << "VkDispatchIndirectCommand = {\n";
+ s << "\tx = " << value.x << '\n';
+ s << "\ty = " << value.y << '\n';
+ s << "\tz = " << value.z << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkDrawIndexedIndirectCommand& value)
+{
+ s << "VkDrawIndexedIndirectCommand = {\n";
+ s << "\tindexCount = " << value.indexCount << '\n';
+ s << "\tinstanceCount = " << value.instanceCount << '\n';
+ s << "\tfirstIndex = " << value.firstIndex << '\n';
+ s << "\tvertexOffset = " << value.vertexOffset << '\n';
+ s << "\tfirstInstance = " << value.firstInstance << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkDrawIndirectCommand& value)
+{
+ s << "VkDrawIndirectCommand = {\n";
+ s << "\tvertexCount = " << value.vertexCount << '\n';
+ s << "\tinstanceCount = " << value.instanceCount << '\n';
+ s << "\tfirstVertex = " << value.firstVertex << '\n';
+ s << "\tfirstInstance = " << value.firstInstance << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkImageMemoryBarrier& value)
+{
+ s << "VkImageMemoryBarrier = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tsrcAccessMask = " << getAccessFlagsStr(value.srcAccessMask) << '\n';
+ s << "\tdstAccessMask = " << getAccessFlagsStr(value.dstAccessMask) << '\n';
+ s << "\toldLayout = " << value.oldLayout << '\n';
+ s << "\tnewLayout = " << value.newLayout << '\n';
+ s << "\tsrcQueueFamilyIndex = " << value.srcQueueFamilyIndex << '\n';
+ s << "\tdstQueueFamilyIndex = " << value.dstQueueFamilyIndex << '\n';
+ s << "\timage = " << value.image << '\n';
+ s << "\tsubresourceRange = " << value.subresourceRange << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkMemoryBarrier& value)
+{
+ s << "VkMemoryBarrier = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tsrcAccessMask = " << getAccessFlagsStr(value.srcAccessMask) << '\n';
+ s << "\tdstAccessMask = " << getAccessFlagsStr(value.dstAccessMask) << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkSurfaceCapabilitiesKHR& value)
+{
+ s << "VkSurfaceCapabilitiesKHR = {\n";
+ s << "\tminImageCount = " << value.minImageCount << '\n';
+ s << "\tmaxImageCount = " << value.maxImageCount << '\n';
+ s << "\tcurrentExtent = " << value.currentExtent << '\n';
+ s << "\tminImageExtent = " << value.minImageExtent << '\n';
+ s << "\tmaxImageExtent = " << value.maxImageExtent << '\n';
+ s << "\tmaxImageArrayLayers = " << value.maxImageArrayLayers << '\n';
+ s << "\tsupportedTransforms = " << getSurfaceTransformFlagsKHRStr(value.supportedTransforms) << '\n';
+ s << "\tcurrentTransform = " << value.currentTransform << '\n';
+ s << "\tsupportedCompositeAlpha = " << getCompositeAlphaFlagsKHRStr(value.supportedCompositeAlpha) << '\n';
+ s << "\tsupportedUsageFlags = " << getImageUsageFlagsStr(value.supportedUsageFlags) << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkSurfaceFormatKHR& value)
+{
+ s << "VkSurfaceFormatKHR = {\n";
+ s << "\tformat = " << value.format << '\n';
+ s << "\tcolorSpace = " << value.colorSpace << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkSwapchainCreateInfoKHR& value)
+{
+ s << "VkSwapchainCreateInfoKHR = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tflags = " << getSwapchainCreateFlagsKHRStr(value.flags) << '\n';
+ s << "\tsurface = " << value.surface << '\n';
+ s << "\tminImageCount = " << value.minImageCount << '\n';
+ s << "\timageFormat = " << value.imageFormat << '\n';
+ s << "\timageColorSpace = " << value.imageColorSpace << '\n';
+ s << "\timageExtent = " << value.imageExtent << '\n';
+ s << "\timageArrayLayers = " << value.imageArrayLayers << '\n';
+ s << "\timageUsage = " << getImageUsageFlagsStr(value.imageUsage) << '\n';
+ s << "\timageSharingMode = " << value.imageSharingMode << '\n';
+ s << "\tqueueFamilyIndexCount = " << value.queueFamilyIndexCount << '\n';
+ s << "\tpQueueFamilyIndices = " << value.pQueueFamilyIndices << '\n';
+ s << "\tpreTransform = " << value.preTransform << '\n';
+ s << "\tcompositeAlpha = " << value.compositeAlpha << '\n';
+ s << "\tpresentMode = " << value.presentMode << '\n';
+ s << "\tclipped = " << value.clipped << '\n';
+ s << "\toldSwapchain = " << value.oldSwapchain << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkPresentInfoKHR& value)
+{
+ s << "VkPresentInfoKHR = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\twaitSemaphoreCount = " << value.waitSemaphoreCount << '\n';
+ s << "\tpWaitSemaphores = " << value.pWaitSemaphores << '\n';
+ s << "\tswapchainCount = " << value.swapchainCount << '\n';
+ s << "\tpSwapchains = " << value.pSwapchains << '\n';
+ s << "\tpImageIndices = " << value.pImageIndices << '\n';
+ s << "\tpResults = " << value.pResults << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkDisplayPropertiesKHR& value)
+{
+ s << "VkDisplayPropertiesKHR = {\n";
+ s << "\tdisplay = " << value.display << '\n';
+ s << "\tdisplayName = " << getCharPtrStr(value.displayName) << '\n';
+ s << "\tphysicalDimensions = " << value.physicalDimensions << '\n';
+ s << "\tphysicalResolution = " << value.physicalResolution << '\n';
+ s << "\tsupportedTransforms = " << getSurfaceTransformFlagsKHRStr(value.supportedTransforms) << '\n';
+ s << "\tplaneReorderPossible = " << value.planeReorderPossible << '\n';
+ s << "\tpersistentContent = " << value.persistentContent << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkDisplayModeParametersKHR& value)
+{
+ s << "VkDisplayModeParametersKHR = {\n";
+ s << "\tvisibleRegion = " << value.visibleRegion << '\n';
+ s << "\trefreshRate = " << value.refreshRate << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkDisplayModePropertiesKHR& value)
+{
+ s << "VkDisplayModePropertiesKHR = {\n";
+ s << "\tdisplayMode = " << value.displayMode << '\n';
+ s << "\tparameters = " << value.parameters << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkDisplayModeCreateInfoKHR& value)
+{
+ s << "VkDisplayModeCreateInfoKHR = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tflags = " << getDisplayModeCreateFlagsKHRStr(value.flags) << '\n';
+ s << "\tparameters = " << value.parameters << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkDisplayPlaneCapabilitiesKHR& value)
+{
+ s << "VkDisplayPlaneCapabilitiesKHR = {\n";
+ s << "\tsupportedAlpha = " << getDisplayPlaneAlphaFlagsKHRStr(value.supportedAlpha) << '\n';
+ s << "\tminSrcPosition = " << value.minSrcPosition << '\n';
+ s << "\tmaxSrcPosition = " << value.maxSrcPosition << '\n';
+ s << "\tminSrcExtent = " << value.minSrcExtent << '\n';
+ s << "\tmaxSrcExtent = " << value.maxSrcExtent << '\n';
+ s << "\tminDstPosition = " << value.minDstPosition << '\n';
+ s << "\tmaxDstPosition = " << value.maxDstPosition << '\n';
+ s << "\tminDstExtent = " << value.minDstExtent << '\n';
+ s << "\tmaxDstExtent = " << value.maxDstExtent << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkDisplayPlanePropertiesKHR& value)
+{
+ s << "VkDisplayPlanePropertiesKHR = {\n";
+ s << "\tcurrentDisplay = " << value.currentDisplay << '\n';
+ s << "\tcurrentStackIndex = " << value.currentStackIndex << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkDisplaySurfaceCreateInfoKHR& value)
+{
+ s << "VkDisplaySurfaceCreateInfoKHR = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tflags = " << getDisplaySurfaceCreateFlagsKHRStr(value.flags) << '\n';
+ s << "\tdisplayMode = " << value.displayMode << '\n';
+ s << "\tplaneIndex = " << value.planeIndex << '\n';
+ s << "\tplaneStackIndex = " << value.planeStackIndex << '\n';
+ s << "\ttransform = " << value.transform << '\n';
+ s << "\tglobalAlpha = " << value.globalAlpha << '\n';
+ s << "\talphaMode = " << value.alphaMode << '\n';
+ s << "\timageExtent = " << value.imageExtent << '\n';
+ s << '}';
+ return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkDisplayPresentInfoKHR& value)
+{
+ s << "VkDisplayPresentInfoKHR = {\n";
+ s << "\tsType = " << value.sType << '\n';
+ s << "\tpNext = " << value.pNext << '\n';
+ s << "\tsrcRect = " << value.srcRect << '\n';
+ s << "\tdstRect = " << value.dstRect << '\n';
+ s << "\tpersistent = " << value.persistent << '\n';
+ s << '}';
+ return s;
+}
--- /dev/null
+/* WARNING: This is auto-generated file. Do not modify, since changes will
+ * be lost! Modify the generating script instead.
+ */
+struct VkApplicationInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ const char* pApplicationName;
+ deUint32 applicationVersion;
+ const char* pEngineName;
+ deUint32 engineVersion;
+ deUint32 apiVersion;
+};
+
+struct VkInstanceCreateInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkInstanceCreateFlags flags;
+ const VkApplicationInfo* pApplicationInfo;
+ deUint32 enabledLayerNameCount;
+ const char* const* ppEnabledLayerNames;
+ deUint32 enabledExtensionNameCount;
+ const char* const* ppEnabledExtensionNames;
+};
+
+struct VkAllocationCallbacks
+{
+ void* pUserData;
+ PFN_vkAllocationFunction pfnAllocation;
+ PFN_vkReallocationFunction pfnReallocation;
+ PFN_vkFreeFunction pfnFree;
+ PFN_vkInternalAllocationNotification pfnInternalAllocation;
+ PFN_vkInternalFreeNotification pfnInternalFree;
+};
+
+struct VkPhysicalDeviceFeatures
+{
+ VkBool32 robustBufferAccess;
+ VkBool32 fullDrawIndexUint32;
+ VkBool32 imageCubeArray;
+ VkBool32 independentBlend;
+ VkBool32 geometryShader;
+ VkBool32 tessellationShader;
+ VkBool32 sampleRateShading;
+ VkBool32 dualSrcBlend;
+ VkBool32 logicOp;
+ VkBool32 multiDrawIndirect;
+ VkBool32 depthClamp;
+ VkBool32 depthBiasClamp;
+ VkBool32 fillModeNonSolid;
+ VkBool32 depthBounds;
+ VkBool32 wideLines;
+ VkBool32 largePoints;
+ VkBool32 alphaToOne;
+ VkBool32 multiViewport;
+ VkBool32 samplerAnisotropy;
+ VkBool32 textureCompressionETC2;
+ VkBool32 textureCompressionASTC_LDR;
+ VkBool32 textureCompressionBC;
+ VkBool32 occlusionQueryPrecise;
+ VkBool32 pipelineStatisticsQuery;
+ VkBool32 vertexPipelineStoresAndAtomics;
+ VkBool32 fragmentStoresAndAtomics;
+ VkBool32 shaderTessellationAndGeometryPointSize;
+ VkBool32 shaderImageGatherExtended;
+ VkBool32 shaderStorageImageExtendedFormats;
+ VkBool32 shaderStorageImageMultisample;
+ VkBool32 shaderStorageImageReadWithoutFormat;
+ VkBool32 shaderStorageImageWriteWithoutFormat;
+ VkBool32 shaderUniformBufferArrayDynamicIndexing;
+ VkBool32 shaderSampledImageArrayDynamicIndexing;
+ VkBool32 shaderStorageBufferArrayDynamicIndexing;
+ VkBool32 shaderStorageImageArrayDynamicIndexing;
+ VkBool32 shaderClipDistance;
+ VkBool32 shaderCullDistance;
+ VkBool32 shaderFloat64;
+ VkBool32 shaderInt64;
+ VkBool32 shaderInt16;
+ VkBool32 shaderResourceResidency;
+ VkBool32 shaderResourceMinLod;
+ VkBool32 sparseBinding;
+ VkBool32 sparseResidencyBuffer;
+ VkBool32 sparseResidencyImage2D;
+ VkBool32 sparseResidencyImage3D;
+ VkBool32 sparseResidency2Samples;
+ VkBool32 sparseResidency4Samples;
+ VkBool32 sparseResidency8Samples;
+ VkBool32 sparseResidency16Samples;
+ VkBool32 sparseResidencyAliased;
+ VkBool32 variableMultisampleRate;
+};
+
+struct VkFormatProperties
+{
+ VkFormatFeatureFlags linearTilingFeatures;
+ VkFormatFeatureFlags optimalTilingFeatures;
+ VkFormatFeatureFlags bufferFeatures;
+};
+
+struct VkExtent3D
+{
+ deInt32 width;
+ deInt32 height;
+ deInt32 depth;
+};
+
+struct VkImageFormatProperties
+{
+ VkExtent3D maxExtent;
+ deUint32 maxMipLevels;
+ deUint32 maxArrayLayers;
+ VkSampleCountFlags sampleCounts;
+ VkDeviceSize maxResourceSize;
+};
+
+struct VkPhysicalDeviceLimits
+{
+ deUint32 maxImageDimension1D;
+ deUint32 maxImageDimension2D;
+ deUint32 maxImageDimension3D;
+ deUint32 maxImageDimensionCube;
+ deUint32 maxImageArrayLayers;
+ deUint32 maxTexelBufferElements;
+ deUint32 maxUniformBufferRange;
+ deUint32 maxStorageBufferRange;
+ deUint32 maxPushConstantsSize;
+ deUint32 maxMemoryAllocationCount;
+ deUint32 maxSamplerAllocationCount;
+ VkDeviceSize bufferImageGranularity;
+ VkDeviceSize sparseAddressSpaceSize;
+ deUint32 maxBoundDescriptorSets;
+ deUint32 maxPerStageDescriptorSamplers;
+ deUint32 maxPerStageDescriptorUniformBuffers;
+ deUint32 maxPerStageDescriptorStorageBuffers;
+ deUint32 maxPerStageDescriptorSampledImages;
+ deUint32 maxPerStageDescriptorStorageImages;
+ deUint32 maxPerStageDescriptorInputAttachments;
+ deUint32 maxPerStageResources;
+ deUint32 maxDescriptorSetSamplers;
+ deUint32 maxDescriptorSetUniformBuffers;
+ deUint32 maxDescriptorSetUniformBuffersDynamic;
+ deUint32 maxDescriptorSetStorageBuffers;
+ deUint32 maxDescriptorSetStorageBuffersDynamic;
+ deUint32 maxDescriptorSetSampledImages;
+ deUint32 maxDescriptorSetStorageImages;
+ deUint32 maxDescriptorSetInputAttachments;
+ deUint32 maxVertexInputAttributes;
+ deUint32 maxVertexInputBindings;
+ deUint32 maxVertexInputAttributeOffset;
+ deUint32 maxVertexInputBindingStride;
+ deUint32 maxVertexOutputComponents;
+ deUint32 maxTessellationGenerationLevel;
+ deUint32 maxTessellationPatchSize;
+ deUint32 maxTessellationControlPerVertexInputComponents;
+ deUint32 maxTessellationControlPerVertexOutputComponents;
+ deUint32 maxTessellationControlPerPatchOutputComponents;
+ deUint32 maxTessellationControlTotalOutputComponents;
+ deUint32 maxTessellationEvaluationInputComponents;
+ deUint32 maxTessellationEvaluationOutputComponents;
+ deUint32 maxGeometryShaderInvocations;
+ deUint32 maxGeometryInputComponents;
+ deUint32 maxGeometryOutputComponents;
+ deUint32 maxGeometryOutputVertices;
+ deUint32 maxGeometryTotalOutputComponents;
+ deUint32 maxFragmentInputComponents;
+ deUint32 maxFragmentOutputAttachments;
+ deUint32 maxFragmentDualSrcAttachments;
+ deUint32 maxFragmentCombinedOutputResources;
+ deUint32 maxComputeSharedMemorySize;
+ deUint32 maxComputeWorkGroupCount[3];
+ deUint32 maxComputeWorkGroupInvocations;
+ deUint32 maxComputeWorkGroupSize[3];
+ deUint32 subPixelPrecisionBits;
+ deUint32 subTexelPrecisionBits;
+ deUint32 mipmapPrecisionBits;
+ deUint32 maxDrawIndexedIndexValue;
+ deUint32 maxDrawIndirectCount;
+ float maxSamplerLodBias;
+ float maxSamplerAnisotropy;
+ deUint32 maxViewports;
+ deUint32 maxViewportDimensions[2];
+ float viewportBoundsRange[2];
+ deUint32 viewportSubPixelBits;
+ deUintptr minMemoryMapAlignment;
+ VkDeviceSize minTexelBufferOffsetAlignment;
+ VkDeviceSize minUniformBufferOffsetAlignment;
+ VkDeviceSize minStorageBufferOffsetAlignment;
+ deInt32 minTexelOffset;
+ deUint32 maxTexelOffset;
+ deInt32 minTexelGatherOffset;
+ deUint32 maxTexelGatherOffset;
+ float minInterpolationOffset;
+ float maxInterpolationOffset;
+ deUint32 subPixelInterpolationOffsetBits;
+ deUint32 maxFramebufferWidth;
+ deUint32 maxFramebufferHeight;
+ deUint32 maxFramebufferLayers;
+ VkSampleCountFlags framebufferColorSampleCounts;
+ VkSampleCountFlags framebufferDepthSampleCounts;
+ VkSampleCountFlags framebufferStencilSampleCounts;
+ VkSampleCountFlags framebufferNoAttachmentsSampleCounts;
+ deUint32 maxColorAttachments;
+ VkSampleCountFlags sampledImageColorSampleCounts;
+ VkSampleCountFlags sampledImageIntegerSampleCounts;
+ VkSampleCountFlags sampledImageDepthSampleCounts;
+ VkSampleCountFlags sampledImageStencilSampleCounts;
+ VkSampleCountFlags storageImageSampleCounts;
+ deUint32 maxSampleMaskWords;
+ float timestampPeriod;
+ deUint32 maxClipDistances;
+ deUint32 maxCullDistances;
+ deUint32 maxCombinedClipAndCullDistances;
+ deUint32 discreteQueuePriorities;
+ float pointSizeRange[2];
+ float lineWidthRange[2];
+ float pointSizeGranularity;
+ float lineWidthGranularity;
+ VkBool32 strictLines;
+ VkBool32 standardSampleLocations;
+ VkDeviceSize optimalBufferCopyOffsetAlignment;
+ VkDeviceSize optimalBufferCopyRowPitchAlignment;
+ VkDeviceSize nonCoherentAtomSize;
+};
+
+struct VkPhysicalDeviceSparseProperties
+{
+ VkBool32 residencyStandard2DBlockShape;
+ VkBool32 residencyStandard2DMultisampleBlockShape;
+ VkBool32 residencyStandard3DBlockShape;
+ VkBool32 residencyAlignedMipSize;
+ VkBool32 residencyNonResidentStrict;
+};
+
+struct VkPhysicalDeviceProperties
+{
+ deUint32 apiVersion;
+ deUint32 driverVersion;
+ deUint32 vendorID;
+ deUint32 deviceID;
+ VkPhysicalDeviceType deviceType;
+ char deviceName[VK_MAX_PHYSICAL_DEVICE_NAME_SIZE];
+ deUint8 pipelineCacheUUID[VK_UUID_SIZE];
+ VkPhysicalDeviceLimits limits;
+ VkPhysicalDeviceSparseProperties sparseProperties;
+};
+
+struct VkQueueFamilyProperties
+{
+ VkQueueFlags queueFlags;
+ deUint32 queueCount;
+ deUint32 timestampValidBits;
+ VkExtent3D minImageTransferGranularity;
+};
+
+struct VkMemoryType
+{
+ VkMemoryPropertyFlags propertyFlags;
+ deUint32 heapIndex;
+};
+
+struct VkMemoryHeap
+{
+ VkDeviceSize size;
+ VkMemoryHeapFlags flags;
+};
+
+struct VkPhysicalDeviceMemoryProperties
+{
+ deUint32 memoryTypeCount;
+ VkMemoryType memoryTypes[VK_MAX_MEMORY_TYPES];
+ deUint32 memoryHeapCount;
+ VkMemoryHeap memoryHeaps[VK_MAX_MEMORY_HEAPS];
+};
+
+struct VkDeviceQueueCreateInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkDeviceQueueCreateFlags flags;
+ deUint32 queueFamilyIndex;
+ deUint32 queueCount;
+ const float* pQueuePriorities;
+};
+
+struct VkDeviceCreateInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkDeviceCreateFlags flags;
+ deUint32 queueCreateInfoCount;
+ const VkDeviceQueueCreateInfo* pQueueCreateInfos;
+ deUint32 enabledLayerNameCount;
+ const char* const* ppEnabledLayerNames;
+ deUint32 enabledExtensionNameCount;
+ const char* const* ppEnabledExtensionNames;
+ const VkPhysicalDeviceFeatures* pEnabledFeatures;
+};
+
+struct VkExtensionProperties
+{
+ char extensionName[VK_MAX_EXTENSION_NAME_SIZE];
+ deUint32 specVersion;
+};
+
+struct VkLayerProperties
+{
+ char layerName[VK_MAX_EXTENSION_NAME_SIZE];
+ deUint32 specVersion;
+ deUint32 implementationVersion;
+ char description[VK_MAX_DESCRIPTION_SIZE];
+};
+
+struct VkSubmitInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ deUint32 waitSemaphoreCount;
+ const VkSemaphore* pWaitSemaphores;
+ deUint32 commandBufferCount;
+ const VkCommandBuffer* pCommandBuffers;
+ deUint32 signalSemaphoreCount;
+ const VkSemaphore* pSignalSemaphores;
+};
+
+struct VkMemoryAllocateInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkDeviceSize allocationSize;
+ deUint32 memoryTypeIndex;
+};
+
+struct VkMappedMemoryRange
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkDeviceMemory memory;
+ VkDeviceSize offset;
+ VkDeviceSize size;
+};
+
+struct VkMemoryRequirements
+{
+ VkDeviceSize size;
+ VkDeviceSize alignment;
+ deUint32 memoryTypeBits;
+};
+
+struct VkSparseImageFormatProperties
+{
+ VkImageAspectFlags aspectMask;
+ VkExtent3D imageGranularity;
+ VkSparseImageFormatFlags flags;
+};
+
+struct VkSparseImageMemoryRequirements
+{
+ VkSparseImageFormatProperties formatProperties;
+ deUint32 imageMipTailStartLod;
+ VkDeviceSize imageMipTailSize;
+ VkDeviceSize imageMipTailOffset;
+ VkDeviceSize imageMipTailStride;
+};
+
+struct VkSparseMemoryBind
+{
+ VkDeviceSize resourceOffset;
+ VkDeviceSize size;
+ VkDeviceMemory memory;
+ VkDeviceSize memoryOffset;
+ VkSparseMemoryBindFlags flags;
+};
+
+struct VkSparseBufferMemoryBindInfo
+{
+ VkBuffer buffer;
+ deUint32 bindCount;
+ const VkSparseMemoryBind* pBinds;
+};
+
+struct VkSparseImageOpaqueMemoryBindInfo
+{
+ VkImage image;
+ deUint32 bindCount;
+ const VkSparseMemoryBind* pBinds;
+};
+
+struct VkImageSubresource
+{
+ VkImageAspectFlags aspectMask;
+ deUint32 mipLevel;
+ deUint32 arrayLayer;
+};
+
+struct VkOffset3D
+{
+ deInt32 x;
+ deInt32 y;
+ deInt32 z;
+};
+
+struct VkSparseImageMemoryBind
+{
+ VkImageSubresource subresource;
+ VkOffset3D offset;
+ VkExtent3D extent;
+ VkDeviceMemory memory;
+ VkDeviceSize memoryOffset;
+ VkSparseMemoryBindFlags flags;
+};
+
+struct VkSparseImageMemoryBindInfo
+{
+ VkImage image;
+ deUint32 bindCount;
+ const VkSparseImageMemoryBind* pBinds;
+};
+
+struct VkBindSparseInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ deUint32 waitSemaphoreCount;
+ const VkSemaphore* pWaitSemaphores;
+ deUint32 bufferBindCount;
+ const VkSparseBufferMemoryBindInfo* pBufferBinds;
+ deUint32 imageOpaqueBindCount;
+ const VkSparseImageOpaqueMemoryBindInfo* pImageOpaqueBinds;
+ deUint32 imageBindCount;
+ const VkSparseImageMemoryBindInfo* pImageBinds;
+ deUint32 signalSemaphoreCount;
+ const VkSemaphore* pSignalSemaphores;
+};
+
+struct VkFenceCreateInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkFenceCreateFlags flags;
+};
+
+struct VkSemaphoreCreateInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkSemaphoreCreateFlags flags;
+};
+
+struct VkEventCreateInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkEventCreateFlags flags;
+};
+
+struct VkQueryPoolCreateInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkQueryPoolCreateFlags flags;
+ VkQueryType queryType;
+ deUint32 entryCount;
+ VkQueryPipelineStatisticFlags pipelineStatistics;
+};
+
+struct VkBufferCreateInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkBufferCreateFlags flags;
+ VkDeviceSize size;
+ VkBufferUsageFlags usage;
+ VkSharingMode sharingMode;
+ deUint32 queueFamilyIndexCount;
+ const deUint32* pQueueFamilyIndices;
+};
+
+struct VkBufferViewCreateInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkBufferViewCreateFlags flags;
+ VkBuffer buffer;
+ VkFormat format;
+ VkDeviceSize offset;
+ VkDeviceSize range;
+};
+
+struct VkImageCreateInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkImageCreateFlags flags;
+ VkImageType imageType;
+ VkFormat format;
+ VkExtent3D extent;
+ deUint32 mipLevels;
+ deUint32 arrayLayers;
+ VkSampleCountFlagBits samples;
+ VkImageTiling tiling;
+ VkImageUsageFlags usage;
+ VkSharingMode sharingMode;
+ deUint32 queueFamilyIndexCount;
+ const deUint32* pQueueFamilyIndices;
+ VkImageLayout initialLayout;
+};
+
+struct VkSubresourceLayout
+{
+ VkDeviceSize offset;
+ VkDeviceSize size;
+ VkDeviceSize rowPitch;
+ VkDeviceSize depthPitch;
+};
+
+struct VkComponentMapping
+{
+ VkComponentSwizzle r;
+ VkComponentSwizzle g;
+ VkComponentSwizzle b;
+ VkComponentSwizzle a;
+};
+
+struct VkImageSubresourceRange
+{
+ VkImageAspectFlags aspectMask;
+ deUint32 baseMipLevel;
+ deUint32 levelCount;
+ deUint32 baseArrayLayer;
+ deUint32 layerCount;
+};
+
+struct VkImageViewCreateInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkImageViewCreateFlags flags;
+ VkImage image;
+ VkImageViewType viewType;
+ VkFormat format;
+ VkComponentMapping components;
+ VkImageSubresourceRange subresourceRange;
+};
+
+struct VkShaderModuleCreateInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkShaderModuleCreateFlags flags;
+ deUintptr codeSize;
+ const deUint32* pCode;
+};
+
+struct VkPipelineCacheCreateInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineCacheCreateFlags flags;
+ deUintptr initialDataSize;
+ const void* pInitialData;
+};
+
+struct VkSpecializationMapEntry
+{
+ deUint32 constantID;
+ deUint32 offset;
+ deUintptr size;
+};
+
+struct VkSpecializationInfo
+{
+ deUint32 mapEntryCount;
+ const VkSpecializationMapEntry* pMapEntries;
+ deUintptr dataSize;
+ const void* pData;
+};
+
+struct VkPipelineShaderStageCreateInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineShaderStageCreateFlags flags;
+ VkShaderStageFlagBits stage;
+ VkShaderModule module;
+ const char* pName;
+ const VkSpecializationInfo* pSpecializationInfo;
+};
+
+struct VkVertexInputBindingDescription
+{
+ deUint32 binding;
+ deUint32 stride;
+ VkVertexInputRate inputRate;
+};
+
+struct VkVertexInputAttributeDescription
+{
+ deUint32 location;
+ deUint32 binding;
+ VkFormat format;
+ deUint32 offset;
+};
+
+struct VkPipelineVertexInputStateCreateInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineVertexInputStateCreateFlags flags;
+ deUint32 vertexBindingDescriptionCount;
+ const VkVertexInputBindingDescription* pVertexBindingDescriptions;
+ deUint32 vertexAttributeDescriptionCount;
+ const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
+};
+
+struct VkPipelineInputAssemblyStateCreateInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineInputAssemblyStateCreateFlags flags;
+ VkPrimitiveTopology topology;
+ VkBool32 primitiveRestartEnable;
+};
+
+struct VkPipelineTessellationStateCreateInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineTesselationStateCreateFlags flags;
+ deUint32 patchControlPoints;
+};
+
+struct VkViewport
+{
+ float x;
+ float y;
+ float width;
+ float height;
+ float minDepth;
+ float maxDepth;
+};
+
+struct VkOffset2D
+{
+ deInt32 x;
+ deInt32 y;
+};
+
+struct VkExtent2D
+{
+ deInt32 width;
+ deInt32 height;
+};
+
+struct VkRect2D
+{
+ VkOffset2D offset;
+ VkExtent2D extent;
+};
+
+struct VkPipelineViewportStateCreateInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineViewportStateCreateFlags flags;
+ deUint32 viewportCount;
+ const VkViewport* pViewports;
+ deUint32 scissorCount;
+ const VkRect2D* pScissors;
+};
+
+struct VkPipelineRasterizationStateCreateInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineRasterizationStateCreateFlags flags;
+ VkBool32 depthClampEnable;
+ VkBool32 rasterizerDiscardEnable;
+ VkPolygonMode polygonMode;
+ VkCullModeFlags cullMode;
+ VkFrontFace frontFace;
+ VkBool32 depthBiasEnable;
+ float depthBiasConstantFactor;
+ float depthBiasClamp;
+ float depthBiasSlopeFactor;
+ float lineWidth;
+};
+
+struct VkPipelineMultisampleStateCreateInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineMultisampleStateCreateFlags flags;
+ VkSampleCountFlagBits rasterizationSamples;
+ VkBool32 sampleShadingEnable;
+ float minSampleShading;
+ const VkSampleMask* pSampleMask;
+ VkBool32 alphaToCoverageEnable;
+ VkBool32 alphaToOneEnable;
+};
+
+struct VkStencilOpState
+{
+ VkStencilOp failOp;
+ VkStencilOp passOp;
+ VkStencilOp depthFailOp;
+ VkCompareOp compareOp;
+ deUint32 compareMask;
+ deUint32 writeMask;
+ deUint32 reference;
+};
+
+struct VkPipelineDepthStencilStateCreateInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineDepthStencilStateCreateFlags flags;
+ VkBool32 depthTestEnable;
+ VkBool32 depthWriteEnable;
+ VkCompareOp depthCompareOp;
+ VkBool32 depthBoundsTestEnable;
+ VkBool32 stencilTestEnable;
+ VkStencilOpState front;
+ VkStencilOpState back;
+ float minDepthBounds;
+ float maxDepthBounds;
+};
+
+struct VkPipelineColorBlendAttachmentState
+{
+ VkBool32 blendEnable;
+ VkBlendFactor srcColorBlendFactor;
+ VkBlendFactor dstColorBlendFactor;
+ VkBlendOp colorBlendOp;
+ VkBlendFactor srcAlphaBlendFactor;
+ VkBlendFactor dstAlphaBlendFactor;
+ VkBlendOp alphaBlendOp;
+ VkColorComponentFlags colorWriteMask;
+};
+
+struct VkPipelineColorBlendStateCreateInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineColorBlendStateCreateFlags flags;
+ VkBool32 logicOpEnable;
+ VkLogicOp logicOp;
+ deUint32 attachmentCount;
+ const VkPipelineColorBlendAttachmentState* pAttachments;
+ float blendConstants[4];
+};
+
+struct VkPipelineDynamicStateCreateInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineDynamicStateCreateFlags flags;
+ deUint32 dynamicStateCount;
+ const VkDynamicState* pDynamicStates;
+};
+
+struct VkGraphicsPipelineCreateInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineCreateFlags flags;
+ deUint32 stageCount;
+ const VkPipelineShaderStageCreateInfo* pStages;
+ const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
+ const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
+ const VkPipelineTessellationStateCreateInfo* pTessellationState;
+ const VkPipelineViewportStateCreateInfo* pViewportState;
+ const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
+ const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
+ const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
+ const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
+ const VkPipelineDynamicStateCreateInfo* pDynamicState;
+ VkPipelineLayout layout;
+ VkRenderPass renderPass;
+ deUint32 subpass;
+ VkPipeline basePipelineHandle;
+ deInt32 basePipelineIndex;
+};
+
+struct VkComputePipelineCreateInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineCreateFlags flags;
+ VkPipelineShaderStageCreateInfo stage;
+ VkPipelineLayout layout;
+ VkPipeline basePipelineHandle;
+ deInt32 basePipelineIndex;
+};
+
+struct VkPushConstantRange
+{
+ VkShaderStageFlags stageFlags;
+ deUint32 offset;
+ deUint32 size;
+};
+
+struct VkPipelineLayoutCreateInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineLayoutCreateFlags flags;
+ deUint32 setLayoutCount;
+ const VkDescriptorSetLayout* pSetLayouts;
+ deUint32 pushConstantRangeCount;
+ const VkPushConstantRange* pPushConstantRanges;
+};
+
+struct VkSamplerCreateInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkSamplerCreateFlags flags;
+ VkFilter magFilter;
+ VkFilter minFilter;
+ VkSamplerMipmapMode mipmapMode;
+ VkSamplerAddressMode addressModeU;
+ VkSamplerAddressMode addressModeV;
+ VkSamplerAddressMode addressModeW;
+ float mipLodBias;
+ float maxAnisotropy;
+ VkBool32 compareEnable;
+ VkCompareOp compareOp;
+ float minLod;
+ float maxLod;
+ VkBorderColor borderColor;
+ VkBool32 unnormalizedCoordinates;
+};
+
+struct VkDescriptorSetLayoutBinding
+{
+ deUint32 binding;
+ VkDescriptorType descriptorType;
+ deUint32 descriptorCount;
+ VkShaderStageFlags stageFlags;
+ const VkSampler* pImmutableSamplers;
+};
+
+struct VkDescriptorSetLayoutCreateInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkDescriptorSetLayoutCreateFlags flags;
+ deUint32 bindingCount;
+ const VkDescriptorSetLayoutBinding* pBinding;
+};
+
+struct VkDescriptorPoolSize
+{
+ VkDescriptorType type;
+ deUint32 descriptorCount;
+};
+
+struct VkDescriptorPoolCreateInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkDescriptorPoolCreateFlags flags;
+ deUint32 maxSets;
+ deUint32 poolSizeCount;
+ const VkDescriptorPoolSize* pPoolSizes;
+};
+
+struct VkDescriptorSetAllocateInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkDescriptorPool descriptorPool;
+ deUint32 setLayoutCount;
+ const VkDescriptorSetLayout* pSetLayouts;
+};
+
+struct VkDescriptorImageInfo
+{
+ VkSampler sampler;
+ VkImageView imageView;
+ VkImageLayout imageLayout;
+};
+
+struct VkDescriptorBufferInfo
+{
+ VkBuffer buffer;
+ VkDeviceSize offset;
+ VkDeviceSize range;
+};
+
+struct VkWriteDescriptorSet
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkDescriptorSet dstSet;
+ deUint32 dstBinding;
+ deUint32 dstArrayElement;
+ deUint32 descriptorCount;
+ VkDescriptorType descriptorType;
+ const VkDescriptorImageInfo* pImageInfo;
+ const VkDescriptorBufferInfo* pBufferInfo;
+ const VkBufferView* pTexelBufferView;
+};
+
+struct VkCopyDescriptorSet
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkDescriptorSet srcSet;
+ deUint32 srcBinding;
+ deUint32 srcArrayElement;
+ VkDescriptorSet dstSet;
+ deUint32 dstBinding;
+ deUint32 dstArrayElement;
+ deUint32 descriptorCount;
+};
+
+struct VkFramebufferCreateInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkFramebufferCreateFlags flags;
+ VkRenderPass renderPass;
+ deUint32 attachmentCount;
+ const VkImageView* pAttachments;
+ deUint32 width;
+ deUint32 height;
+ deUint32 layers;
+};
+
+struct VkAttachmentDescription
+{
+ VkAttachmentDescriptionFlags flags;
+ VkFormat format;
+ VkSampleCountFlagBits samples;
+ VkAttachmentLoadOp loadOp;
+ VkAttachmentStoreOp storeOp;
+ VkAttachmentLoadOp stencilLoadOp;
+ VkAttachmentStoreOp stencilStoreOp;
+ VkImageLayout initialLayout;
+ VkImageLayout finalLayout;
+};
+
+struct VkAttachmentReference
+{
+ deUint32 attachment;
+ VkImageLayout layout;
+};
+
+struct VkSubpassDescription
+{
+ VkSubpassDescriptionFlags flags;
+ VkPipelineBindPoint pipelineBindPoint;
+ deUint32 inputAttachmentCount;
+ const VkAttachmentReference* pInputAttachments;
+ deUint32 colorAttachmentCount;
+ const VkAttachmentReference* pColorAttachments;
+ const VkAttachmentReference* pResolveAttachments;
+ const VkAttachmentReference* pDepthStencilAttachment;
+ deUint32 preserveAttachmentCount;
+ const VkAttachmentReference* pPreserveAttachments;
+};
+
+struct VkSubpassDependency
+{
+ deUint32 srcSubpass;
+ deUint32 dstSubpass;
+ VkPipelineStageFlags srcStageMask;
+ VkPipelineStageFlags dstStageMask;
+ VkAccessFlags srcAccessMask;
+ VkAccessFlags dstAccessMask;
+ VkDependencyFlags dependencyFlags;
+};
+
+struct VkRenderPassCreateInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkRenderPassCreateFlags flags;
+ deUint32 attachmentCount;
+ const VkAttachmentDescription* pAttachments;
+ deUint32 subpassCount;
+ const VkSubpassDescription* pSubpasses;
+ deUint32 dependencyCount;
+ const VkSubpassDependency* pDependencies;
+};
+
+struct VkCommandPoolCreateInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkCommandPoolCreateFlags flags;
+ deUint32 queueFamilyIndex;
+};
+
+struct VkCommandBufferAllocateInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkCommandPool commandPool;
+ VkCommandBufferLevel level;
+ deUint32 bufferCount;
+};
+
+struct VkCommandBufferBeginInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkCommandBufferUsageFlags flags;
+ VkRenderPass renderPass;
+ deUint32 subpass;
+ VkFramebuffer framebuffer;
+ VkBool32 occlusionQueryEnable;
+ VkQueryControlFlags queryFlags;
+ VkQueryPipelineStatisticFlags pipelineStatistics;
+};
+
+struct VkBufferCopy
+{
+ VkDeviceSize srcOffset;
+ VkDeviceSize dstOffset;
+ VkDeviceSize size;
+};
+
+struct VkImageSubresourceLayers
+{
+ VkImageAspectFlags aspectMask;
+ deUint32 mipLevel;
+ deUint32 baseArrayLayer;
+ deUint32 layerCount;
+};
+
+struct VkImageCopy
+{
+ VkImageSubresourceLayers srcSubresource;
+ VkOffset3D srcOffset;
+ VkImageSubresourceLayers dstSubresource;
+ VkOffset3D dstOffset;
+ VkExtent3D extent;
+};
+
+struct VkImageBlit
+{
+ VkImageSubresourceLayers srcSubresource;
+ VkOffset3D srcOffset;
+ VkExtent3D srcExtent;
+ VkImageSubresourceLayers dstSubresource;
+ VkOffset3D dstOffset;
+ VkExtent3D dstExtent;
+};
+
+struct VkBufferImageCopy
+{
+ VkDeviceSize bufferOffset;
+ deUint32 bufferRowLength;
+ deUint32 bufferImageHeight;
+ VkImageSubresourceLayers imageSubresource;
+ VkOffset3D imageOffset;
+ VkExtent3D imageExtent;
+};
+
+union VkClearColorValue
+{
+ float float32[4];
+ deInt32 int32[4];
+ deUint32 uint32[4];
+};
+
+struct VkClearDepthStencilValue
+{
+ float depth;
+ deUint32 stencil;
+};
+
+union VkClearValue
+{
+ VkClearColorValue color;
+ VkClearDepthStencilValue depthStencil;
+};
+
+struct VkClearAttachment
+{
+ VkImageAspectFlags aspectMask;
+ deUint32 colorAttachment;
+ VkClearValue clearValue;
+};
+
+struct VkClearRect
+{
+ VkRect2D rect;
+ deUint32 baseArrayLayer;
+ deUint32 layerCount;
+};
+
+struct VkImageResolve
+{
+ VkImageSubresourceLayers srcSubresource;
+ VkOffset3D srcOffset;
+ VkImageSubresourceLayers dstSubresource;
+ VkOffset3D dstOffset;
+ VkExtent3D extent;
+};
+
+struct VkRenderPassBeginInfo
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkRenderPass renderPass;
+ VkFramebuffer framebuffer;
+ VkRect2D renderArea;
+ deUint32 clearValueCount;
+ const VkClearValue* pClearValues;
+};
+
+struct VkBufferMemoryBarrier
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkAccessFlags srcAccessMask;
+ VkAccessFlags dstAccessMask;
+ deUint32 srcQueueFamilyIndex;
+ deUint32 dstQueueFamilyIndex;
+ VkBuffer buffer;
+ VkDeviceSize offset;
+ VkDeviceSize size;
+};
+
+struct VkDispatchIndirectCommand
+{
+ deUint32 x;
+ deUint32 y;
+ deUint32 z;
+};
+
+struct VkDrawIndexedIndirectCommand
+{
+ deUint32 indexCount;
+ deUint32 instanceCount;
+ deUint32 firstIndex;
+ deInt32 vertexOffset;
+ deUint32 firstInstance;
+};
+
+struct VkDrawIndirectCommand
+{
+ deUint32 vertexCount;
+ deUint32 instanceCount;
+ deUint32 firstVertex;
+ deUint32 firstInstance;
+};
+
+struct VkImageMemoryBarrier
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkAccessFlags srcAccessMask;
+ VkAccessFlags dstAccessMask;
+ VkImageLayout oldLayout;
+ VkImageLayout newLayout;
+ deUint32 srcQueueFamilyIndex;
+ deUint32 dstQueueFamilyIndex;
+ VkImage image;
+ VkImageSubresourceRange subresourceRange;
+};
+
+struct VkMemoryBarrier
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkAccessFlags srcAccessMask;
+ VkAccessFlags dstAccessMask;
+};
+
+struct VkSurfaceCapabilitiesKHR
+{
+ deUint32 minImageCount;
+ deUint32 maxImageCount;
+ VkExtent2D currentExtent;
+ VkExtent2D minImageExtent;
+ VkExtent2D maxImageExtent;
+ deUint32 maxImageArrayLayers;
+ VkSurfaceTransformFlagsKHR supportedTransforms;
+ VkSurfaceTransformFlagBitsKHR currentTransform;
+ VkCompositeAlphaFlagsKHR supportedCompositeAlpha;
+ VkImageUsageFlags supportedUsageFlags;
+};
+
+struct VkSurfaceFormatKHR
+{
+ VkFormat format;
+ VkColorSpaceKHR colorSpace;
+};
+
+struct VkSwapchainCreateInfoKHR
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkSwapchainCreateFlagsKHR flags;
+ VkSurfaceKHR surface;
+ deUint32 minImageCount;
+ VkFormat imageFormat;
+ VkColorSpaceKHR imageColorSpace;
+ VkExtent2D imageExtent;
+ deUint32 imageArrayLayers;
+ VkImageUsageFlags imageUsage;
+ VkSharingMode imageSharingMode;
+ deUint32 queueFamilyIndexCount;
+ const deUint32* pQueueFamilyIndices;
+ VkSurfaceTransformFlagBitsKHR preTransform;
+ VkCompositeAlphaFlagBitsKHR compositeAlpha;
+ VkPresentModeKHR presentMode;
+ VkBool32 clipped;
+ VkSwapchainKHR oldSwapchain;
+};
+
+struct VkPresentInfoKHR
+{
+ VkStructureType sType;
+ const void* pNext;
+ deUint32 waitSemaphoreCount;
+ const VkSemaphore* pWaitSemaphores;
+ deUint32 swapchainCount;
+ const VkSwapchainKHR* pSwapchains;
+ const deUint32* pImageIndices;
+ VkResult* pResults;
+};
+
+struct VkDisplayPropertiesKHR
+{
+ VkDisplayKHR display;
+ const char* displayName;
+ VkExtent2D physicalDimensions;
+ VkExtent2D physicalResolution;
+ VkSurfaceTransformFlagsKHR supportedTransforms;
+ VkBool32 planeReorderPossible;
+ VkBool32 persistentContent;
+};
+
+struct VkDisplayModeParametersKHR
+{
+ VkExtent2D visibleRegion;
+ deUint32 refreshRate;
+};
+
+struct VkDisplayModePropertiesKHR
+{
+ VkDisplayModeKHR displayMode;
+ VkDisplayModeParametersKHR parameters;
+};
+
+struct VkDisplayModeCreateInfoKHR
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkDisplayModeCreateFlagsKHR flags;
+ VkDisplayModeParametersKHR parameters;
+};
+
+struct VkDisplayPlaneCapabilitiesKHR
+{
+ VkDisplayPlaneAlphaFlagsKHR supportedAlpha;
+ VkOffset2D minSrcPosition;
+ VkOffset2D maxSrcPosition;
+ VkExtent2D minSrcExtent;
+ VkExtent2D maxSrcExtent;
+ VkOffset2D minDstPosition;
+ VkOffset2D maxDstPosition;
+ VkExtent2D minDstExtent;
+ VkExtent2D maxDstExtent;
+};
+
+struct VkDisplayPlanePropertiesKHR
+{
+ VkDisplayKHR currentDisplay;
+ deUint32 currentStackIndex;
+};
+
+struct VkDisplaySurfaceCreateInfoKHR
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkDisplaySurfaceCreateFlagsKHR flags;
+ VkDisplayModeKHR displayMode;
+ deUint32 planeIndex;
+ deUint32 planeStackIndex;
+ VkSurfaceTransformFlagBitsKHR transform;
+ float globalAlpha;
+ VkDisplayPlaneAlphaFlagBitsKHR alphaMode;
+ VkExtent2D imageExtent;
+};
+
+struct VkDisplayPresentInfoKHR
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkRect2D srcRect;
+ VkRect2D dstRect;
+ VkBool32 persistent;
+};
+
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Utilities for creating commonly used composite types.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkTypeUtil.hpp"
+
+DE_EMPTY_CPP_FILE
--- /dev/null
+#ifndef _VKTYPEUTIL_HPP
+#define _VKTYPEUTIL_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Utilities for creating commonly used composite types.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkDefs.hpp"
+#include "tcuVector.hpp"
+
+namespace vk
+{
+
+#include "vkTypeUtil.inl"
+
+inline VkClearValue makeClearValueColorF32 (float r, float g, float b, float a)
+{
+ VkClearValue v;
+ v.color.float32[0] = r;
+ v.color.float32[1] = g;
+ v.color.float32[2] = b;
+ v.color.float32[3] = a;
+ return v;
+}
+
+inline VkClearValue makeClearValueColor (const tcu::Vec4& color)
+{
+ VkClearValue v;
+ v.color.float32[0] = color[0];
+ v.color.float32[1] = color[1];
+ v.color.float32[2] = color[2];
+ v.color.float32[3] = color[3];
+ return v;
+}
+
+inline VkClearValue makeClearValueDepthStencil (float depth, deUint32 stencil)
+{
+ VkClearValue v;
+ v.depthStencil.depth = depth;
+ v.depthStencil.stencil = stencil;
+ return v;
+}
+
+inline VkClearValue makeClearValue (VkClearColorValue color)
+{
+ VkClearValue v;
+ v.color = color;
+ return v;
+}
+
+inline VkComponentMapping makeComponentMappingRGBA (void)
+{
+ return makeComponentMapping(VK_COMPONENT_SWIZZLE_R,
+ VK_COMPONENT_SWIZZLE_G,
+ VK_COMPONENT_SWIZZLE_B,
+ VK_COMPONENT_SWIZZLE_A);
+}
+
+} // vk
+
+#endif // _VKTYPEUTIL_HPP
--- /dev/null
+/* WARNING: This is auto-generated file. Do not modify, since changes will
+ * be lost! Modify the generating script instead.
+ */
+
+inline VkAllocationCallbacks makeAllocationCallbacks (void* pUserData, PFN_vkAllocationFunction pfnAllocation, PFN_vkReallocationFunction pfnReallocation, PFN_vkFreeFunction pfnFree, PFN_vkInternalAllocationNotification pfnInternalAllocation, PFN_vkInternalFreeNotification pfnInternalFree)
+{
+ VkAllocationCallbacks res;
+ res.pUserData = pUserData;
+ res.pfnAllocation = pfnAllocation;
+ res.pfnReallocation = pfnReallocation;
+ res.pfnFree = pfnFree;
+ res.pfnInternalAllocation = pfnInternalAllocation;
+ res.pfnInternalFree = pfnInternalFree;
+ return res;
+}
+
+inline VkExtent3D makeExtent3D (deInt32 width, deInt32 height, deInt32 depth)
+{
+ VkExtent3D res;
+ res.width = width;
+ res.height = height;
+ res.depth = depth;
+ return res;
+}
+
+inline VkMemoryRequirements makeMemoryRequirements (VkDeviceSize size, VkDeviceSize alignment, deUint32 memoryTypeBits)
+{
+ VkMemoryRequirements res;
+ res.size = size;
+ res.alignment = alignment;
+ res.memoryTypeBits = memoryTypeBits;
+ return res;
+}
+
+inline VkSparseMemoryBind makeSparseMemoryBind (VkDeviceSize resourceOffset, VkDeviceSize size, VkDeviceMemory memory, VkDeviceSize memoryOffset, VkSparseMemoryBindFlags flags)
+{
+ VkSparseMemoryBind res;
+ res.resourceOffset = resourceOffset;
+ res.size = size;
+ res.memory = memory;
+ res.memoryOffset = memoryOffset;
+ res.flags = flags;
+ return res;
+}
+
+inline VkSparseBufferMemoryBindInfo makeSparseBufferMemoryBindInfo (VkBuffer buffer, deUint32 bindCount, const VkSparseMemoryBind* pBinds)
+{
+ VkSparseBufferMemoryBindInfo res;
+ res.buffer = buffer;
+ res.bindCount = bindCount;
+ res.pBinds = pBinds;
+ return res;
+}
+
+inline VkSparseImageOpaqueMemoryBindInfo makeSparseImageOpaqueMemoryBindInfo (VkImage image, deUint32 bindCount, const VkSparseMemoryBind* pBinds)
+{
+ VkSparseImageOpaqueMemoryBindInfo res;
+ res.image = image;
+ res.bindCount = bindCount;
+ res.pBinds = pBinds;
+ return res;
+}
+
+inline VkImageSubresource makeImageSubresource (VkImageAspectFlags aspectMask, deUint32 mipLevel, deUint32 arrayLayer)
+{
+ VkImageSubresource res;
+ res.aspectMask = aspectMask;
+ res.mipLevel = mipLevel;
+ res.arrayLayer = arrayLayer;
+ return res;
+}
+
+inline VkOffset3D makeOffset3D (deInt32 x, deInt32 y, deInt32 z)
+{
+ VkOffset3D res;
+ res.x = x;
+ res.y = y;
+ res.z = z;
+ return res;
+}
+
+inline VkSparseImageMemoryBindInfo makeSparseImageMemoryBindInfo (VkImage image, deUint32 bindCount, const VkSparseImageMemoryBind* pBinds)
+{
+ VkSparseImageMemoryBindInfo res;
+ res.image = image;
+ res.bindCount = bindCount;
+ res.pBinds = pBinds;
+ return res;
+}
+
+inline VkSubresourceLayout makeSubresourceLayout (VkDeviceSize offset, VkDeviceSize size, VkDeviceSize rowPitch, VkDeviceSize depthPitch)
+{
+ VkSubresourceLayout res;
+ res.offset = offset;
+ res.size = size;
+ res.rowPitch = rowPitch;
+ res.depthPitch = depthPitch;
+ return res;
+}
+
+inline VkComponentMapping makeComponentMapping (VkComponentSwizzle r, VkComponentSwizzle g, VkComponentSwizzle b, VkComponentSwizzle a)
+{
+ VkComponentMapping res;
+ res.r = r;
+ res.g = g;
+ res.b = b;
+ res.a = a;
+ return res;
+}
+
+inline VkImageSubresourceRange makeImageSubresourceRange (VkImageAspectFlags aspectMask, deUint32 baseMipLevel, deUint32 levelCount, deUint32 baseArrayLayer, deUint32 layerCount)
+{
+ VkImageSubresourceRange res;
+ res.aspectMask = aspectMask;
+ res.baseMipLevel = baseMipLevel;
+ res.levelCount = levelCount;
+ res.baseArrayLayer = baseArrayLayer;
+ res.layerCount = layerCount;
+ return res;
+}
+
+inline VkSpecializationMapEntry makeSpecializationMapEntry (deUint32 constantID, deUint32 offset, deUintptr size)
+{
+ VkSpecializationMapEntry res;
+ res.constantID = constantID;
+ res.offset = offset;
+ res.size = size;
+ return res;
+}
+
+inline VkSpecializationInfo makeSpecializationInfo (deUint32 mapEntryCount, const VkSpecializationMapEntry* pMapEntries, deUintptr dataSize, const void* pData)
+{
+ VkSpecializationInfo res;
+ res.mapEntryCount = mapEntryCount;
+ res.pMapEntries = pMapEntries;
+ res.dataSize = dataSize;
+ res.pData = pData;
+ return res;
+}
+
+inline VkVertexInputBindingDescription makeVertexInputBindingDescription (deUint32 binding, deUint32 stride, VkVertexInputRate inputRate)
+{
+ VkVertexInputBindingDescription res;
+ res.binding = binding;
+ res.stride = stride;
+ res.inputRate = inputRate;
+ return res;
+}
+
+inline VkVertexInputAttributeDescription makeVertexInputAttributeDescription (deUint32 location, deUint32 binding, VkFormat format, deUint32 offset)
+{
+ VkVertexInputAttributeDescription res;
+ res.location = location;
+ res.binding = binding;
+ res.format = format;
+ res.offset = offset;
+ return res;
+}
+
+inline VkViewport makeViewport (float x, float y, float width, float height, float minDepth, float maxDepth)
+{
+ VkViewport res;
+ res.x = x;
+ res.y = y;
+ res.width = width;
+ res.height = height;
+ res.minDepth = minDepth;
+ res.maxDepth = maxDepth;
+ return res;
+}
+
+inline VkOffset2D makeOffset2D (deInt32 x, deInt32 y)
+{
+ VkOffset2D res;
+ res.x = x;
+ res.y = y;
+ return res;
+}
+
+inline VkExtent2D makeExtent2D (deInt32 width, deInt32 height)
+{
+ VkExtent2D res;
+ res.width = width;
+ res.height = height;
+ return res;
+}
+
+inline VkStencilOpState makeStencilOpState (VkStencilOp failOp, VkStencilOp passOp, VkStencilOp depthFailOp, VkCompareOp compareOp, deUint32 compareMask, deUint32 writeMask, deUint32 reference)
+{
+ VkStencilOpState res;
+ res.failOp = failOp;
+ res.passOp = passOp;
+ res.depthFailOp = depthFailOp;
+ res.compareOp = compareOp;
+ res.compareMask = compareMask;
+ res.writeMask = writeMask;
+ res.reference = reference;
+ return res;
+}
+
+inline VkPipelineColorBlendAttachmentState makePipelineColorBlendAttachmentState (VkBool32 blendEnable, VkBlendFactor srcColorBlendFactor, VkBlendFactor dstColorBlendFactor, VkBlendOp colorBlendOp, VkBlendFactor srcAlphaBlendFactor, VkBlendFactor dstAlphaBlendFactor, VkBlendOp alphaBlendOp, VkColorComponentFlags colorWriteMask)
+{
+ VkPipelineColorBlendAttachmentState res;
+ res.blendEnable = blendEnable;
+ res.srcColorBlendFactor = srcColorBlendFactor;
+ res.dstColorBlendFactor = dstColorBlendFactor;
+ res.colorBlendOp = colorBlendOp;
+ res.srcAlphaBlendFactor = srcAlphaBlendFactor;
+ res.dstAlphaBlendFactor = dstAlphaBlendFactor;
+ res.alphaBlendOp = alphaBlendOp;
+ res.colorWriteMask = colorWriteMask;
+ return res;
+}
+
+inline VkPushConstantRange makePushConstantRange (VkShaderStageFlags stageFlags, deUint32 offset, deUint32 size)
+{
+ VkPushConstantRange res;
+ res.stageFlags = stageFlags;
+ res.offset = offset;
+ res.size = size;
+ return res;
+}
+
+inline VkDescriptorSetLayoutBinding makeDescriptorSetLayoutBinding (deUint32 binding, VkDescriptorType descriptorType, deUint32 descriptorCount, VkShaderStageFlags stageFlags, const VkSampler* pImmutableSamplers)
+{
+ VkDescriptorSetLayoutBinding res;
+ res.binding = binding;
+ res.descriptorType = descriptorType;
+ res.descriptorCount = descriptorCount;
+ res.stageFlags = stageFlags;
+ res.pImmutableSamplers = pImmutableSamplers;
+ return res;
+}
+
+inline VkDescriptorPoolSize makeDescriptorPoolSize (VkDescriptorType type, deUint32 descriptorCount)
+{
+ VkDescriptorPoolSize res;
+ res.type = type;
+ res.descriptorCount = descriptorCount;
+ return res;
+}
+
+inline VkDescriptorImageInfo makeDescriptorImageInfo (VkSampler sampler, VkImageView imageView, VkImageLayout imageLayout)
+{
+ VkDescriptorImageInfo res;
+ res.sampler = sampler;
+ res.imageView = imageView;
+ res.imageLayout = imageLayout;
+ return res;
+}
+
+inline VkDescriptorBufferInfo makeDescriptorBufferInfo (VkBuffer buffer, VkDeviceSize offset, VkDeviceSize range)
+{
+ VkDescriptorBufferInfo res;
+ res.buffer = buffer;
+ res.offset = offset;
+ res.range = range;
+ return res;
+}
+
+inline VkAttachmentDescription makeAttachmentDescription (VkAttachmentDescriptionFlags flags, VkFormat format, VkSampleCountFlagBits samples, VkAttachmentLoadOp loadOp, VkAttachmentStoreOp storeOp, VkAttachmentLoadOp stencilLoadOp, VkAttachmentStoreOp stencilStoreOp, VkImageLayout initialLayout, VkImageLayout finalLayout)
+{
+ VkAttachmentDescription res;
+ res.flags = flags;
+ res.format = format;
+ res.samples = samples;
+ res.loadOp = loadOp;
+ res.storeOp = storeOp;
+ res.stencilLoadOp = stencilLoadOp;
+ res.stencilStoreOp = stencilStoreOp;
+ res.initialLayout = initialLayout;
+ res.finalLayout = finalLayout;
+ return res;
+}
+
+inline VkAttachmentReference makeAttachmentReference (deUint32 attachment, VkImageLayout layout)
+{
+ VkAttachmentReference res;
+ res.attachment = attachment;
+ res.layout = layout;
+ return res;
+}
+
+inline VkSubpassDescription makeSubpassDescription (VkSubpassDescriptionFlags flags, VkPipelineBindPoint pipelineBindPoint, deUint32 inputAttachmentCount, const VkAttachmentReference* pInputAttachments, deUint32 colorAttachmentCount, const VkAttachmentReference* pColorAttachments, const VkAttachmentReference* pResolveAttachments, const VkAttachmentReference* pDepthStencilAttachment, deUint32 preserveAttachmentCount, const VkAttachmentReference* pPreserveAttachments)
+{
+ VkSubpassDescription res;
+ res.flags = flags;
+ res.pipelineBindPoint = pipelineBindPoint;
+ res.inputAttachmentCount = inputAttachmentCount;
+ res.pInputAttachments = pInputAttachments;
+ res.colorAttachmentCount = colorAttachmentCount;
+ res.pColorAttachments = pColorAttachments;
+ res.pResolveAttachments = pResolveAttachments;
+ res.pDepthStencilAttachment = pDepthStencilAttachment;
+ res.preserveAttachmentCount = preserveAttachmentCount;
+ res.pPreserveAttachments = pPreserveAttachments;
+ return res;
+}
+
+inline VkSubpassDependency makeSubpassDependency (deUint32 srcSubpass, deUint32 dstSubpass, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkDependencyFlags dependencyFlags)
+{
+ VkSubpassDependency res;
+ res.srcSubpass = srcSubpass;
+ res.dstSubpass = dstSubpass;
+ res.srcStageMask = srcStageMask;
+ res.dstStageMask = dstStageMask;
+ res.srcAccessMask = srcAccessMask;
+ res.dstAccessMask = dstAccessMask;
+ res.dependencyFlags = dependencyFlags;
+ return res;
+}
+
+inline VkBufferCopy makeBufferCopy (VkDeviceSize srcOffset, VkDeviceSize dstOffset, VkDeviceSize size)
+{
+ VkBufferCopy res;
+ res.srcOffset = srcOffset;
+ res.dstOffset = dstOffset;
+ res.size = size;
+ return res;
+}
+
+inline VkImageSubresourceLayers makeImageSubresourceLayers (VkImageAspectFlags aspectMask, deUint32 mipLevel, deUint32 baseArrayLayer, deUint32 layerCount)
+{
+ VkImageSubresourceLayers res;
+ res.aspectMask = aspectMask;
+ res.mipLevel = mipLevel;
+ res.baseArrayLayer = baseArrayLayer;
+ res.layerCount = layerCount;
+ return res;
+}
+
+inline VkClearDepthStencilValue makeClearDepthStencilValue (float depth, deUint32 stencil)
+{
+ VkClearDepthStencilValue res;
+ res.depth = depth;
+ res.stencil = stencil;
+ return res;
+}
+
+inline VkDispatchIndirectCommand makeDispatchIndirectCommand (deUint32 x, deUint32 y, deUint32 z)
+{
+ VkDispatchIndirectCommand res;
+ res.x = x;
+ res.y = y;
+ res.z = z;
+ return res;
+}
+
+inline VkDrawIndexedIndirectCommand makeDrawIndexedIndirectCommand (deUint32 indexCount, deUint32 instanceCount, deUint32 firstIndex, deInt32 vertexOffset, deUint32 firstInstance)
+{
+ VkDrawIndexedIndirectCommand res;
+ res.indexCount = indexCount;
+ res.instanceCount = instanceCount;
+ res.firstIndex = firstIndex;
+ res.vertexOffset = vertexOffset;
+ res.firstInstance = firstInstance;
+ return res;
+}
+
+inline VkDrawIndirectCommand makeDrawIndirectCommand (deUint32 vertexCount, deUint32 instanceCount, deUint32 firstVertex, deUint32 firstInstance)
+{
+ VkDrawIndirectCommand res;
+ res.vertexCount = vertexCount;
+ res.instanceCount = instanceCount;
+ res.firstVertex = firstVertex;
+ res.firstInstance = firstInstance;
+ return res;
+}
+
+inline VkSurfaceFormatKHR makeSurfaceFormatKHR (VkFormat format, VkColorSpaceKHR colorSpace)
+{
+ VkSurfaceFormatKHR res;
+ res.format = format;
+ res.colorSpace = colorSpace;
+ return res;
+}
+
+inline VkDisplayPlanePropertiesKHR makeDisplayPlanePropertiesKHR (VkDisplayKHR currentDisplay, deUint32 currentStackIndex)
+{
+ VkDisplayPlanePropertiesKHR res;
+ res.currentDisplay = currentDisplay;
+ res.currentStackIndex = currentStackIndex;
+ return res;
+}
--- /dev/null
+/* WARNING: This is auto-generated file. Do not modify, since changes will
+ * be lost! Modify the generating script instead.
+ */
+virtual void destroyDevice (VkDevice device, const VkAllocationCallbacks* pAllocator) const = 0;
+virtual void getDeviceQueue (VkDevice device, deUint32 queueFamilyIndex, deUint32 queueIndex, VkQueue* pQueue) const = 0;
+virtual VkResult queueSubmit (VkQueue queue, deUint32 submitCount, const VkSubmitInfo* pSubmits, VkFence fence) const = 0;
+virtual VkResult queueWaitIdle (VkQueue queue) const = 0;
+virtual VkResult deviceWaitIdle (VkDevice device) const = 0;
+virtual VkResult allocateMemory (VkDevice device, const VkMemoryAllocateInfo* pAllocateInfo, const VkAllocationCallbacks* pAllocator, VkDeviceMemory* pMemory) const = 0;
+virtual void freeMemory (VkDevice device, VkDeviceMemory memory, const VkAllocationCallbacks* pAllocator) const = 0;
+virtual VkResult mapMemory (VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData) const = 0;
+virtual void unmapMemory (VkDevice device, VkDeviceMemory memory) const = 0;
+virtual VkResult flushMappedMemoryRanges (VkDevice device, deUint32 memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges) const = 0;
+virtual VkResult invalidateMappedMemoryRanges (VkDevice device, deUint32 memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges) const = 0;
+virtual void getDeviceMemoryCommitment (VkDevice device, VkDeviceMemory memory, VkDeviceSize* pCommittedMemoryInBytes) const = 0;
+virtual VkResult bindBufferMemory (VkDevice device, VkBuffer buffer, VkDeviceMemory memory, VkDeviceSize memoryOffset) const = 0;
+virtual VkResult bindImageMemory (VkDevice device, VkImage image, VkDeviceMemory memory, VkDeviceSize memoryOffset) const = 0;
+virtual void getBufferMemoryRequirements (VkDevice device, VkBuffer buffer, VkMemoryRequirements* pMemoryRequirements) const = 0;
+virtual void getImageMemoryRequirements (VkDevice device, VkImage image, VkMemoryRequirements* pMemoryRequirements) const = 0;
+virtual void getImageSparseMemoryRequirements (VkDevice device, VkImage image, deUint32* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements* pSparseMemoryRequirements) const = 0;
+virtual void getPhysicalDeviceSparseImageFormatProperties (VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling, deUint32* pPropertyCount, VkSparseImageFormatProperties* pProperties) const = 0;
+virtual VkResult queueBindSparse (VkQueue queue, deUint32 bindInfoCount, const VkBindSparseInfo* pBindInfo, VkFence fence) const = 0;
+virtual VkResult createFence (VkDevice device, const VkFenceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence) const = 0;
+virtual void destroyFence (VkDevice device, VkFence fence, const VkAllocationCallbacks* pAllocator) const = 0;
+virtual VkResult resetFences (VkDevice device, deUint32 fenceCount, const VkFence* pFences) const = 0;
+virtual VkResult getFenceStatus (VkDevice device, VkFence fence) const = 0;
+virtual VkResult waitForFences (VkDevice device, deUint32 fenceCount, const VkFence* pFences, VkBool32 waitAll, deUint64 timeout) const = 0;
+virtual VkResult createSemaphore (VkDevice device, const VkSemaphoreCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSemaphore* pSemaphore) const = 0;
+virtual void destroySemaphore (VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks* pAllocator) const = 0;
+virtual VkResult createEvent (VkDevice device, const VkEventCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkEvent* pEvent) const = 0;
+virtual void destroyEvent (VkDevice device, VkEvent event, const VkAllocationCallbacks* pAllocator) const = 0;
+virtual VkResult getEventStatus (VkDevice device, VkEvent event) const = 0;
+virtual VkResult setEvent (VkDevice device, VkEvent event) const = 0;
+virtual VkResult resetEvent (VkDevice device, VkEvent event) const = 0;
+virtual VkResult createQueryPool (VkDevice device, const VkQueryPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkQueryPool* pQueryPool) const = 0;
+virtual void destroyQueryPool (VkDevice device, VkQueryPool queryPool, const VkAllocationCallbacks* pAllocator) const = 0;
+virtual VkResult getQueryPoolResults (VkDevice device, VkQueryPool queryPool, deUint32 startQuery, deUint32 queryCount, deUintptr dataSize, void* pData, VkDeviceSize stride, VkQueryResultFlags flags) const = 0;
+virtual VkResult createBuffer (VkDevice device, const VkBufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBuffer* pBuffer) const = 0;
+virtual void destroyBuffer (VkDevice device, VkBuffer buffer, const VkAllocationCallbacks* pAllocator) const = 0;
+virtual VkResult createBufferView (VkDevice device, const VkBufferViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBufferView* pView) const = 0;
+virtual void destroyBufferView (VkDevice device, VkBufferView bufferView, const VkAllocationCallbacks* pAllocator) const = 0;
+virtual VkResult createImage (VkDevice device, const VkImageCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImage* pImage) const = 0;
+virtual void destroyImage (VkDevice device, VkImage image, const VkAllocationCallbacks* pAllocator) const = 0;
+virtual void getImageSubresourceLayout (VkDevice device, VkImage image, const VkImageSubresource* pSubresource, VkSubresourceLayout* pLayout) const = 0;
+virtual VkResult createImageView (VkDevice device, const VkImageViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImageView* pView) const = 0;
+virtual void destroyImageView (VkDevice device, VkImageView imageView, const VkAllocationCallbacks* pAllocator) const = 0;
+virtual VkResult createShaderModule (VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule) const = 0;
+virtual void destroyShaderModule (VkDevice device, VkShaderModule shaderModule, const VkAllocationCallbacks* pAllocator) const = 0;
+virtual VkResult createPipelineCache (VkDevice device, const VkPipelineCacheCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineCache* pPipelineCache) const = 0;
+virtual void destroyPipelineCache (VkDevice device, VkPipelineCache pipelineCache, const VkAllocationCallbacks* pAllocator) const = 0;
+virtual VkResult getPipelineCacheData (VkDevice device, VkPipelineCache pipelineCache, deUintptr* pDataSize, void* pData) const = 0;
+virtual VkResult mergePipelineCaches (VkDevice device, VkPipelineCache dstCache, deUint32 srcCacheCount, const VkPipelineCache* pSrcCaches) const = 0;
+virtual VkResult createGraphicsPipelines (VkDevice device, VkPipelineCache pipelineCache, deUint32 createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines) const = 0;
+virtual VkResult createComputePipelines (VkDevice device, VkPipelineCache pipelineCache, deUint32 createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines) const = 0;
+virtual void destroyPipeline (VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks* pAllocator) const = 0;
+virtual VkResult createPipelineLayout (VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout) const = 0;
+virtual void destroyPipelineLayout (VkDevice device, VkPipelineLayout pipelineLayout, const VkAllocationCallbacks* pAllocator) const = 0;
+virtual VkResult createSampler (VkDevice device, const VkSamplerCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSampler* pSampler) const = 0;
+virtual void destroySampler (VkDevice device, VkSampler sampler, const VkAllocationCallbacks* pAllocator) const = 0;
+virtual VkResult createDescriptorSetLayout (VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorSetLayout* pSetLayout) const = 0;
+virtual void destroyDescriptorSetLayout (VkDevice device, VkDescriptorSetLayout descriptorSetLayout, const VkAllocationCallbacks* pAllocator) const = 0;
+virtual VkResult createDescriptorPool (VkDevice device, const VkDescriptorPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorPool* pDescriptorPool) const = 0;
+virtual void destroyDescriptorPool (VkDevice device, VkDescriptorPool descriptorPool, const VkAllocationCallbacks* pAllocator) const = 0;
+virtual VkResult resetDescriptorPool (VkDevice device, VkDescriptorPool descriptorPool, VkDescriptorPoolResetFlags flags) const = 0;
+virtual VkResult allocateDescriptorSets (VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets) const = 0;
+virtual VkResult freeDescriptorSets (VkDevice device, VkDescriptorPool descriptorPool, deUint32 descriptorSetCount, const VkDescriptorSet* pDescriptorSets) const = 0;
+virtual void updateDescriptorSets (VkDevice device, deUint32 descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites, deUint32 descriptorCopyCount, const VkCopyDescriptorSet* pDescriptorCopies) const = 0;
+virtual VkResult createFramebuffer (VkDevice device, const VkFramebufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkFramebuffer* pFramebuffer) const = 0;
+virtual void destroyFramebuffer (VkDevice device, VkFramebuffer framebuffer, const VkAllocationCallbacks* pAllocator) const = 0;
+virtual VkResult createRenderPass (VkDevice device, const VkRenderPassCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass) const = 0;
+virtual void destroyRenderPass (VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks* pAllocator) const = 0;
+virtual void getRenderAreaGranularity (VkDevice device, VkRenderPass renderPass, VkExtent2D* pGranularity) const = 0;
+virtual VkResult createCommandPool (VkDevice device, const VkCommandPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCommandPool* pCommandPool) const = 0;
+virtual void destroyCommandPool (VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks* pAllocator) const = 0;
+virtual VkResult resetCommandPool (VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags) const = 0;
+virtual VkResult allocateCommandBuffers (VkDevice device, const VkCommandBufferAllocateInfo* pAllocateInfo, VkCommandBuffer* pCommandBuffers) const = 0;
+virtual void freeCommandBuffers (VkDevice device, VkCommandPool commandPool, deUint32 commandBufferCount, const VkCommandBuffer* pCommandBuffers) const = 0;
+virtual VkResult beginCommandBuffer (VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo* pBeginInfo) const = 0;
+virtual VkResult endCommandBuffer (VkCommandBuffer commandBuffer) const = 0;
+virtual VkResult resetCommandBuffer (VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags) const = 0;
+virtual void cmdBindPipeline (VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline) const = 0;
+virtual void cmdSetViewport (VkCommandBuffer commandBuffer, deUint32 viewportCount, const VkViewport* pViewports) const = 0;
+virtual void cmdSetScissor (VkCommandBuffer commandBuffer, deUint32 scissorCount, const VkRect2D* pScissors) const = 0;
+virtual void cmdSetLineWidth (VkCommandBuffer commandBuffer, float lineWidth) const = 0;
+virtual void cmdSetDepthBias (VkCommandBuffer commandBuffer, float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor) const = 0;
+virtual void cmdSetBlendConstants (VkCommandBuffer commandBuffer, const float blendConstants[4]) const = 0;
+virtual void cmdSetDepthBounds (VkCommandBuffer commandBuffer, float minDepthBounds, float maxDepthBounds) const = 0;
+virtual void cmdSetStencilCompareMask (VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, deUint32 compareMask) const = 0;
+virtual void cmdSetStencilWriteMask (VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, deUint32 writeMask) const = 0;
+virtual void cmdSetStencilReference (VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, deUint32 reference) const = 0;
+virtual void cmdBindDescriptorSets (VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, deUint32 firstSet, deUint32 descriptorSetCount, const VkDescriptorSet* pDescriptorSets, deUint32 dynamicOffsetCount, const deUint32* pDynamicOffsets) const = 0;
+virtual void cmdBindIndexBuffer (VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType) const = 0;
+virtual void cmdBindVertexBuffers (VkCommandBuffer commandBuffer, deUint32 startBinding, deUint32 bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets) const = 0;
+virtual void cmdDraw (VkCommandBuffer commandBuffer, deUint32 vertexCount, deUint32 instanceCount, deUint32 firstVertex, deUint32 firstInstance) const = 0;
+virtual void cmdDrawIndexed (VkCommandBuffer commandBuffer, deUint32 indexCount, deUint32 instanceCount, deUint32 firstIndex, deInt32 vertexOffset, deUint32 firstInstance) const = 0;
+virtual void cmdDrawIndirect (VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, deUint32 drawCount, deUint32 stride) const = 0;
+virtual void cmdDrawIndexedIndirect (VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, deUint32 drawCount, deUint32 stride) const = 0;
+virtual void cmdDispatch (VkCommandBuffer commandBuffer, deUint32 x, deUint32 y, deUint32 z) const = 0;
+virtual void cmdDispatchIndirect (VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) const = 0;
+virtual void cmdCopyBuffer (VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, deUint32 regionCount, const VkBufferCopy* pRegions) const = 0;
+virtual void cmdCopyImage (VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, deUint32 regionCount, const VkImageCopy* pRegions) const = 0;
+virtual void cmdBlitImage (VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, deUint32 regionCount, const VkImageBlit* pRegions, VkFilter filter) const = 0;
+virtual void cmdCopyBufferToImage (VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage, VkImageLayout dstImageLayout, deUint32 regionCount, const VkBufferImageCopy* pRegions) const = 0;
+virtual void cmdCopyImageToBuffer (VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkBuffer dstBuffer, deUint32 regionCount, const VkBufferImageCopy* pRegions) const = 0;
+virtual void cmdUpdateBuffer (VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const deUint32* pData) const = 0;
+virtual void cmdFillBuffer (VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, deUint32 data) const = 0;
+virtual void cmdClearColorImage (VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearColorValue* pColor, deUint32 rangeCount, const VkImageSubresourceRange* pRanges) const = 0;
+virtual void cmdClearDepthStencilImage (VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearDepthStencilValue* pDepthStencil, deUint32 rangeCount, const VkImageSubresourceRange* pRanges) const = 0;
+virtual void cmdClearAttachments (VkCommandBuffer commandBuffer, deUint32 attachmentCount, const VkClearAttachment* pAttachments, deUint32 rectCount, const VkClearRect* pRects) const = 0;
+virtual void cmdResolveImage (VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, deUint32 regionCount, const VkImageResolve* pRegions) const = 0;
+virtual void cmdSetEvent (VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) const = 0;
+virtual void cmdResetEvent (VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) const = 0;
+virtual void cmdWaitEvents (VkCommandBuffer commandBuffer, deUint32 eventCount, const VkEvent* pEvents, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, deUint32 memoryBarrierCount, const void* const* ppMemoryBarriers) const = 0;
+virtual void cmdPipelineBarrier (VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, deUint32 memoryBarrierCount, const void* const* ppMemoryBarriers) const = 0;
+virtual void cmdBeginQuery (VkCommandBuffer commandBuffer, VkQueryPool queryPool, deUint32 entry, VkQueryControlFlags flags) const = 0;
+virtual void cmdEndQuery (VkCommandBuffer commandBuffer, VkQueryPool queryPool, deUint32 entry) const = 0;
+virtual void cmdResetQueryPool (VkCommandBuffer commandBuffer, VkQueryPool queryPool, deUint32 startQuery, deUint32 queryCount) const = 0;
+virtual void cmdWriteTimestamp (VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkQueryPool queryPool, deUint32 entry) const = 0;
+virtual void cmdCopyQueryPoolResults (VkCommandBuffer commandBuffer, VkQueryPool queryPool, deUint32 startQuery, deUint32 queryCount, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags) const = 0;
+virtual void cmdPushConstants (VkCommandBuffer commandBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, deUint32 offset, deUint32 size, const void* pValues) const = 0;
+virtual void cmdBeginRenderPass (VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, VkSubpassContents contents) const = 0;
+virtual void cmdNextSubpass (VkCommandBuffer commandBuffer, VkSubpassContents contents) const = 0;
+virtual void cmdEndRenderPass (VkCommandBuffer commandBuffer) const = 0;
+virtual void cmdExecuteCommands (VkCommandBuffer commandBuffer, deUint32 commandBuffersCount, const VkCommandBuffer* pCommandBuffers) const = 0;
--- /dev/null
+/* WARNING: This is auto-generated file. Do not modify, since changes will
+ * be lost! Modify the generating script instead.
+ */
+virtual void destroyInstance (VkInstance instance, const VkAllocationCallbacks* pAllocator) const = 0;
+virtual VkResult enumeratePhysicalDevices (VkInstance instance, deUint32* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices) const = 0;
+virtual void getPhysicalDeviceFeatures (VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures* pFeatures) const = 0;
+virtual void getPhysicalDeviceFormatProperties (VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties* pFormatProperties) const = 0;
+virtual VkResult getPhysicalDeviceImageFormatProperties (VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties* pImageFormatProperties) const = 0;
+virtual void getPhysicalDeviceProperties (VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties* pProperties) const = 0;
+virtual void getPhysicalDeviceQueueFamilyProperties (VkPhysicalDevice physicalDevice, deUint32* pQueueFamilyPropertyCount, VkQueueFamilyProperties* pQueueFamilyProperties) const = 0;
+virtual void getPhysicalDeviceMemoryProperties (VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties* pMemoryProperties) const = 0;
+virtual PFN_vkVoidFunction getDeviceProcAddr (VkDevice device, const char* pName) const = 0;
+virtual VkResult createDevice (VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice) const = 0;
+virtual VkResult enumerateDeviceExtensionProperties (VkPhysicalDevice physicalDevice, const char* pLayerName, deUint32* pPropertyCount, VkExtensionProperties* pProperties) const = 0;
+virtual VkResult enumerateDeviceLayerProperties (VkPhysicalDevice physicalDevice, deUint32* pPropertyCount, VkLayerProperties* pProperties) const = 0;
--- /dev/null
+/* WARNING: This is auto-generated file. Do not modify, since changes will
+ * be lost! Modify the generating script instead.
+ */
+virtual VkResult createInstance (const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance) const = 0;
+virtual PFN_vkVoidFunction getInstanceProcAddr (VkInstance instance, const char* pName) const = 0;
+virtual VkResult enumerateInstanceExtensionProperties (const char* pLayerName, deUint32* pPropertyCount, VkExtensionProperties* pProperties) const = 0;
+virtual VkResult enumerateInstanceLayerProperties (deUint32* pPropertyCount, VkLayerProperties* pProperties) const = 0;
--- /dev/null
+# -*- coding: utf-8 -*-
+
+#-------------------------------------------------------------------------
+# Vulkan CTS
+# ----------
+#
+# Copyright (c) 2015 Google Inc.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and/or associated documentation files (the
+# "Materials"), to deal in the Materials without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Materials, and to
+# permit persons to whom the Materials are furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice(s) and this permission notice shall be
+# included in all copies or substantial portions of the Materials.
+#
+# The Materials are Confidential Information as defined by the
+# Khronos Membership Agreement until designated non-confidential by
+# Khronos, at which point this condition clause shall be removed.
+#
+# THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+#
+#-------------------------------------------------------------------------
+
+import os
+import re
+import sys
+
+sys.path.append(os.path.join(os.path.dirname(__file__), "..", "..", "scripts"))
+
+from build.common import DEQP_DIR
+from khr_util.format import indentLines, writeInlFile
+
+VULKAN_DIR = os.path.join(os.path.dirname(__file__), "framework", "vulkan")
+
+INL_HEADER = """\
+/* WARNING: This is auto-generated file. Do not modify, since changes will
+ * be lost! Modify the generating script instead.
+ */\
+"""
+
+PLATFORM_FUNCTIONS = [
+ "vkCreateInstance",
+ "vkGetInstanceProcAddr",
+ "vkEnumerateInstanceExtensionProperties",
+ "vkEnumerateInstanceLayerProperties",
+]
+INSTANCE_FUNCTIONS = [
+ "vkDestroyInstance",
+ "vkEnumeratePhysicalDevices",
+ "vkGetPhysicalDeviceFeatures",
+ "vkGetPhysicalDeviceFormatProperties",
+ "vkGetPhysicalDeviceImageFormatProperties",
+ "vkGetPhysicalDeviceLimits",
+ "vkGetPhysicalDeviceProperties",
+ "vkGetPhysicalDeviceQueueFamilyProperties",
+ "vkGetPhysicalDeviceMemoryProperties",
+ "vkEnumerateDeviceExtensionProperties",
+ "vkEnumerateDeviceLayerProperties",
+ "vkCreateDevice",
+ "vkGetDeviceProcAddr",
+]
+
+DEFINITIONS = [
+ "VK_API_VERSION",
+ "VK_MAX_PHYSICAL_DEVICE_NAME_SIZE",
+ "VK_MAX_EXTENSION_NAME_SIZE",
+ "VK_UUID_SIZE",
+ "VK_MAX_MEMORY_TYPES",
+ "VK_MAX_MEMORY_HEAPS",
+ "VK_MAX_DESCRIPTION_SIZE",
+ "VK_ATTACHMENT_UNUSED",
+]
+
+class Handle:
+ TYPE_DISP = 0
+ TYPE_NONDISP = 1
+
+ def __init__ (self, type, name):
+ self.type = type
+ self.name = name
+
+ def getHandleType (self):
+ name = re.sub(r'([a-z])([A-Z])', r'\1_\2', self.name)
+ return "HANDLE_TYPE_" + name[3:].upper()
+
+class Enum:
+ def __init__ (self, name, values):
+ self.name = name
+ self.values = values
+
+class Bitfield:
+ def __init__ (self, name, values):
+ self.name = name
+ self.values = values
+
+class Variable:
+ def __init__ (self, type, name, arraySize = None):
+ self.type = type
+ self.name = name
+ self.arraySize = arraySize
+
+class CompositeType:
+ CLASS_STRUCT = 0
+ CLASS_UNION = 1
+
+ def __init__ (self, typeClass, name, members):
+ self.typeClass = typeClass
+ self.name = name
+ self.members = members
+
+ def getClassName (self):
+ names = {CompositeType.CLASS_STRUCT: 'struct', CompositeType.CLASS_UNION: 'union'}
+ return names[self.typeClass]
+
+class Function:
+ TYPE_PLATFORM = 0 # Not bound to anything
+ TYPE_INSTANCE = 1 # Bound to VkInstance
+ TYPE_DEVICE = 2 # Bound to VkDevice
+
+ def __init__ (self, name, returnType, arguments):
+ self.name = name
+ self.returnType = returnType
+ self.arguments = arguments
+
+ def getType (self):
+ if self.name in PLATFORM_FUNCTIONS:
+ return Function.TYPE_PLATFORM
+ elif self.name in INSTANCE_FUNCTIONS:
+ return Function.TYPE_INSTANCE
+ else:
+ return Function.TYPE_DEVICE
+
+class API:
+ def __init__ (self, definitions, handles, enums, bitfields, compositeTypes, functions):
+ self.definitions = definitions
+ self.handles = handles
+ self.enums = enums
+ self.bitfields = bitfields
+ self.compositeTypes = compositeTypes
+ self.functions = functions
+
+def readFile (filename):
+ with open(filename, 'rb') as f:
+ return f.read()
+
+IDENT_PTRN = r'[a-zA-Z_][a-zA-Z0-9_]*'
+TYPE_PTRN = r'[a-zA-Z_][a-zA-Z0-9_ \t*]*'
+
+def endswith (s, postfix):
+ return len(s) >= len(postfix) and s[len(s)-len(postfix):] == postfix
+
+def fixupEnumValues (values):
+ fixed = []
+ for name, value in values:
+ if endswith(name, "_BEGIN_RANGE") or endswith(name, "_END_RANGE"):
+ continue
+ fixed.append((name, value))
+ return fixed
+
+def fixupType (type):
+ replacements = [
+ ("uint8_t", "deUint8"),
+ ("uint16_t", "deUint16"),
+ ("uint32_t", "deUint32"),
+ ("uint64_t", "deUint64"),
+ ("int8_t", "deInt8"),
+ ("int16_t", "deInt16"),
+ ("int32_t", "deInt32"),
+ ("int64_t", "deInt64"),
+ ("bool32_t", "deUint32"),
+ ("size_t", "deUintptr"),
+ ]
+
+ for src, dst in replacements:
+ type = type.replace(src, dst)
+
+ return type
+
+def fixupFunction (function):
+ fixedArgs = [Variable(fixupType(a.type), a.name, a.arraySize) for a in function.arguments]
+ fixedReturnType = fixupType(function.returnType)
+
+ return Function(function.name, fixedReturnType, fixedArgs)
+
+def getInterfaceName (function):
+ assert function.name[:2] == "vk"
+ return function.name[2].lower() + function.name[3:]
+
+def getFunctionTypeName (function):
+ assert function.name[:2] == "vk"
+ return function.name[2:] + "Func"
+
+def getBitEnumNameForBitfield (bitfieldName):
+ if bitfieldName[-3:] == "KHR":
+ postfix = "KHR"
+ bitfieldName = bitfieldName[:-3]
+ else:
+ postfix = ""
+
+ assert bitfieldName[-1] == "s"
+ return bitfieldName[:-1] + "Bits" + postfix
+
+def getBitfieldNameForBitEnum (bitEnumName):
+ if bitEnumName[-3:] == "KHR":
+ postfix = "KHR"
+ bitEnumName = bitEnumName[:-3]
+ else:
+ postfix = ""
+
+ assert bitEnumName[-4:] == "Bits"
+ return bitEnumName[:-4] + "s" + postfix
+
+def parsePreprocDefinedValue (src, name):
+ definition = re.search(r'#\s*define\s+' + name + r'\s+([^\n]+)\n', src)
+ if definition is None:
+ raise Exception("No such definition: %s" % name)
+ value = definition.group(1).strip()
+
+ if value == "UINT32_MAX":
+ value = "(~0u)"
+
+ return value
+
+def parseEnum (name, src):
+ keyValuePtrn = '(' + IDENT_PTRN + r')\s*=\s*([^\s,}]+)\s*[,}]'
+ matches = re.findall(keyValuePtrn, src)
+
+ return Enum(name, fixupEnumValues(matches))
+
+# \note Parses raw enums, some are mapped to bitfields later
+def parseEnums (src):
+ matches = re.findall(r'typedef enum(\s*' + IDENT_PTRN + r')?\s*{([^}]*)}\s*(' + IDENT_PTRN + r')\s*;', src)
+ enums = []
+
+ for enumname, contents, typename in matches:
+ enums.append(parseEnum(typename, contents))
+
+ return enums
+
+def parseCompositeType (type, name, src):
+ # \todo [pyry] Array support is currently a hack (size coupled with name)
+ typeNamePtrn = r'(' + TYPE_PTRN + ')(\s' + IDENT_PTRN + r'(\[[^\]]+\])*)\s*;'
+ matches = re.findall(typeNamePtrn, src)
+ members = [Variable(fixupType(t.strip()), n.strip()) for t, n, a in matches]
+
+ return CompositeType(type, name, members)
+
+def parseCompositeTypes (src):
+ typeMap = { 'struct': CompositeType.CLASS_STRUCT, 'union': CompositeType.CLASS_UNION }
+ matches = re.findall(r'typedef (struct|union)(\s*' + IDENT_PTRN + r')?\s*{([^}]*)}\s*(' + IDENT_PTRN + r')\s*;', src)
+ types = []
+
+ for type, structname, contents, typename in matches:
+ types.append(parseCompositeType(typeMap[type], typename, contents))
+
+ return types
+
+def parseHandles (src):
+ matches = re.findall(r'VK_DEFINE(_NON_DISPATCHABLE|)_HANDLE\((' + IDENT_PTRN + r')\)[ \t]*[\n\r]', src)
+ handles = []
+ typeMap = {'': Handle.TYPE_DISP, '_NON_DISPATCHABLE': Handle.TYPE_NONDISP}
+
+ for type, name in matches:
+ handle = Handle(typeMap[type], name)
+ handles.append(handle)
+
+ return handles
+
+def parseArgList (src):
+ typeNamePtrn = r'(' + TYPE_PTRN + ')(\s' + IDENT_PTRN + r')(\[[^\]]+\])?'
+ args = []
+
+ for rawArg in src.split(','):
+ m = re.search(typeNamePtrn, rawArg)
+ args.append(Variable(m.group(1).strip(), m.group(2).strip(), m.group(3)))
+
+ return args
+
+def parseFunctions (src):
+ ptrn = r'VKAPI_ATTR\s+(' + TYPE_PTRN + ')VKAPI_CALL\s+(' + IDENT_PTRN + r')\s*\(([^)]*)\)\s*;'
+ matches = re.findall(ptrn, src)
+ functions = []
+
+ for returnType, name, argList in matches:
+ if name[-3:] == "KHR":
+ continue # \todo [2015-11-16 pyry] Figure out how to handle platform-specific extension functions
+
+ functions.append(Function(name.strip(), returnType.strip(), parseArgList(argList)))
+
+ return [fixupFunction(f) for f in functions]
+
+def parseBitfieldNames (src):
+ ptrn = r'typedef\s+VkFlags\s(' + IDENT_PTRN + r')\s*;'
+ matches = re.findall(ptrn, src)
+
+ return matches
+
+def parseAPI (src):
+ definitions = [(name, parsePreprocDefinedValue(src, name)) for name in DEFINITIONS]
+ rawEnums = parseEnums(src)
+ bitfieldNames = parseBitfieldNames(src)
+ enums = []
+ bitfields = []
+ bitfieldEnums = set([getBitEnumNameForBitfield(n) for n in bitfieldNames])
+
+ for enum in rawEnums:
+ if enum.name in bitfieldEnums:
+ bitfields.append(Bitfield(getBitfieldNameForBitEnum(enum.name), enum.values))
+ else:
+ enums.append(enum)
+
+ for bitfieldName in bitfieldNames:
+ if not bitfieldName in [bitfield.name for bitfield in bitfields]:
+ # Add empty bitfield
+ bitfields.append(Bitfield(bitfieldName, []))
+
+ return API(
+ definitions = definitions,
+ handles = parseHandles(src),
+ enums = enums,
+ bitfields = bitfields,
+ compositeTypes = parseCompositeTypes(src),
+ functions = parseFunctions(src))
+
+def writeHandleType (api, filename):
+ def gen ():
+ yield "enum HandleType"
+ yield "{"
+ yield "\t%s = 0," % api.handles[0].getHandleType()
+ for handle in api.handles[1:]:
+ yield "\t%s," % handle.getHandleType()
+ yield "\tHANDLE_TYPE_LAST"
+ yield "};"
+ yield ""
+
+ writeInlFile(filename, INL_HEADER, gen())
+
+def getEnumValuePrefix (enum):
+ prefix = enum.name[0]
+ for i in range(1, len(enum.name)):
+ if enum.name[i].isupper():
+ prefix += "_"
+ prefix += enum.name[i].upper()
+ return prefix
+
+def parseInt (value):
+ if value[:2] == "0x":
+ return int(value, 16)
+ else:
+ return int(value, 10)
+
+def areEnumValuesLinear (enum):
+ curIndex = 0
+ for name, value in enum.values:
+ if parseInt(value) != curIndex:
+ return False
+ curIndex += 1
+ return True
+
+def genEnumSrc (enum):
+ yield "enum %s" % enum.name
+ yield "{"
+
+ for line in indentLines(["\t%s\t= %s," % v for v in enum.values]):
+ yield line
+
+ if areEnumValuesLinear(enum):
+ yield ""
+ yield "\t%s_LAST" % getEnumValuePrefix(enum)
+
+ yield "};"
+
+def genBitfieldSrc (bitfield):
+ if len(bitfield.values) > 0:
+ yield "enum %s" % getBitEnumNameForBitfield(bitfield.name)
+ yield "{"
+ for line in indentLines(["\t%s\t= %s," % v for v in bitfield.values]):
+ yield line
+ yield "};"
+
+ yield "typedef deUint32 %s;" % bitfield.name
+
+def genCompositeTypeSrc (type):
+ yield "%s %s" % (type.getClassName(), type.name)
+ yield "{"
+ for line in indentLines(["\t%s\t%s;" % (m.type, m.name) for m in type.members]):
+ yield line
+ yield "};"
+
+def genHandlesSrc (handles):
+ def genLines (handles):
+ for handle in handles:
+ if handle.type == Handle.TYPE_DISP:
+ yield "VK_DEFINE_HANDLE\t(%s,\t%s);" % (handle.name, handle.getHandleType())
+ elif handle.type == Handle.TYPE_NONDISP:
+ yield "VK_DEFINE_NON_DISPATCHABLE_HANDLE\t(%s,\t%s);" % (handle.name, handle.getHandleType())
+
+ for line in indentLines(genLines(handles)):
+ yield line
+
+def writeBasicTypes (api, filename):
+ def gen ():
+ for line in indentLines(["enum { %s\t= %s\t};" % define for define in api.definitions]):
+ yield line
+ yield ""
+ for line in genHandlesSrc(api.handles):
+ yield line
+ yield ""
+ for enum in api.enums:
+ for line in genEnumSrc(enum):
+ yield line
+ yield ""
+ for bitfield in api.bitfields:
+ for line in genBitfieldSrc(bitfield):
+ yield line
+ yield ""
+
+ writeInlFile(filename, INL_HEADER, gen())
+
+def writeCompositeTypes (api, filename):
+ def gen ():
+ for type in api.compositeTypes:
+ for line in genCompositeTypeSrc(type):
+ yield line
+ yield ""
+
+ writeInlFile(filename, INL_HEADER, gen())
+
+def argListToStr (args):
+ return ", ".join("%s %s%s" % (v.type, v.name, v.arraySize if v.arraySize != None else "") for v in args)
+
+def writeInterfaceDecl (api, filename, functionTypes, concrete):
+ def genProtos ():
+ postfix = "" if concrete else " = 0"
+ for function in api.functions:
+ if function.getType() in functionTypes:
+ yield "virtual %s\t%s\t(%s) const%s;" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments), postfix)
+
+ writeInlFile(filename, INL_HEADER, indentLines(genProtos()))
+
+def writeFunctionPtrTypes (api, filename):
+ def genTypes ():
+ for function in api.functions:
+ yield "typedef VKAPI_ATTR %s\t(VKAPI_CALL* %s)\t(%s);" % (function.returnType, getFunctionTypeName(function), argListToStr(function.arguments))
+
+ writeInlFile(filename, INL_HEADER, indentLines(genTypes()))
+
+def writeFunctionPointers (api, filename, functionTypes):
+ writeInlFile(filename, INL_HEADER, indentLines(["%s\t%s;" % (getFunctionTypeName(function), getInterfaceName(function)) for function in api.functions if function.getType() in functionTypes]))
+
+def writeInitFunctionPointers (api, filename, functionTypes):
+ def makeInitFunctionPointers ():
+ for function in api.functions:
+ if function.getType() in functionTypes:
+ yield "m_vk.%s\t= (%s)\tGET_PROC_ADDR(\"%s\");" % (getInterfaceName(function), getFunctionTypeName(function), function.name)
+
+ writeInlFile(filename, INL_HEADER, indentLines(makeInitFunctionPointers()))
+
+def writeFuncPtrInterfaceImpl (api, filename, functionTypes, className):
+ def makeFuncPtrInterfaceImpl ():
+ for function in api.functions:
+ if function.getType() in functionTypes:
+ yield ""
+ yield "%s %s::%s (%s) const" % (function.returnType, className, getInterfaceName(function), argListToStr(function.arguments))
+ yield "{"
+ yield " %sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function), ", ".join(a.name for a in function.arguments))
+ yield "}"
+
+ writeInlFile(filename, INL_HEADER, makeFuncPtrInterfaceImpl())
+
+def writeStrUtilProto (api, filename):
+ def makeStrUtilProto ():
+ for line in indentLines(["const char*\tget%sName\t(%s value);" % (enum.name[2:], enum.name) for enum in api.enums]):
+ yield line
+ yield ""
+ for line in indentLines(["inline tcu::Format::Enum<%s>\tget%sStr\t(%s value)\t{ return tcu::Format::Enum<%s>(get%sName, value);\t}" % (e.name, e.name[2:], e.name, e.name, e.name[2:]) for e in api.enums]):
+ yield line
+ yield ""
+ for line in indentLines(["inline std::ostream&\toperator<<\t(std::ostream& s, %s value)\t{ return s << get%sStr(value);\t}" % (e.name, e.name[2:]) for e in api.enums]):
+ yield line
+ yield ""
+ for line in indentLines(["tcu::Format::Bitfield<32>\tget%sStr\t(%s value);" % (bitfield.name[2:], bitfield.name) for bitfield in api.bitfields]):
+ yield line
+ yield ""
+ for line in indentLines(["std::ostream&\toperator<<\t(std::ostream& s, const %s& value);" % (s.name) for s in api.compositeTypes]):
+ yield line
+
+ writeInlFile(filename, INL_HEADER, makeStrUtilProto())
+
+def writeStrUtilImpl (api, filename):
+ def makeStrUtilImpl ():
+ for line in indentLines(["template<> const char*\tgetTypeName<%s>\t(void) { return \"%s\";\t}" % (handle.name, handle.name) for handle in api.handles]):
+ yield line
+
+ for enum in api.enums:
+ yield ""
+ yield "const char* get%sName (%s value)" % (enum.name[2:], enum.name)
+ yield "{"
+ yield "\tswitch (value)"
+ yield "\t{"
+ for line in indentLines(["\t\tcase %s:\treturn \"%s\";" % (n, n) for n, v in enum.values] + ["\t\tdefault:\treturn DE_NULL;"]):
+ yield line
+ yield "\t}"
+ yield "}"
+
+ for bitfield in api.bitfields:
+ yield ""
+ yield "tcu::Format::Bitfield<32> get%sStr (%s value)" % (bitfield.name[2:], bitfield.name)
+ yield "{"
+
+ if len(bitfield.values) > 0:
+ yield "\tstatic const tcu::Format::BitDesc s_desc[] ="
+ yield "\t{"
+ for line in indentLines(["\t\ttcu::Format::BitDesc(%s,\t\"%s\")," % (n, n) for n, v in bitfield.values]):
+ yield line
+ yield "\t};"
+ yield "\treturn tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));"
+ else:
+ yield "\treturn tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);"
+
+ yield "}"
+
+ bitfieldTypeNames = set([bitfield.name for bitfield in api.bitfields])
+
+ for type in api.compositeTypes:
+ yield ""
+ yield "std::ostream& operator<< (std::ostream& s, const %s& value)" % type.name
+ yield "{"
+ yield "\ts << \"%s = {\\n\";" % type.name
+ for member in type.members:
+ memberName = member.name
+ valFmt = None
+ newLine = ""
+ if member.type in bitfieldTypeNames:
+ valFmt = "get%sStr(value.%s)" % (member.type[2:], member.name)
+ elif member.type == "const char*" or member.type == "char*":
+ valFmt = "getCharPtrStr(value.%s)" % member.name
+ elif '[' in member.name:
+ baseName = member.name[:member.name.find('[')]
+ if baseName in ["extensionName", "deviceName", "layerName", "description"]:
+ valFmt = "(const char*)value.%s" % baseName
+ elif member.type == 'char' or member.type == 'deUint8':
+ newLine = "'\\n' << "
+ valFmt = "tcu::formatArray(tcu::Format::HexIterator<%s>(DE_ARRAY_BEGIN(value.%s)), tcu::Format::HexIterator<%s>(DE_ARRAY_END(value.%s)))" % (member.type, baseName, member.type, baseName)
+ else:
+ newLine = "'\\n' << "
+ valFmt = "tcu::formatArray(DE_ARRAY_BEGIN(value.%s), DE_ARRAY_END(value.%s))" % (baseName, baseName)
+ memberName = baseName
+ else:
+ valFmt = "value.%s" % member.name
+ yield ("\ts << \"\\t%s = \" << " % memberName) + newLine + valFmt + " << '\\n';"
+ yield "\ts << '}';"
+ yield "\treturn s;"
+ yield "}"
+
+
+ writeInlFile(filename, INL_HEADER, makeStrUtilImpl())
+
+class ConstructorFunction:
+ def __init__ (self, type, name, objectType, iface, arguments):
+ self.type = type
+ self.name = name
+ self.objectType = objectType
+ self.iface = iface
+ self.arguments = arguments
+
+def getConstructorFunctions (api):
+ funcs = []
+ for function in api.functions:
+ if (function.name[:8] == "vkCreate" or function.name == "vkAllocateMemory") and not "count" in [a.name for a in function.arguments]:
+ # \todo [pyry] Rather hacky
+ iface = None
+ if function.getType() == Function.TYPE_PLATFORM:
+ iface = Variable("const PlatformInterface&", "vk")
+ elif function.getType() == Function.TYPE_INSTANCE:
+ iface = Variable("const InstanceInterface&", "vk")
+ else:
+ iface = Variable("const DeviceInterface&", "vk")
+
+ assert function.arguments[-2].type == "const VkAllocationCallbacks*"
+
+ objectType = function.arguments[-1].type.replace("*", "").strip()
+ arguments = function.arguments[:-2]
+ funcs.append(ConstructorFunction(function.getType(), getInterfaceName(function), objectType, iface, arguments))
+ return funcs
+
+def writeRefUtilProto (api, filename):
+ functions = getConstructorFunctions(api)
+
+ def makeRefUtilProto ():
+ unindented = []
+ for line in indentLines(["Move<%s>\t%s\t(%s);" % (function.objectType, function.name, argListToStr([function.iface] + function.arguments)) for function in functions]):
+ yield line
+
+ writeInlFile(filename, INL_HEADER, makeRefUtilProto())
+
+def writeRefUtilImpl (api, filename):
+ functions = getConstructorFunctions(api)
+
+ def makeRefUtilImpl ():
+ yield "namespace refdetails"
+ yield "{"
+ yield ""
+
+ for function in api.functions:
+ if function.getType() == Function.TYPE_DEVICE \
+ and (function.name[:9] == "vkDestroy" or function.name == "vkFreeMemory") \
+ and not function.name == "vkDestroyDevice":
+ objectType = function.arguments[-2].type
+ yield "template<>"
+ yield "void Deleter<%s>::operator() (%s obj) const" % (objectType, objectType)
+ yield "{"
+ yield "\tm_deviceIface->%s(m_device, obj, DE_NULL);" % (getInterfaceName(function))
+ yield "}"
+ yield ""
+
+ yield "} // refdetails"
+ yield ""
+
+ for function in functions:
+ dtorObj = "device" if function.type == Function.TYPE_DEVICE else "object"
+
+ yield "Move<%s> %s (%s)" % (function.objectType, function.name, argListToStr([function.iface] + function.arguments))
+ yield "{"
+ yield "\t%s object = 0;" % function.objectType
+ yield "\tVK_CHECK(vk.%s(%s));" % (function.name, ", ".join([a.name for a in function.arguments] + ["DE_NULL", "&object"]))
+ yield "\treturn Move<%s>(check<%s>(object), Deleter<%s>(vk, %s));" % (function.objectType, function.objectType, function.objectType, dtorObj)
+ yield "}"
+ yield ""
+
+ writeInlFile(filename, INL_HEADER, makeRefUtilImpl())
+
+def writeNullDriverImpl (api, filename):
+ def genNullDriverImpl ():
+ specialFuncNames = [
+ "vkCreateGraphicsPipelines",
+ "vkCreateComputePipelines",
+ "vkGetInstanceProcAddr",
+ "vkGetDeviceProcAddr",
+ "vkEnumeratePhysicalDevices",
+ "vkGetPhysicalDeviceProperties",
+ "vkGetPhysicalDeviceQueueFamilyProperties",
+ "vkGetPhysicalDeviceMemoryProperties",
+ "vkGetPhysicalDeviceFormatProperties",
+ "vkGetBufferMemoryRequirements",
+ "vkGetImageMemoryRequirements",
+ "vkMapMemory",
+ "vkAllocateDescriptorSets",
+ "vkFreeDescriptorSets",
+ "vkResetDescriptorPool",
+ "vkAllocateCommandBuffers",
+ "vkFreeCommandBuffers"
+ ]
+ specialFuncs = [f for f in api.functions if f.name in specialFuncNames]
+ createFuncs = [f for f in api.functions if (f.name[:8] == "vkCreate" or f.name == "vkAllocateMemory") and not f in specialFuncs]
+ destroyFuncs = [f for f in api.functions if (f.name[:9] == "vkDestroy" or f.name == "vkFreeMemory") and not f in specialFuncs]
+ dummyFuncs = [f for f in api.functions if f not in specialFuncs + createFuncs + destroyFuncs]
+
+ def getHandle (name):
+ for handle in api.handles:
+ if handle.name == name:
+ return handle
+ raise Exception("No such handle: %s" % name)
+
+ for function in createFuncs:
+ objectType = function.arguments[-1].type.replace("*", "").strip()
+ argsStr = ", ".join([a.name for a in function.arguments[:-2]])
+
+ yield "%s %s (%s)" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments))
+ yield "{"
+ yield "\tDE_UNREF(%s);" % function.arguments[-2].name
+
+ if getHandle(objectType).type == Handle.TYPE_NONDISP:
+ yield "\tVK_NULL_RETURN(*%s = %s((deUint64)(deUintptr)new %s(%s)));" % (function.arguments[-1].name, objectType, objectType[2:], argsStr)
+ else:
+ yield "\tVK_NULL_RETURN(*%s = reinterpret_cast<%s>(new %s(%s)));" % (function.arguments[-1].name, objectType, objectType[2:], argsStr)
+
+ yield "}"
+ yield ""
+
+ for function in destroyFuncs:
+ objectArg = function.arguments[-2]
+
+ yield "%s %s (%s)" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments))
+ yield "{"
+ for arg in function.arguments[:-2]:
+ yield "\tDE_UNREF(%s);" % arg.name
+ yield "\tDE_UNREF(%s);" % function.arguments[-1].name
+
+ if getHandle(objectArg.type).type == Handle.TYPE_NONDISP:
+ yield "\tdelete reinterpret_cast<%s*>((deUintptr)%s.getInternal());" % (objectArg.type[2:], objectArg.name)
+ else:
+ yield "\tdelete reinterpret_cast<%s*>(%s);" % (objectArg.type[2:], objectArg.name)
+
+ yield "}"
+ yield ""
+
+ for function in dummyFuncs:
+ yield "%s %s (%s)" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments))
+ yield "{"
+ for arg in function.arguments:
+ yield "\tDE_UNREF(%s);" % arg.name
+ if function.returnType != "void":
+ yield "\treturn VK_SUCCESS;"
+ yield "}"
+ yield ""
+
+ def genFuncEntryTable (type, name):
+ funcs = [f for f in api.functions if f.getType() == type]
+
+ yield "static const tcu::StaticFunctionLibrary::Entry %s[] =" % name
+ yield "{"
+ for line in indentLines(["\tVK_NULL_FUNC_ENTRY(%s,\t%s)," % (function.name, getInterfaceName(function)) for function in funcs]):
+ yield line
+ yield "};"
+ yield ""
+
+ # Func tables
+ for line in genFuncEntryTable(Function.TYPE_PLATFORM, "s_platformFunctions"):
+ yield line
+
+ for line in genFuncEntryTable(Function.TYPE_INSTANCE, "s_instanceFunctions"):
+ yield line
+
+ for line in genFuncEntryTable(Function.TYPE_DEVICE, "s_deviceFunctions"):
+ yield line
+
+
+ writeInlFile(filename, INL_HEADER, genNullDriverImpl())
+
+def writeTypeUtil (api, filename):
+ # Structs filled by API queries are not often used in test code
+ QUERY_RESULT_TYPES = set([
+ "VkPhysicalDeviceFeatures",
+ "VkPhysicalDeviceLimits",
+ "VkFormatProperties",
+ "VkImageFormatProperties",
+ "VkPhysicalDeviceSparseProperties",
+ "VkQueueFamilyProperties",
+ "VkMemoryType",
+ "VkMemoryHeap",
+ ])
+ COMPOSITE_TYPES = set([t.name for t in api.compositeTypes])
+
+ def isSimpleStruct (type):
+ def hasArrayMember (type):
+ for member in type.members:
+ if "[" in member.name:
+ return True
+ return False
+
+ def hasCompositeMember (type):
+ for member in type.members:
+ if member.type in COMPOSITE_TYPES:
+ return True
+ return False
+
+ return type.typeClass == CompositeType.CLASS_STRUCT and \
+ type.members[0].type != "VkStructureType" and \
+ not type.name in QUERY_RESULT_TYPES and \
+ not hasArrayMember(type) and \
+ not hasCompositeMember(type)
+
+ def gen ():
+ for type in api.compositeTypes:
+ if not isSimpleStruct(type):
+ continue
+
+ yield ""
+ yield "inline %s make%s (%s)" % (type.name, type.name[2:], argListToStr(type.members))
+ yield "{"
+ yield "\t%s res;" % type.name
+ for line in indentLines(["\tres.%s\t= %s;" % (m.name, m.name) for m in type.members]):
+ yield line
+ yield "\treturn res;"
+ yield "}"
+
+ writeInlFile(filename, INL_HEADER, gen())
+
+if __name__ == "__main__":
+ src = readFile(sys.argv[1])
+ api = parseAPI(src)
+ platformFuncs = set([Function.TYPE_PLATFORM])
+ instanceFuncs = set([Function.TYPE_INSTANCE])
+ deviceFuncs = set([Function.TYPE_DEVICE])
+
+ writeHandleType (api, os.path.join(VULKAN_DIR, "vkHandleType.inl"))
+ writeBasicTypes (api, os.path.join(VULKAN_DIR, "vkBasicTypes.inl"))
+ writeCompositeTypes (api, os.path.join(VULKAN_DIR, "vkStructTypes.inl"))
+ writeInterfaceDecl (api, os.path.join(VULKAN_DIR, "vkVirtualPlatformInterface.inl"), functionTypes = platformFuncs, concrete = False)
+ writeInterfaceDecl (api, os.path.join(VULKAN_DIR, "vkVirtualInstanceInterface.inl"), functionTypes = instanceFuncs, concrete = False)
+ writeInterfaceDecl (api, os.path.join(VULKAN_DIR, "vkVirtualDeviceInterface.inl"), functionTypes = deviceFuncs, concrete = False)
+ writeInterfaceDecl (api, os.path.join(VULKAN_DIR, "vkConcretePlatformInterface.inl"), functionTypes = platformFuncs, concrete = True)
+ writeInterfaceDecl (api, os.path.join(VULKAN_DIR, "vkConcreteInstanceInterface.inl"), functionTypes = instanceFuncs, concrete = True)
+ writeInterfaceDecl (api, os.path.join(VULKAN_DIR, "vkConcreteDeviceInterface.inl"), functionTypes = deviceFuncs, concrete = True)
+ writeFunctionPtrTypes (api, os.path.join(VULKAN_DIR, "vkFunctionPointerTypes.inl"))
+ writeFunctionPointers (api, os.path.join(VULKAN_DIR, "vkPlatformFunctionPointers.inl"), functionTypes = platformFuncs)
+ writeFunctionPointers (api, os.path.join(VULKAN_DIR, "vkInstanceFunctionPointers.inl"), functionTypes = instanceFuncs)
+ writeFunctionPointers (api, os.path.join(VULKAN_DIR, "vkDeviceFunctionPointers.inl"), functionTypes = deviceFuncs)
+ writeInitFunctionPointers (api, os.path.join(VULKAN_DIR, "vkInitPlatformFunctionPointers.inl"), functionTypes = platformFuncs)
+ writeInitFunctionPointers (api, os.path.join(VULKAN_DIR, "vkInitInstanceFunctionPointers.inl"), functionTypes = instanceFuncs)
+ writeInitFunctionPointers (api, os.path.join(VULKAN_DIR, "vkInitDeviceFunctionPointers.inl"), functionTypes = deviceFuncs)
+ writeFuncPtrInterfaceImpl (api, os.path.join(VULKAN_DIR, "vkPlatformDriverImpl.inl"), functionTypes = platformFuncs, className = "PlatformDriver")
+ writeFuncPtrInterfaceImpl (api, os.path.join(VULKAN_DIR, "vkInstanceDriverImpl.inl"), functionTypes = instanceFuncs, className = "InstanceDriver")
+ writeFuncPtrInterfaceImpl (api, os.path.join(VULKAN_DIR, "vkDeviceDriverImpl.inl"), functionTypes = deviceFuncs, className = "DeviceDriver")
+ writeStrUtilProto (api, os.path.join(VULKAN_DIR, "vkStrUtil.inl"))
+ writeStrUtilImpl (api, os.path.join(VULKAN_DIR, "vkStrUtilImpl.inl"))
+ writeRefUtilProto (api, os.path.join(VULKAN_DIR, "vkRefUtil.inl"))
+ writeRefUtilImpl (api, os.path.join(VULKAN_DIR, "vkRefUtilImpl.inl"))
+ writeNullDriverImpl (api, os.path.join(VULKAN_DIR, "vkNullDriverImpl.inl"))
+ writeTypeUtil (api, os.path.join(VULKAN_DIR, "vkTypeUtil.inl"))
--- /dev/null
+# dEQP-VK
+
+add_subdirectory(api)
+add_subdirectory(pipeline)
+add_subdirectory(binding_model)
+add_subdirectory(spirv_assembly)
+add_subdirectory(shaderrender)
+add_subdirectory(memory)
+
+include_directories(
+ api
+ pipeline
+ binding_model
+ spirv_assembly
+ shaderrender
+ memory
+ )
+
+set(DEQP_VK_COMMON_SRCS
+ vktTestCase.cpp
+ vktTestCase.hpp
+ vktTestCaseUtil.cpp
+ vktTestCaseUtil.hpp
+ vktTestPackage.cpp
+ vktTestPackage.hpp
+ vktInfo.cpp
+ vktInfo.hpp
+ vktShaderLibrary.cpp
+ vktShaderLibrary.hpp
+ vktRenderPassTests.cpp
+ vktRenderPassTests.hpp
+ )
+
+set(DEQP_VK_COMMON_LIBS
+ tcutil
+ vkutil
+ glutil
+ deqp-vk-api
+ deqp-vk-pipeline
+ deqp-vk-binding-model
+ deqp-vk-spirv-assembly
+ deqp-vk-shaderrender
+ deqp-vk-memory
+ )
+
+if (DE_OS_IS_WIN32 OR DE_OS_IS_UNIX OR DE_OS_IS_OSX)
+ add_library(deqp-vk-common STATIC ${DEQP_VK_COMMON_SRCS})
+ target_link_libraries(deqp-vk-common ${DEQP_VK_COMMON_LIBS})
+
+ add_executable(vk-build-programs vktBuildPrograms.cpp)
+ target_link_libraries(vk-build-programs deqp-vk-common)
+ add_dependencies(vk-build-programs deqp-vk-data)
+
+ set(DEQP_VK_SRCS )
+ set(DEQP_VK_LIBS deqp-vk-common)
+
+else ()
+ set(DEQP_VK_SRCS ${DEQP_VK_COMMON_SRCS})
+ set(DEQP_VK_LIBS ${DEQP_VK_COMMON_LIBS})
+
+endif ()
+
+add_deqp_module(deqp-vk "${DEQP_VK_SRCS}" "${DEQP_VK_LIBS}" vktTestPackageEntry.cpp)
+
+add_data_dir(deqp-vk ../../data/vulkan vulkan)
--- /dev/null
+# API layer tests
+
+include_directories(..)
+
+set(DEQP_VK_API_SRCS
+ vktApiTests.cpp
+ vktApiTests.hpp
+ vktApiSmokeTests.cpp
+ vktApiSmokeTests.hpp
+ vktApiDeviceInitializationTests.cpp
+ vktApiDeviceInitializationTests.hpp
+ vktApiObjectManagementTests.cpp
+ vktApiObjectManagementTests.hpp
+ vktApiBufferTests.cpp
+ vktApiBufferTests.hpp
+ vktApiBufferViewCreateTests.cpp
+ vktApiBufferViewCreateTests.hpp
+ vktApiBufferViewAccessTests.cpp
+ vktApiBufferViewAccessTests.hpp
+ )
+
+set(DEQP_VK_API_LIBS
+ tcutil
+ vkutil
+ )
+
+add_library(deqp-vk-api STATIC ${DEQP_VK_API_SRCS})
+target_link_libraries(deqp-vk-api ${DEQP_VK_API_LIBS})
--- /dev/null
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by Khronos,
+ * at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Vulkan Buffers Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktApiBufferTests.hpp"
+
+#include "deStringUtil.hpp"
+#include "gluVarType.hpp"
+#include "tcuTestLog.hpp"
+#include "vkPrograms.hpp"
+#include "vktTestCase.hpp"
+
+namespace vkt
+{
+
+using namespace vk;
+
+namespace api
+{
+
+namespace
+{
+
+struct BufferCaseParameters
+{
+ VkBufferUsageFlags usage;
+ VkBufferCreateFlags flags;
+ VkSharingMode sharingMode;
+};
+
+class BufferTestInstance : public TestInstance
+{
+public:
+ BufferTestInstance (Context& ctx,
+ BufferCaseParameters testCase)
+ : TestInstance (ctx)
+ , m_testCase (testCase)
+ {}
+ virtual tcu::TestStatus iterate (void);
+ tcu::TestStatus bufferCreateAndAllocTest (VkDeviceSize size);
+
+private:
+ BufferCaseParameters m_testCase;
+};
+
+class BuffersTestCase : public TestCase
+{
+public:
+ BuffersTestCase (tcu::TestContext& testCtx,
+ const std::string& name,
+ const std::string& description,
+ BufferCaseParameters testCase)
+ : TestCase(testCtx, name, description)
+ , m_testCase(testCase)
+ {}
+
+ virtual ~BuffersTestCase (void) {}
+ virtual TestInstance* createInstance (Context& ctx) const
+ {
+ tcu::TestLog& log = m_testCtx.getLog();
+ log << tcu::TestLog::Message << getBufferUsageFlagsStr(m_testCase.usage) << tcu::TestLog::EndMessage;
+ return new BufferTestInstance(ctx, m_testCase);
+ }
+
+private:
+ BufferCaseParameters m_testCase;
+};
+
+ tcu::TestStatus BufferTestInstance::bufferCreateAndAllocTest (VkDeviceSize size)
+{
+ const VkDevice vkDevice = m_context.getDevice();
+ const DeviceInterface& vk = m_context.getDeviceInterface();
+ VkBuffer testBuffer;
+ VkMemoryRequirements memReqs;
+ VkDeviceMemory memory;
+
+ // Create buffer
+ {
+ const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
+ const VkBufferCreateInfo bufferParams =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
+ DE_NULL,
+ m_testCase.flags,
+ size,
+ m_testCase.usage,
+ m_testCase.sharingMode,
+ 1u, // deUint32 queueFamilyCount;
+ &queueFamilyIndex,
+ };
+
+ if (vk.createBuffer(vkDevice, &bufferParams, (const VkAllocationCallbacks*)DE_NULL, &testBuffer) != VK_SUCCESS)
+ return tcu::TestStatus::fail("Buffer creation failed! (requested memory size: " + de::toString(size) + ")");
+
+ vk.getBufferMemoryRequirements(vkDevice, testBuffer, &memReqs);
+
+ if (size > memReqs.size)
+ {
+ std::ostringstream errorMsg;
+ errorMsg << "Requied memory size (" << memReqs.size << " bytes) smaller than the buffer's size (" << size << " bytes)!";
+ return tcu::TestStatus::fail(errorMsg.str());
+ }
+ }
+
+ // Allocate and bind memory
+ {
+ const VkMemoryAllocateInfo memAlloc =
+ {
+ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+ NULL,
+ memReqs.size,
+ 0 // deUint32 memoryTypeIndex
+ };
+
+ if (vk.allocateMemory(vkDevice, &memAlloc, (const VkAllocationCallbacks*)DE_NULL, &memory) != VK_SUCCESS)
+ return tcu::TestStatus::fail("Alloc memory failed! (requested memory size: " + de::toString(size) + ")");
+
+ if (vk.bindBufferMemory(vkDevice, testBuffer, memory, 0) != VK_SUCCESS)
+ return tcu::TestStatus::fail("Bind buffer memory failed! (requested memory size: " + de::toString(size) + ")");
+ }
+
+ vk.freeMemory(vkDevice, memory, (const VkAllocationCallbacks*)DE_NULL);
+ vk.destroyBuffer(vkDevice, testBuffer, (const VkAllocationCallbacks*)DE_NULL);
+
+ return tcu::TestStatus::pass("Buffer test");
+}
+
+tcu::TestStatus BufferTestInstance::iterate (void)
+{
+ const VkDeviceSize testSizes[] =
+ {
+ 0,
+ 1181,
+ 15991,
+ 16384
+ };
+ tcu::TestStatus testStatus = tcu::TestStatus::pass("Buffer test");
+
+ for (int i = 0; i < DE_LENGTH_OF_ARRAY(testSizes); i++)
+ {
+ if ((testStatus = bufferCreateAndAllocTest(testSizes[i])).getCode() != QP_TEST_RESULT_PASS)
+ return testStatus;
+ }
+
+ if (m_testCase.usage & (VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT))
+ {
+ const VkPhysicalDevice vkPhysicalDevice = m_context.getPhysicalDevice();
+ const InstanceInterface& vkInstance = m_context.getInstanceInterface();
+ VkPhysicalDeviceProperties props;
+
+ vkInstance.getPhysicalDeviceProperties(vkPhysicalDevice, &props);
+
+ testStatus = bufferCreateAndAllocTest(props.limits.maxTexelBufferElements);
+ }
+
+ return testStatus;
+}
+
+} // anonymous
+
+ tcu::TestCaseGroup* createBufferTests (tcu::TestContext& testCtx)
+{
+ const VkBufferUsageFlags bufferUsageModes[] =
+ {
+ VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
+ VK_BUFFER_USAGE_TRANSFER_DST_BIT,
+ VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT,
+ VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT,
+ VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
+ VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
+ VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
+ VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
+ VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT
+ };
+
+ const VkBufferCreateFlags bufferCreateFlags[] =
+ {
+ VK_BUFFER_CREATE_SPARSE_BINDING_BIT,
+ VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT,
+ VK_BUFFER_CREATE_SPARSE_ALIASED_BIT
+ };
+
+ de::MovePtr<tcu::TestCaseGroup> buffersTests (new tcu::TestCaseGroup(testCtx, "buffer", "Buffer Tests"));
+
+ deUint32 numberOfBufferUsageFlags = DE_LENGTH_OF_ARRAY(bufferUsageModes);
+ deUint32 numberOfBufferCreateFlags = DE_LENGTH_OF_ARRAY(bufferCreateFlags);
+ deUint32 maximumValueOfBufferUsageFlags = (1 << (numberOfBufferUsageFlags - 1)) - 1;
+ deUint32 maximumValueOfBufferCreateFlags = (1 << (numberOfBufferCreateFlags)) - 1;
+
+ for (deUint32 combinedBufferCreateFlags = 0; combinedBufferCreateFlags < maximumValueOfBufferCreateFlags; combinedBufferCreateFlags++)
+ {
+ for (deUint32 combinedBufferUsageFlags = 0; combinedBufferUsageFlags < maximumValueOfBufferUsageFlags; combinedBufferUsageFlags++)
+ {
+ BufferCaseParameters testParams =
+ {
+ combinedBufferUsageFlags,
+ combinedBufferCreateFlags,
+ VK_SHARING_MODE_EXCLUSIVE
+ };
+ std::ostringstream testName;
+ std::ostringstream testDescription;
+ testName << "createBuffer_" << combinedBufferUsageFlags << "_" << combinedBufferCreateFlags;
+ testDescription << "vkCreateBuffer test " << combinedBufferUsageFlags << " " << combinedBufferCreateFlags;
+ buffersTests->addChild(new BuffersTestCase(testCtx, testName.str(), testDescription.str(), testParams));
+ }
+ }
+
+ return buffersTests.release();
+}
+
+} // api
+} // vk
--- /dev/null
+#ifndef _VKTAPIBUFFERTESTS_HPP
+#define _VKTAPIBUFFERTESTS_HPP
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by Khronos,
+ * at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Vulkan Buffers Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+
+namespace api
+{
+
+tcu::TestCaseGroup* createBufferTests (tcu::TestContext& testCtx);
+
+} // api
+} // vkt
+
+#endif // _VKTAPIBUFFERTESTS_HPP
--- /dev/null
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by Khronos,
+ * at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Vulkan Buffer View Memory Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktApiBufferViewAccessTests.hpp"
+
+#include "deStringUtil.hpp"
+#include "deUniquePtr.hpp"
+#include "vktTestCase.hpp"
+#include "vktTestCaseUtil.hpp"
+#include "vkImageUtil.hpp"
+#include "vkMemUtil.hpp"
+#include "vkPrograms.hpp"
+#include "vkQueryUtil.hpp"
+#include "vkRef.hpp"
+#include "vkRefUtil.hpp"
+#include "vkTypeUtil.hpp"
+#include "tcuImageCompare.hpp"
+#include "tcuTexture.hpp"
+#include "tcuTextureUtil.hpp"
+
+namespace vkt
+{
+
+namespace api
+{
+
+using namespace vk;
+
+namespace
+{
+
+struct BufferViewCaseParams
+{
+ deUint32 bufferSize;
+ deUint32 bufferViewSize;
+ deUint32 elementOffset;
+ deUint32 offset;
+};
+
+class BufferViewTestInstance : public vkt::TestInstance
+{
+public:
+ BufferViewTestInstance (Context& context,
+ BufferViewCaseParams testCase);
+ virtual ~BufferViewTestInstance (void);
+ virtual tcu::TestStatus iterate (void);
+
+private:
+ void createQuad (void);
+ tcu::TestStatus checkResult (deInt8 factor = 1);
+
+private:
+ BufferViewCaseParams m_testCase;
+
+ const tcu::IVec2 m_renderSize;
+ const VkFormat m_colorFormat;
+
+ const VkDeviceSize m_pixelDataSize;
+
+ Move<VkImage> m_colorImage;
+ de::MovePtr<Allocation> m_colorImageAlloc;
+ Move<VkImageView> m_colorAttachmentView;
+ Move<VkRenderPass> m_renderPass;
+ Move<VkFramebuffer> m_framebuffer;
+
+ Move<VkDescriptorSetLayout> m_descriptorSetLayout;
+ Move<VkDescriptorPool> m_descriptorPool;
+ Move<VkDescriptorSet> m_descriptorSet;
+
+ Move<VkBuffer> m_uniformBuffer;
+ de::MovePtr<vk::Allocation> m_uniformBufferAlloc;
+ Move<VkBufferView> m_uniformBufferView;
+
+ Move<VkShaderModule> m_vertexShaderModule;
+ Move<VkShaderModule> m_fragmentShaderModule;
+
+ Move<VkBuffer> m_vertexBuffer;
+ std::vector<tcu::Vec4> m_vertices;
+ de::MovePtr<Allocation> m_vertexBufferAlloc;
+
+ Move<VkPipelineLayout> m_pipelineLayout;
+ Move<VkPipeline> m_graphicsPipelines;
+
+ Move<VkCommandPool> m_cmdPool;
+ Move<VkCommandBuffer> m_cmdBuffer;
+
+ Move<VkBuffer> m_resultBuffer;
+ de::MovePtr<Allocation> m_resultBufferAlloc;
+
+ Move<VkFence> m_fence;
+};
+
+static void generateBuffer (std::vector<tcu::IVec4>& uniformData, deUint32 bufferSize, deInt8 factor = 1)
+{
+ for (deUint32 i = 0; i < bufferSize; ++i)
+ uniformData.push_back(tcu::IVec4(factor * i, factor * (i + 1), factor * (i + 2), factor * (i + 3)));
+}
+
+void BufferViewTestInstance::createQuad (void)
+{
+ tcu::Vec4 a(-1.0, -1.0, 0.0, 1.0);
+ tcu::Vec4 b(1.0, -1.0, 0.0, 1.0);
+ tcu::Vec4 c(1.0, 1.0, 0.0, 1.0);
+ tcu::Vec4 d(-1.0, 1.0, 0.0, 1.0);
+
+ // Triangle 1
+ m_vertices.push_back(a);
+ m_vertices.push_back(c);
+ m_vertices.push_back(b);
+
+ // Triangle 2
+ m_vertices.push_back(c);
+ m_vertices.push_back(a);
+ m_vertices.push_back(d);
+}
+
+BufferViewTestInstance::~BufferViewTestInstance (void)
+{
+}
+
+BufferViewTestInstance::BufferViewTestInstance (Context& context, BufferViewCaseParams testCase)
+ : vkt::TestInstance (context)
+ , m_testCase (testCase)
+ , m_renderSize (testCase.bufferViewSize, testCase.bufferViewSize)
+ , m_colorFormat (VK_FORMAT_R32_UINT)
+ , m_pixelDataSize (m_renderSize.x() * m_renderSize.y() * mapVkFormat(m_colorFormat).getPixelSize())
+{
+ const DeviceInterface& vk = context.getDeviceInterface();
+ const VkDevice vkDevice = context.getDevice();
+ const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
+ SimpleAllocator memAlloc (vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
+ const VkComponentMapping channelMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
+
+ // Create color image
+ {
+ const VkImageCreateInfo colorImageParams =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkImageCreateFlags flags;
+ VK_IMAGE_TYPE_2D, // VkImageType imageType;
+ m_colorFormat, // VkFormat format;
+ { m_renderSize.x(), m_renderSize.y(), 1u }, // VkExtent3D extent;
+ 1u, // deUint32 mipLevels;
+ 1u, // deUint32 arraySize;
+ VK_SAMPLE_COUNT_1_BIT, // deUint32 samples;
+ VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
+ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
+ VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
+ 1u, // deUint32 queueFamilyCount;
+ &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout;
+ };
+
+ m_colorImage = createImage(vk, vkDevice, &colorImageParams);
+
+ // Allocate and bind color image memory
+ m_colorImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
+ VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
+ }
+
+ // Create destination buffer
+ {
+ const VkBufferCreateInfo bufferParams =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkBufferCreateFlags flags;
+ m_pixelDataSize, // VkDeviceSize size;
+ VK_BUFFER_USAGE_TRANSFER_DST_BIT, // VkBufferUsageFlags usage;
+ VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
+ 0u, // deUint32 queueFamilyCount;
+ DE_NULL, // const deUint32* pQueueFamilyIndices;
+ };
+
+ m_resultBuffer = createBuffer(vk, vkDevice, &bufferParams);
+ m_resultBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_resultBuffer), MemoryRequirement::HostVisible);
+
+ VK_CHECK(vk.bindBufferMemory(vkDevice, *m_resultBuffer, m_resultBufferAlloc->getMemory(), m_resultBufferAlloc->getOffset()));
+ }
+
+ // Create color attachment view
+ {
+ const VkImageViewCreateInfo colorAttachmentViewParams =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkImageViewCreateFlags flags;
+ *m_colorImage, // VkImage image;
+ VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
+ m_colorFormat, // VkFormat format;
+ channelMappingRGBA, // VkChannelMapping channels;
+ { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }, // VkImageSubresourceRange subresourceRange;
+ };
+
+ m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
+ }
+
+ // Create render pass
+ {
+ const VkAttachmentDescription colorAttachmentDescription =
+ {
+ 0u, // VkAttachmentDescriptionFlags flags;
+ m_colorFormat, // VkFormat format;
+ VK_SAMPLE_COUNT_1_BIT, // deUint32 samples;
+ VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
+ VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
+ VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
+ VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout;
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
+ };
+
+ const VkAttachmentReference colorAttachmentReference =
+ {
+ 0u, // deUint32 attachment;
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
+ };
+
+ const VkSubpassDescription subpassDescription =
+ {
+ 0u, // VkSubpassDescriptionFlags flags;
+ VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
+ 0u, // deUint32 inputCount;
+ DE_NULL, // const VkAttachmentReference* pInputAttachments;
+ 1u, // deUint32 colorCount;
+ &colorAttachmentReference, // const VkAttachmentReference* pColorAttachments;
+ DE_NULL, // const VkAttachmentReference* pResolveAttachments;
+ DE_NULL, // VkAttachmentReference depthStencilAttachment;
+ 0u, // deUint32 preserveCount;
+ DE_NULL // const VkAttachmentReference* pPreserveAttachments;
+ };
+
+ const VkRenderPassCreateInfo renderPassParams =
+ {
+ VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkRenderPassCreateFlags)0,
+ 1u, // deUint32 attachmentCount;
+ &colorAttachmentDescription, // const VkAttachmentDescription* pAttachments;
+ 1u, // deUint32 subpassCount;
+ &subpassDescription, // const VkSubpassDescription* pSubpasses;
+ 0u, // deUint32 dependencyCount;
+ DE_NULL // const VkSubpassDependency* pDependencies;
+ };
+
+ m_renderPass = createRenderPass(vk, vkDevice, &renderPassParams);
+ }
+
+ // Create framebuffer
+ {
+ const VkImageView attachmentBindInfos[1] =
+ {
+ *m_colorAttachmentView,
+ };
+
+ const VkFramebufferCreateInfo framebufferParams =
+ {
+ VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkFramebufferCreateFlags)0,
+ *m_renderPass, // VkRenderPass renderPass;
+ 1u, // deUint32 attachmentCount;
+ attachmentBindInfos, // const VkImageView* pAttachments;
+ (deUint32)m_renderSize.x(), // deUint32 width;
+ (deUint32)m_renderSize.y(), // deUint32 height;
+ 1u // deUint32 layers;
+ };
+
+ m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
+ }
+
+ // Create descriptors
+ {
+ const VkDescriptorSetLayoutBinding layoutBindings[1] =
+ {
+ {
+ 0u, // deUint32 binding;
+ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, // VkDescriptorType descriptorType;
+ 1u, // deUint32 arraySize;
+ VK_SHADER_STAGE_ALL, // VkShaderStageFlags stageFlags;
+ DE_NULL // const VkSampler* pImmutableSamplers;
+ },
+ };
+
+ const VkDescriptorSetLayoutCreateInfo descriptorLayoutParams =
+ {
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // cost void* pNexŧ;
+ (VkDescriptorSetLayoutCreateFlags)0,
+ DE_LENGTH_OF_ARRAY(layoutBindings), // deUint32 count;
+ layoutBindings // const VkDescriptorSetLayoutBinding pBinding;
+ };
+
+ m_descriptorSetLayout = createDescriptorSetLayout(vk, vkDevice, &descriptorLayoutParams);
+
+ // Generate buffer
+ std::vector<tcu::IVec4> uniformData;
+ generateBuffer(uniformData, testCase.bufferSize);
+
+ const VkDeviceSize uniformSize = testCase.bufferSize * sizeof(tcu::Vec4);
+ const VkBufferCreateInfo uniformBufferParams =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkBufferCreateFlags flags; <-- TODO: 0u?
+ uniformSize, // VkDeviceSize size;
+ VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, // VkBufferUsageFlags usage;
+ VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
+ 1u, // deUint32 queueFamilyIndexCount;
+ &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
+ };
+
+ m_uniformBuffer = createBuffer(vk, vkDevice, &uniformBufferParams);
+ m_uniformBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_uniformBuffer), MemoryRequirement::HostVisible);
+
+ VK_CHECK(vk.bindBufferMemory(vkDevice, *m_uniformBuffer, m_uniformBufferAlloc->getMemory(), 0));
+ deMemcpy(m_uniformBufferAlloc->getHostPtr(), uniformData.data(), uniformSize);
+
+ const VkBufferViewCreateInfo viewInfo =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // void* pNext;
+ (VkBufferViewCreateFlags)0,
+ *m_uniformBuffer, // VkBuffer buffer;
+ m_colorFormat, // VkFormat format;
+ m_testCase.elementOffset * sizeof(tcu::IVec4) + m_testCase.offset, // VkDeviceSize offset;
+ m_testCase.bufferViewSize * sizeof(tcu::IVec4) // VkDeviceSize range;
+ };
+
+ m_uniformBufferView = createBufferView(vk, vkDevice, &viewInfo);
+
+ const VkDescriptorPoolSize descriptorTypes[1] =
+ {
+ {
+ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, // VkDescriptorType type;
+ 1 // deUint32 count;
+ }
+ };
+
+ const VkDescriptorPoolCreateInfo descriptorPoolParams =
+ {
+ VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // void* pNext;
+ VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, // VkDescriptorPoolCreateFlags flags;
+ 1u, // uint32_t maxSets;
+ DE_LENGTH_OF_ARRAY(descriptorTypes), // deUint32 count;
+ descriptorTypes // const VkDescriptorTypeCount* pTypeCount
+ };
+
+ m_descriptorPool = createDescriptorPool(vk, vkDevice, &descriptorPoolParams);
+
+ const VkDescriptorSetAllocateInfo descriptorSetParams =
+ {
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+ DE_NULL,
+ *m_descriptorPool,
+ 1u,
+ &m_descriptorSetLayout.get(),
+ };
+ m_descriptorSet = allocateDescriptorSet(vk, vkDevice, &descriptorSetParams);
+
+ const VkWriteDescriptorSet writeDescritporSets[] =
+ {
+ {
+ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ *m_descriptorSet, // VkDescriptorSet destSet;
+ 0, // deUint32 destBinding;
+ 0, // deUint32 destArrayElement;
+ 1u, // deUint32 count;
+ VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, // VkDescriptorType descriptorType;
+ (const VkDescriptorImageInfo*)DE_NULL,
+ (const VkDescriptorBufferInfo*)DE_NULL,
+ &m_uniformBufferView.get(),
+ }
+ };
+
+ vk.updateDescriptorSets(vkDevice, DE_LENGTH_OF_ARRAY(writeDescritporSets), writeDescritporSets, 0u, DE_NULL);
+ }
+
+ // Create pipeline layout
+ {
+ const VkPipelineLayoutCreateInfo pipelineLayoutParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkPipelineLayoutCreateFlags)0,
+ 1u, // deUint32 descriptorSetCount;
+ &*m_descriptorSetLayout, // const VkDescriptorSetLayout* pSetLayouts;
+ 0u, // deUint32 pushConstantRangeCount;
+ DE_NULL // const VkPushConstantRange* pPushConstantRanges;
+ };
+
+ m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
+ }
+
+ // Create shaders
+ {
+ m_vertexShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("vert"), 0);
+ m_fragmentShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("frag"), 0);
+ }
+
+ // Create pipeline
+ {
+
+ const VkPipelineShaderStageCreateInfo shaderStageParams[2] =
+ {
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkPipelineShaderStageCreateFlags)0,
+ VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStage stage;
+ *m_vertexShaderModule, // VkShader shader;
+ "main",
+ DE_NULL // const VkSpecializationInfo* pSpecializationInfo;
+ },
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkPipelineShaderStageCreateFlags)0,
+ VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStage stage;
+ *m_fragmentShaderModule, // VkShader shader;
+ "main",
+ DE_NULL // const VkSpecializationInfo* pSpecializationInfo;
+ }
+ };
+
+ const VkVertexInputBindingDescription vertexInputBindingDescription =
+ {
+ 0u, // deUint32 binding;
+ sizeof(tcu::Vec4), // deUint32 strideInBytes;
+ VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate stepRate;
+ };
+
+ const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[1] =
+ {
+ {
+ 0u, // deUint32 location;
+ 0u, // deUint32 binding;
+ VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
+ 0u // deUint32 offsetInBytes;
+ }
+ };
+
+ const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkPipelineVertexInputStateCreateFlags)0,
+ 1u, // deUint32 bindingCount;
+ &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
+ 1u, // deUint32 attributeCount;
+ vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
+ };
+
+ const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkPipelineInputAssemblyStateCreateFlags)0,
+ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology topology;
+ false // VkBool32 primitiveRestartEnable;
+ };
+
+ const VkViewport viewport =
+ {
+ 0.0f, // float originX;
+ 0.0f, // float originY;
+ (float)m_renderSize.x(), // float width;
+ (float)m_renderSize.y(), // float height;
+ 0.0f, // float minDepth;
+ 1.0f // float maxDepth;
+ };
+ const VkRect2D scissor =
+ {
+ { 0, 0 }, // VkOffset2D offset;
+ { m_renderSize.x(), m_renderSize.y() } // VkExtent2D extent;
+ };
+ const VkPipelineViewportStateCreateInfo viewportStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkPipelineViewportStateCreateFlags)0,
+ 1u, // deUint32 viewportCount;
+ &viewport, // const VkViewport* pViewports;
+ 1u, // deUint32 scissorCount;
+ &scissor // const VkRect2D* pScissors;
+ };
+
+ const VkPipelineRasterizationStateCreateInfo rasterStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkPipelineRasterizationStateCreateFlags)0,
+ false, // VkBool32 depthClipEnable;
+ false, // VkBool32 rasterizerDiscardEnable;
+ VK_POLYGON_MODE_FILL, // VkFillMode fillMode;
+ VK_CULL_MODE_NONE, // VkCullMode cullMode;
+ VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
+ VK_FALSE, // VkBool32 depthBiasEnable;
+ 0.0f, // float depthBias;
+ 0.0f, // float depthBiasClamp;
+ 0.0f, // float slopeScaledDepthBias;
+ 1.0f, // float lineWidth;
+ };
+
+ const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
+ {
+ false, // VkBool32 blendEnable;
+ VK_BLEND_FACTOR_ONE, // VkBlend srcBlendColor;
+ VK_BLEND_FACTOR_ZERO, // VkBlend destBlendColor;
+ VK_BLEND_OP_ADD, // VkBlendOp blendOpColor;
+ VK_BLEND_FACTOR_ONE, // VkBlend srcBlendAlpha;
+ VK_BLEND_FACTOR_ZERO, // VkBlend destBlendAlpha;
+ VK_BLEND_OP_ADD, // VkBlendOp blendOpAlpha;
+ (VK_COLOR_COMPONENT_R_BIT |
+ VK_COLOR_COMPONENT_G_BIT |
+ VK_COLOR_COMPONENT_B_BIT |
+ VK_COLOR_COMPONENT_A_BIT) // VkChannelFlags channelWriteMask;
+ };
+
+ const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkPipelineColorBlendStateCreateFlags)0,
+ false, // VkBool32 logicOpEnable;
+ VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
+ 1u, // deUint32 attachmentCount;
+ &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
+ { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConst[4];
+ };
+
+ const VkPipelineDynamicStateCreateInfo dynamicStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkPipelineDynamicStateCreateFlags)0,
+ 0u, // deUint32 dynamicStateCount;
+ DE_NULL // const VkDynamicState* pDynamicStates;
+ };
+
+ const VkGraphicsPipelineCreateInfo graphicsPipelineParams =
+ {
+ VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineCreateFlags flags;
+ 2u, // deUint32 stageCount;
+ shaderStageParams, // const VkPipelineShaderStageCreateInfo* pStages;
+ &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
+ &inputAssemblyStateParams, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
+ DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
+ &viewportStateParams, // const VkPipelineViewportStateCreateInfo* pViewportState;
+ &rasterStateParams, // const VkPipelineRasterStateCreateInfo* pRasterState;
+ DE_NULL, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
+ DE_NULL, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
+ &colorBlendStateParams, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
+ &dynamicStateParams, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
+ *m_pipelineLayout, // VkPipelineLayout layout;
+ *m_renderPass, // VkRenderPass renderPass;
+ 0u, // deUint32 subpass;
+ 0u, // VkPipeline basePipelineHandle;
+ 0u // deInt32 basePipelineIndex;
+ };
+
+ m_graphicsPipelines = createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams);
+ }
+
+ // Create vertex buffer
+ {
+ createQuad();
+ const VkDeviceSize vertexDataSize = m_vertices.size() * sizeof(tcu::Vec4);
+ const VkBufferCreateInfo vertexBufferParams =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkBufferCreateFlags flags;
+ vertexDataSize, // VkDeviceSize size;
+ VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
+ VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
+ 1u, // deUint32 queueFamilyCount;
+ &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
+ };
+
+ m_vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams);
+ m_vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
+
+ VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
+
+ // Load vertices into vertex buffer
+ deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), vertexDataSize);
+ flushMappedMemoryRange(vk, vkDevice, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset(), vertexDataSize);
+ }
+
+ // Create command pool
+ {
+ const VkCommandPoolCreateInfo cmdPoolParams =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // VkCmdPoolCreateFlags flags;
+ queueFamilyIndex, // deUint32 queueFamilyIndex;
+ };
+
+ m_cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams);
+ }
+
+ // Create command buffer
+ {
+ const VkCommandBufferAllocateInfo cmdBufferParams =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ *m_cmdPool, // VkCmdPool cmdPool;
+ VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCmdBufferLevel level;
+ 1u // deUint32 count;
+ };
+
+ const VkCommandBufferBeginInfo cmdBufferBeginInfo =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkCmdBufferOptimizeFlags flags;
+ DE_NULL, // VkRenderPass renderPass;
+ 0u, // deUint32 subpass;
+ DE_NULL, // VkFramebuffer framebuffer;
+ VK_FALSE,
+ (VkQueryControlFlags)0,
+ (VkQueryPipelineStatisticFlags)0,
+ };
+
+ const VkClearValue clearValue = makeClearValueColorF32(0.0, 0.0, 0.0, 0.0);
+
+ const VkClearValue attachmentClearValues[1] =
+ {
+ clearValue,
+ };
+
+ const VkRenderPassBeginInfo renderPassBeginInfo =
+ {
+ VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ *m_renderPass, // VkRenderPass renderPass;
+ *m_framebuffer, // VkFramebuffer framebuffer;
+ { { 0, 0 }, { m_renderSize.x(), m_renderSize.y() } }, // VkRect2D renderArea;
+ 1u, // deUint32 clearValueCount;
+ attachmentClearValues // const VkClearValue* pClearValues;
+ };
+
+ m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferParams);
+
+ VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
+ vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
+
+ const VkDeviceSize vertexBufferOffset[1] = { 0 };
+
+ vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelines);
+ vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1, &*m_descriptorSet, 0u, DE_NULL);
+ vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), vertexBufferOffset);
+ vk.cmdDraw(*m_cmdBuffer, (deUint32)m_vertices.size(), 1, 0, 0);
+
+ const VkImageMemoryBarrier imageBarrier =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkMemoryOutputFlags outputMask;
+ VK_ACCESS_TRANSFER_READ_BIT, // VkMemoryInputFlags inputMask;
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout;
+ VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
+ VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
+ *m_colorImage, // VkImage image;
+ { // VkImageSubresourceRange subresourceRange;
+ VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
+ 0u, // deUint32 baseMipLevel;
+ 1u, // deUint32 mipLevels;
+ 0u, // deUint32 baseArraySlice;
+ 1u // deUint32 arraySize;
+ }
+ };
+
+ const VkBufferMemoryBarrier bufferBarrier =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ VK_ACCESS_TRANSFER_WRITE_BIT, // VkMemoryOutputFlags outputMask;
+ VK_ACCESS_HOST_READ_BIT, // VkMemoryInputFlags inputMask;
+ VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
+ VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
+ *m_resultBuffer, // VkBuffer buffer;
+ 0u, // VkDeviceSize offset;
+ m_pixelDataSize // VkDeviceSize size;
+ };
+
+ const VkBufferImageCopy copyRegion =
+ {
+ 0u, // VkDeviceSize bufferOffset;
+ (deUint32)m_renderSize.x(), // deUint32 bufferRowLength;
+ (deUint32)m_renderSize.y(), // deUint32 bufferImageHeight;
+ { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u }, // VkImageSubresourceCopy imageSubresource;
+ { 0, 0, 0 }, // VkOffset3D imageOffset;
+ { m_renderSize.x(), m_renderSize.y(), 1 } // VkExtent3D imageExtent;
+ };
+
+ const void* const imageBarrierPtr = &imageBarrier;
+ const void* const bufferBarrierPtr = &bufferBarrier;
+
+ vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_FALSE, 1, &imageBarrierPtr);
+ vk.cmdCopyImageToBuffer(*m_cmdBuffer, *m_colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *m_resultBuffer, 1, ©Region);
+ vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_FALSE, 1, &bufferBarrierPtr);
+
+ vk.cmdEndRenderPass(*m_cmdBuffer);
+ VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
+ }
+
+ // Create fence
+ {
+ const VkFenceCreateInfo fenceParams =
+ {
+ VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u // VkFenceCreateFlags flags;
+ };
+
+ m_fence = createFence(vk, vkDevice, &fenceParams);
+ }
+}
+
+tcu::TestStatus BufferViewTestInstance::checkResult (deInt8 factor)
+{
+ const DeviceInterface& vk = m_context.getDeviceInterface();
+ const VkDevice vkDevice = m_context.getDevice();
+ const tcu::TextureFormat tcuFormat = mapVkFormat(m_colorFormat);
+ de::MovePtr<tcu::TextureLevel> resultLevel (new tcu::TextureLevel(tcuFormat, m_renderSize.x(), m_renderSize.y()));
+
+ invalidateMappedMemoryRange(vk, vkDevice, m_resultBufferAlloc->getMemory(), m_resultBufferAlloc->getOffset(), m_pixelDataSize);
+ tcu::copy(*resultLevel, tcu::ConstPixelBufferAccess(resultLevel->getFormat(), resultLevel->getSize(), m_resultBufferAlloc->getHostPtr()));
+
+ tcu::ConstPixelBufferAccess pixelBuffer = resultLevel->getAccess();
+ for (deInt32 i = 0; i < (deInt32) m_renderSize.x(); ++i)
+ {
+ tcu::IVec4 pixel = pixelBuffer.getPixelInt(i, i);
+ deInt32 expected = factor * (m_testCase.elementOffset + i + (m_testCase.offset / 4) % 4);
+ deInt32 actual = pixel[0];
+ if (expected != actual)
+ {
+ std::ostringstream errorMessage;
+ errorMessage << "BufferView test failed. expected: " << expected << " actual: " << actual;
+ return tcu::TestStatus::fail(errorMessage.str());
+ }
+ }
+
+ return tcu::TestStatus::pass("BufferView test");
+}
+
+tcu::TestStatus BufferViewTestInstance::iterate (void)
+{
+ const DeviceInterface& vk = m_context.getDeviceInterface();
+ const VkDevice vkDevice = m_context.getDevice();
+ const VkQueue queue = m_context.getUniversalQueue();
+ const VkSubmitInfo submitInfo =
+ {
+ VK_STRUCTURE_TYPE_SUBMIT_INFO,
+ DE_NULL,
+ 0u,
+ (const VkSemaphore*)DE_NULL,
+ 1u,
+ &m_cmdBuffer.get(),
+ 0u,
+ (const VkSemaphore*)DE_NULL,
+ };
+
+ VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
+ VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
+ VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity */));
+
+ tcu::TestStatus testStatus = checkResult();
+ if (testStatus.getCode() != QP_TEST_RESULT_PASS)
+ {
+ return testStatus;
+ }
+
+ // Generate and bind another buffer
+ std::vector<tcu::IVec4> uniformData;
+ const VkDeviceSize uniformSize = m_testCase.bufferSize * sizeof(tcu::Vec4);
+ const deInt8 factor = 2;
+
+ generateBuffer(uniformData, m_testCase.bufferSize, factor);
+ deMemcpy(m_uniformBufferAlloc->getHostPtr(), uniformData.data(), uniformSize);
+
+ VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
+ VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
+ VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity */));
+
+ return checkResult(factor);
+}
+
+class BufferViewTestCase : public vkt::TestCase
+{
+public:
+ BufferViewTestCase (tcu::TestContext& testCtx,
+ const std::string& name,
+ const std::string& description,
+ BufferViewCaseParams bufferViewTestInfo)
+ : vkt::TestCase (testCtx, name, description)
+ , m_bufferViewTestInfo (bufferViewTestInfo)
+ {}
+
+ virtual ~BufferViewTestCase (void) {}
+ virtual void initPrograms (SourceCollections& programCollection) const;
+
+ virtual TestInstance* createInstance (Context& context) const
+ {
+ return new BufferViewTestInstance(context, m_bufferViewTestInfo);
+ }
+private:
+ BufferViewCaseParams m_bufferViewTestInfo;
+};
+
+void BufferViewTestCase::initPrograms (SourceCollections& programCollection) const
+{
+ programCollection.glslSources.add("vert") << glu::VertexSource(
+ "#version 310 es\n"
+ "layout (location = 0) in highp vec4 a_position;\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = a_position;\n"
+ "}\n");
+
+
+ programCollection.glslSources.add("frag") << glu::FragmentSource(
+ "#version 310 es\n"
+ "layout (set=0, binding=0) uniform u_buffer {\n"
+ " highp uint item[" + de::toString(m_bufferViewTestInfo.bufferViewSize) + "];\n"
+ "};\n"
+ "layout (location = 0) out highp uint o_color;\n"
+ "void main()\n"
+ "{\n"
+ " o_color = item[int(gl_FragCoord.x)];\n"
+ "}\n");
+}
+
+} // anonymous
+
+tcu::TestCaseGroup* createBufferViewAccessTests (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> bufferViewTests (new tcu::TestCaseGroup(testCtx, "access", "BufferView Access Tests"));
+
+ {
+ BufferViewCaseParams info =
+ {
+ 512, // deUint32 bufferSize
+ 512, // deUint32 bufferViewSize
+ 0, // deUint32 elementOffset
+ 0, // deUint32 offset
+ };
+ std::ostringstream description;
+ description << "bufferSize: " << info.bufferSize << " bufferViewSize: " << " bufferView element offset: " << info.elementOffset << " offset: " << info.offset;
+ bufferViewTests->addChild(new BufferViewTestCase(testCtx, "buffer_view_memory_test_complete", description.str(), info));
+ }
+
+ {
+ BufferViewCaseParams info =
+ {
+ 4096, // deUint32 bufferSize
+ 512, // deUint32 bufferViewSize
+ 0, // deUint32 elementOffset
+ 0, // deUint32 offset
+ };
+ std::ostringstream description;
+ description << "bufferSize: " << info.bufferSize << " bufferViewSize: " << " bufferView element offset: " << info.elementOffset << " offset: " << info.offset;
+ bufferViewTests->addChild(new BufferViewTestCase(testCtx, "buffer_view_memory_test_partial_offset0", description.str(), info));
+ }
+
+ {
+ BufferViewCaseParams info =
+ {
+ 4096, // deUint32 bufferSize
+ 512, // deUint32 bufferViewSize
+ 128, // deUint32 elementOffset
+ 0, // deUint32 offset
+ };
+ std::ostringstream description;
+ description << "bufferSize: " << info.bufferSize << " bufferViewSize: " << " bufferView element offset: " << info.elementOffset << " offset: " << info.offset;
+ bufferViewTests->addChild(new BufferViewTestCase(testCtx, "buffer_view_memory_test_partial_offset1", description.str(), info));
+ }
+
+ {
+ BufferViewCaseParams info =
+ {
+ 4096, // deUint32 bufferSize
+ 512, // deUint32 bufferViewSize
+ 128, // deUint32 elementOffset
+ 4, // deUint32 offset
+ };
+ std::ostringstream description;
+ description << "bufferSize: " << info.bufferSize << " bufferViewSize: " << " bufferView element offset: " << info.elementOffset << " offset: " << info.offset;
+ bufferViewTests->addChild(new BufferViewTestCase(testCtx, "buffer_view_memory_test_partial_offset2", description.str(), info));
+ }
+
+ return bufferViewTests.release();
+}
+
+} // api
+} // vkt
--- /dev/null
+#ifndef _VKTAPIBUFFERVIEWACCESSTESTS_HPP
+#define _VKTAPIBUFFERVIEWACCESSTESTS_HPP
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by Khronos,
+ * at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Vulkan Buffer View Memory Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+
+namespace api
+{
+
+tcu::TestCaseGroup* createBufferViewAccessTests (tcu::TestContext& testCtx);
+
+} // api
+} // vkt
+
+#endif // _VKTAPIBUFFERVIEWACCESSTESTS_HPP
--- /dev/null
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by Khronos,
+ * at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Vulkan Buffer View Creation Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktApiBufferViewCreateTests.hpp"
+
+#include "deStringUtil.hpp"
+#include "gluVarType.hpp"
+#include "tcuTestLog.hpp"
+#include "vkPrograms.hpp"
+#include "vktTestCase.hpp"
+
+namespace vkt
+{
+
+using namespace vk;
+
+namespace api
+{
+
+namespace
+{
+
+struct BufferViewCaseParameters
+{
+ VkFormat format;
+ VkDeviceSize offset;
+ VkDeviceSize range;
+ VkBufferUsageFlags usage;
+ bool beforeAllocateMemory;
+};
+
+class BufferViewTestInstance : public TestInstance
+{
+public:
+ BufferViewTestInstance (Context& ctx,
+ BufferViewCaseParameters createInfo)
+ : TestInstance (ctx)
+ , m_testCase (createInfo)
+ {}
+ virtual tcu::TestStatus iterate (void);
+
+private:
+ BufferViewCaseParameters m_testCase;
+};
+
+class BufferViewTestCase : public TestCase
+{
+public:
+ BufferViewTestCase (tcu::TestContext& testCtx,
+ const std::string& name,
+ const std::string& description,
+ BufferViewCaseParameters createInfo)
+ : TestCase (testCtx, name, description)
+ , m_testCase (createInfo)
+ {}
+
+ virtual ~BufferViewTestCase (void) {}
+ virtual TestInstance* createInstance (Context& ctx) const
+ {
+ return new BufferViewTestInstance(ctx, m_testCase);
+ }
+
+private:
+ BufferViewCaseParameters m_testCase;
+};
+
+tcu::TestStatus BufferViewTestInstance::iterate (void)
+{
+ // Create buffer
+ const VkDevice vkDevice = m_context.getDevice();
+ const DeviceInterface& vk = m_context.getDeviceInterface();
+ const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
+ const VkDeviceSize size = 16 * 1024;
+ VkBuffer testBuffer;
+ VkMemoryRequirements memReqs;
+ const VkBufferCreateInfo bufferParams =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ VK_BUFFER_CREATE_SPARSE_BINDING_BIT, // VkBufferCreateFlags flags;
+ size, // VkDeviceSize size;
+ m_testCase.usage, // VkBufferUsageFlags usage;
+ VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
+ 1u, // deUint32 queueFamilyCount;
+ &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
+ };
+
+ if (vk.createBuffer(vkDevice, &bufferParams, (const VkAllocationCallbacks*)DE_NULL, &testBuffer) != VK_SUCCESS)
+ return tcu::TestStatus::fail("Buffer creation failed!");
+
+ vk.getBufferMemoryRequirements(vkDevice, testBuffer, &memReqs);
+
+ if (size > memReqs.size)
+ {
+ std::ostringstream errorMsg;
+ errorMsg << "Requied memory size (" << memReqs.size << " bytes) smaller than the buffer's size (" << size << " bytes)!";
+ return tcu::TestStatus::fail(errorMsg.str());
+ }
+
+ VkDeviceMemory memory;
+ const VkMemoryAllocateInfo memAlloc =
+ {
+ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType
+ NULL, // const void* pNext
+ memReqs.size, // VkDeviceSize allocationSize
+ 0 // deUint32 memoryTypeIndex
+ };
+
+ {
+ // Testing before attached memory to buffer.
+ if (m_testCase.beforeAllocateMemory)
+ {
+ if (vk.allocateMemory(vkDevice, &memAlloc, (const VkAllocationCallbacks*)DE_NULL, &memory) != VK_SUCCESS)
+ return tcu::TestStatus::fail("Alloc memory failed!");
+
+ if (vk.bindBufferMemory(vkDevice, testBuffer, memory, 0) != VK_SUCCESS)
+ return tcu::TestStatus::fail("Bind buffer memory failed!");
+ }
+
+ // Create buffer view.
+ VkBufferView bufferView;
+ const VkBufferViewCreateInfo bufferViewCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO, // VkStructureType sType;
+ NULL, // const void* pNext;
+ (VkBufferViewCreateFlags)0,
+ testBuffer, // VkBuffer buffer;
+ m_testCase.format, // VkFormat format;
+ m_testCase.offset, // VkDeviceSize offset;
+ m_testCase.range, // VkDeviceSize range;
+ };
+
+ if (vk.createBufferView(vkDevice, &bufferViewCreateInfo, (const VkAllocationCallbacks*)DE_NULL, &bufferView) != VK_SUCCESS)
+ return tcu::TestStatus::fail("Buffer View creation failed!");
+
+ // Testing after attaching memory to buffer.
+ if (!m_testCase.beforeAllocateMemory)
+ {
+ if (vk.allocateMemory(vkDevice, &memAlloc, (const VkAllocationCallbacks*)DE_NULL, &memory) != VK_SUCCESS)
+ return tcu::TestStatus::fail("Alloc memory failed!");
+
+ if (vk.bindBufferMemory(vkDevice, testBuffer, memory, 0) != VK_SUCCESS)
+ return tcu::TestStatus::fail("Bind buffer memory failed!");
+ }
+
+ vk.destroyBufferView(vkDevice, bufferView, (const VkAllocationCallbacks*)DE_NULL);
+ }
+
+ // Testing complete view size.
+ {
+ VkBufferView completeBufferView;
+ VkBufferViewCreateInfo completeBufferViewCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO, // VkStructureType sType;
+ NULL, // const void* pNext;
+ (VkBufferViewCreateFlags)0,
+ testBuffer, // VkBuffer buffer;
+ m_testCase.format, // VkFormat format;
+ m_testCase.offset, // VkDeviceSize offset;
+ size, // VkDeviceSize range;
+ };
+
+ if (vk.createBufferView(vkDevice, &completeBufferViewCreateInfo, (const VkAllocationCallbacks*)DE_NULL, &completeBufferView) != VK_SUCCESS)
+ return tcu::TestStatus::fail("Buffer View creation failed!");
+
+ vk.destroyBufferView(vkDevice, completeBufferView, (const VkAllocationCallbacks*)DE_NULL);
+ }
+
+ vk.freeMemory(vkDevice, memory, (const VkAllocationCallbacks*)DE_NULL);
+ vk.destroyBuffer(vkDevice, testBuffer, (const VkAllocationCallbacks*)DE_NULL);
+
+ return tcu::TestStatus::pass("BufferView test");
+}
+
+} // anonymous
+
+ tcu::TestCaseGroup* createBufferViewCreateTests (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> bufferViewTests (new tcu::TestCaseGroup(testCtx, "create", "BufferView Construction Tests"));
+
+ const VkDeviceSize range = 96;
+ for (deUint32 format = VK_FORMAT_UNDEFINED + 1; format < VK_FORMAT_LAST; format++)
+ {
+ std::ostringstream testName;
+ std::ostringstream testDescription;
+ testName << "createBufferView_" << format;
+ testDescription << "vkBufferView test " << testName.str();
+ {
+ BufferViewCaseParameters testParams =
+ {
+ (VkFormat)format, // VkFormat format;
+ 0, // VkDeviceSize offset;
+ range, // VkDeviceSize range;
+ VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, // VkBufferUsageFlags usage;
+ false // beforeAlloceMemory bool;
+ };
+ bufferViewTests->addChild(new BufferViewTestCase(testCtx, testName.str() + "_before_uniform", testDescription.str(), testParams));
+ }
+ {
+ BufferViewCaseParameters testParams =
+ {
+ (VkFormat)format, // VkFormat format;
+ 0, // VkDeviceSize offset;
+ range, // VkDeviceSize range;
+ VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, // VkBufferUsageFlags usage;
+ true // beforeAlloceMemory bool;
+ };
+ bufferViewTests->addChild(new BufferViewTestCase(testCtx, testName.str() + "_after_uniform", testDescription.str(), testParams));
+ }
+ {
+ BufferViewCaseParameters testParams =
+ {
+ (VkFormat)format, // VkFormat format;
+ 0, // VkDeviceSize offset;
+ range, // VkDeviceSize range;
+ VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT, // VkBufferUsageFlags usage;
+ false // beforeAlloceMemory bool;
+ };
+ bufferViewTests->addChild(new BufferViewTestCase(testCtx, testName.str() + "_before_storage", testDescription.str(), testParams));
+ }
+ {
+ BufferViewCaseParameters testParams =
+ {
+ (VkFormat)format, // VkFormat format;
+ 0, // VkDeviceSize offset;
+ range, // VkDeviceSize range;
+ VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT, // VkBufferUsageFlags usage;
+ true // beforeAlloceMemory bool;
+ };
+ bufferViewTests->addChild(new BufferViewTestCase(testCtx, testName.str() + "_after_storage", testDescription.str(), testParams));
+ }
+ }
+
+ return bufferViewTests.release();
+}
+
+} // api
+} // vk
--- /dev/null
+#ifndef _VKTAPIBUFFERVIEWCREATETESTS_HPP
+#define _VKTAPIBUFFERVIEWCREATETESTS_HPP
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by Khronos,
+ * at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Vulkan Buffer View Creation Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+
+namespace api
+{
+
+tcu::TestCaseGroup* createBufferViewCreateTests (tcu::TestContext& testCtx);
+
+} // api
+} // vkt
+
+#endif // _VKTAPIBUFFERVIEWCREATETESTS_HPP
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Device Initialization Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktApiDeviceInitializationTests.hpp"
+#include "vktTestCaseUtil.hpp"
+
+#include "vkDefs.hpp"
+#include "vkPlatform.hpp"
+#include "vkStrUtil.hpp"
+#include "vkRef.hpp"
+#include "vkRefUtil.hpp"
+#include "vkQueryUtil.hpp"
+#include "vkMemUtil.hpp"
+#include "vkDeviceUtil.hpp"
+#include "vkApiVersion.hpp"
+
+#include "tcuTestLog.hpp"
+#include "tcuResultCollector.hpp"
+
+#include "deUniquePtr.hpp"
+#include "deStringUtil.hpp"
+
+#include <vector>
+
+namespace vkt
+{
+namespace api
+{
+
+namespace
+{
+
+using namespace vk;
+using namespace std;
+using std::vector;
+using tcu::TestLog;
+
+tcu::TestStatus createInstanceTest (Context& context)
+{
+ tcu::TestLog& log = context.getTestContext().getLog();
+ tcu::ResultCollector resultCollector (log);
+ const char* appNames[] = { "appName", DE_NULL, "", "app, name", "app(\"name\"", "app~!@#$%^&*()_+name", "app\nName", "app\r\nName" };
+ const char* engineNames[] = { "engineName", DE_NULL, "", "engine. name", "engine\"(name)", "eng~!@#$%^&*()_+name", "engine\nName", "engine\r\nName" };
+ const deUint32 appVersions[] = { 0, 1, (deUint32)-1 };
+ const deUint32 engineVersions[] = { 0, 1, (deUint32)-1 };
+ const PlatformInterface& platformInterface = context.getPlatformInterface();
+ vector<VkApplicationInfo> appInfos;
+
+ // test over appName
+ for (int appNameNdx = 0; appNameNdx < DE_LENGTH_OF_ARRAY(appNames); appNameNdx++)
+ {
+ const VkApplicationInfo appInfo =
+ {
+ VK_STRUCTURE_TYPE_APPLICATION_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ appNames[appNameNdx], // const char* pAppName;
+ 0u, // deUint32 appVersion;
+ "engineName", // const char* pEngineName;
+ 0u, // deUint32 engineVersion;
+ VK_API_VERSION, // deUint32 apiVersion;
+ };
+
+ appInfos.push_back(appInfo);
+ }
+
+ // test over engineName
+ for (int engineNameNdx = 0; engineNameNdx < DE_LENGTH_OF_ARRAY(engineNames); engineNameNdx++)
+ {
+ const VkApplicationInfo appInfo =
+ {
+ VK_STRUCTURE_TYPE_APPLICATION_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ "appName", // const char* pAppName;
+ 0u, // deUint32 appVersion;
+ engineNames[engineNameNdx], // const char* pEngineName;
+ 0u, // deUint32 engineVersion;
+ VK_API_VERSION, // deUint32 apiVersion;
+ };
+
+ appInfos.push_back(appInfo);
+ }
+
+ // test over appVersion
+ for (int appVersionNdx = 0; appVersionNdx < DE_LENGTH_OF_ARRAY(appVersions); appVersionNdx++)
+ {
+ const VkApplicationInfo appInfo =
+ {
+ VK_STRUCTURE_TYPE_APPLICATION_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ "appName", // const char* pAppName;
+ appVersions[appVersionNdx], // deUint32 appVersion;
+ "engineName", // const char* pEngineName;
+ 0u, // deUint32 engineVersion;
+ VK_API_VERSION, // deUint32 apiVersion;
+ };
+
+ appInfos.push_back(appInfo);
+ }
+
+ // test over engineVersion
+ for (int engineVersionNdx = 0; engineVersionNdx < DE_LENGTH_OF_ARRAY(engineVersions); engineVersionNdx++)
+ {
+ const VkApplicationInfo appInfo =
+ {
+ VK_STRUCTURE_TYPE_APPLICATION_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ "appName", // const char* pAppName;
+ 0u, // deUint32 appVersion;
+ "engineName", // const char* pEngineName;
+ engineVersions[engineVersionNdx], // deUint32 engineVersion;
+ VK_API_VERSION, // deUint32 apiVersion;
+ };
+
+ appInfos.push_back(appInfo);
+ }
+
+ // run the tests!
+ for (size_t appInfoNdx = 0; appInfoNdx < appInfos.size(); ++appInfoNdx)
+ {
+ const VkApplicationInfo& appInfo = appInfos[appInfoNdx];
+ const VkInstanceCreateInfo instanceCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkInstanceCreateFlags)0u, // VkInstanceCreateFlags flags;
+ &appInfo, // const VkApplicationInfo* pAppInfo;
+ 0u, // deUint32 layerCount;
+ DE_NULL, // const char*const* ppEnabledLayernames;
+ 0u, // deUint32 extensionCount;
+ DE_NULL, // const char*const* ppEnabledExtensionNames;
+ };
+
+ log << TestLog::Message << "Creating instance with appInfo: " << appInfo << TestLog::EndMessage;
+
+ try
+ {
+ const Unique<VkInstance> instance(createInstance(platformInterface, &instanceCreateInfo));
+ log << TestLog::Message << "Succeeded" << TestLog::EndMessage;
+ }
+ catch (const vk::Error& err)
+ {
+ resultCollector.fail("Failed, Error code: " + de::toString(err.getMessage()));
+ }
+ }
+
+ return tcu::TestStatus(resultCollector.getResult(), resultCollector.getMessage());
+}
+
+tcu::TestStatus createInstanceWithInvalidApiVersionTest (Context& context)
+{
+ tcu::TestLog& log = context.getTestContext().getLog();
+ tcu::ResultCollector resultCollector (log);
+ const PlatformInterface& platformInterface = context.getPlatformInterface();
+ const ApiVersion apiVersion = unpackVersion(VK_API_VERSION);
+ const deUint32 invalidMajorVersion = (1 << 10) - 1;
+ const deUint32 invalidMinorVersion = (1 << 10) - 1;
+ const deUint32 invalidPatchNum = (1 << 12) - 1;
+ vector<ApiVersion> invalidApiVersions;
+
+ invalidApiVersions.push_back(ApiVersion(invalidMajorVersion, apiVersion.minorNum, apiVersion.patchNum));
+ invalidApiVersions.push_back(ApiVersion(apiVersion.majorNum, invalidMinorVersion, apiVersion.patchNum));
+ invalidApiVersions.push_back(ApiVersion(apiVersion.majorNum, apiVersion.minorNum, invalidPatchNum));
+
+ for (size_t apiVersionNdx = 0; apiVersionNdx < invalidApiVersions.size(); apiVersionNdx++)
+ {
+ const VkApplicationInfo appInfo =
+ {
+ VK_STRUCTURE_TYPE_APPLICATION_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ "appName", // const char* pAppName;
+ 0u, // deUint32 appVersion;
+ "engineName", // const char* pEngineName;
+ 0u, // deUint32 engineVersion;
+ pack(invalidApiVersions[apiVersionNdx]), // deUint32 apiVersion;
+ };
+ const VkInstanceCreateInfo instanceCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkInstanceCreateFlags)0u, // VkInstanceCreateFlags flags;
+ &appInfo, // const VkApplicationInfo* pAppInfo;
+ 0u, // deUint32 layerCount;
+ DE_NULL, // const char*const* ppEnabledLayernames;
+ 0u, // deUint32 extensionCount;
+ DE_NULL, // const char*const* ppEnabledExtensionNames;
+ };
+
+
+ log << TestLog::Message
+ <<"VK_API_VERSION defined in vulkan.h: " << apiVersion
+ << ", api version used to create instance: " << invalidApiVersions[apiVersionNdx]
+ << TestLog::EndMessage;
+
+ {
+ VkInstance instance = (VkInstance)0;
+ const VkResult result = platformInterface.createInstance(&instanceCreateInfo, DE_NULL/*pAllocator*/, &instance);
+ const bool gotInstance = !!instance;
+
+ if (instance)
+ {
+ const InstanceDriver instanceIface (platformInterface, instance);
+ instanceIface.destroyInstance(instance, DE_NULL/*pAllocator*/);
+ }
+
+ if (result == VK_ERROR_INCOMPATIBLE_DRIVER)
+ {
+ TCU_CHECK(!gotInstance);
+ log << TestLog::Message << "Pass, instance creation with invalid apiVersion is rejected" << TestLog::EndMessage;
+ }
+ else
+ resultCollector.fail("Fail, instance creation with invalid apiVersion is not rejected");
+ }
+ }
+
+ return tcu::TestStatus(resultCollector.getResult(), resultCollector.getMessage());
+}
+
+tcu::TestStatus createInstanceWithUnsupportedExtensionsTest (Context& context)
+{
+ tcu::TestLog& log = context.getTestContext().getLog();
+ const PlatformInterface& platformInterface = context.getPlatformInterface();
+ const char* enabledExtensions[] = {"VK_UNSUPPORTED_EXTENSION", "THIS_IS_NOT_AN_EXTENSION"};
+ const VkApplicationInfo appInfo =
+ {
+ VK_STRUCTURE_TYPE_APPLICATION_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ "appName", // const char* pAppName;
+ 0u, // deUint32 appVersion;
+ "engineName", // const char* pEngineName;
+ 0u, // deUint32 engineVersion;
+ VK_API_VERSION, // deUint32 apiVersion;
+ };
+ const VkInstanceCreateInfo instanceCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkInstanceCreateFlags)0u, // VkInstanceCreateFlags flags;
+ &appInfo, // const VkApplicationInfo* pAppInfo;
+ 0u, // deUint32 layerCount;
+ DE_NULL, // const char*const* ppEnabledLayernames;
+ DE_LENGTH_OF_ARRAY(enabledExtensions), // deUint32 extensionCount;
+ enabledExtensions, // const char*const* ppEnabledExtensionNames;
+ };
+
+ log << TestLog::Message << "Enabled extensions are: " << TestLog::EndMessage;
+
+ for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(enabledExtensions); ndx++)
+ log << TestLog::Message << enabledExtensions[ndx] << TestLog::EndMessage;
+
+ {
+ VkInstance instance = (VkInstance)0;
+ const VkResult result = platformInterface.createInstance(&instanceCreateInfo, DE_NULL/*pAllocator*/, &instance);
+ const bool gotInstance = !!instance;
+
+ if (instance)
+ {
+ const InstanceDriver instanceIface (platformInterface, instance);
+ instanceIface.destroyInstance(instance, DE_NULL/*pAllocator*/);
+ }
+
+ if (result == VK_ERROR_EXTENSION_NOT_PRESENT)
+ {
+ TCU_CHECK(!gotInstance);
+ return tcu::TestStatus::pass("Pass, creating instance with unsupported extension was rejected.");
+ }
+ else
+ return tcu::TestStatus::fail("Fail, creating instance with unsupported extensions succeeded.");
+ }
+}
+
+tcu::TestStatus createDeviceTest (Context& context)
+{
+ const PlatformInterface& platformInterface = context.getPlatformInterface();
+ const Unique<VkInstance> instance (createDefaultInstance(platformInterface));
+ const InstanceDriver instanceDriver (platformInterface, instance.get());
+ const VkPhysicalDevice physicalDevice = chooseDevice(instanceDriver, instance.get(), context.getTestContext().getCommandLine());
+ const deUint32 queueFamilyIndex = 0;
+ const deUint32 queueCount = 1;
+ const deUint32 queueIndex = 0;
+ const float queuePriority = 1.0f;
+ const VkDeviceQueueCreateInfo deviceQueueCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
+ DE_NULL,
+ (VkDeviceQueueCreateFlags)0u,
+ queueFamilyIndex, //queueFamilyIndex;
+ queueCount, //queueCount;
+ &queuePriority, //pQueuePriorities;
+ };
+ const VkDeviceCreateInfo deviceCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, //sType;
+ DE_NULL, //pNext;
+ (VkDeviceCreateFlags)0u,
+ 1, //queueRecordCount;
+ &deviceQueueCreateInfo, //pRequestedQueues;
+ 0, //layerCount;
+ DE_NULL, //ppEnabledLayerNames;
+ 0, //extensionCount;
+ DE_NULL, //ppEnabledExtensionNames;
+ DE_NULL, //pEnabledFeatures;
+ };
+
+ const Unique<VkDevice> device (createDevice(instanceDriver, physicalDevice, &deviceCreateInfo));
+ const DeviceDriver deviceDriver (instanceDriver, device.get());
+ VkQueue queue;
+
+ deviceDriver.getDeviceQueue(device.get(), queueFamilyIndex, queueIndex, &queue);
+ VK_CHECK(deviceDriver.queueWaitIdle(queue));
+
+ return tcu::TestStatus::pass("Pass");
+}
+
+tcu::TestStatus createMultipleDevicesTest (Context& context)
+{
+ tcu::TestLog& log = context.getTestContext().getLog();
+ tcu::ResultCollector resultCollector (log);
+ const int numDevices = 5;
+ const PlatformInterface& platformInterface = context.getPlatformInterface();
+ const Unique<VkInstance> instance (createDefaultInstance(platformInterface));
+ const InstanceDriver instanceDriver (platformInterface, instance.get());
+ const VkPhysicalDevice physicalDevice = chooseDevice(instanceDriver, instance.get(), context.getTestContext().getCommandLine());
+ const deUint32 queueFamilyIndex = 0;
+ const deUint32 queueCount = 1;
+ const deUint32 queueIndex = 0;
+ const float queuePriority = 1.0f;
+ const VkDeviceQueueCreateInfo deviceQueueCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
+ DE_NULL,
+ (VkDeviceQueueCreateFlags)0u, //flags;
+ queueFamilyIndex, //queueFamilyIndex;
+ queueCount, //queueCount;
+ &queuePriority, //pQueuePriorities;
+ };
+ const VkDeviceCreateInfo deviceCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, //sType;
+ DE_NULL, //pNext;
+ (VkDeviceCreateFlags)0u,
+ 1, //queueRecordCount;
+ &deviceQueueCreateInfo, //pRequestedQueues;
+ 0, //layerCount;
+ DE_NULL, //ppEnabledLayerNames;
+ 0, //extensionCount;
+ DE_NULL, //ppEnabledExtensionNames;
+ DE_NULL, //pEnabledFeatures;
+ };
+ vector<VkDevice> devices(numDevices, (VkDevice)DE_NULL);
+
+ try
+ {
+ for (int deviceNdx = 0; deviceNdx < numDevices; deviceNdx++)
+ {
+ const VkResult result = instanceDriver.createDevice(physicalDevice, &deviceCreateInfo, DE_NULL/*pAllocator*/, &devices[deviceNdx]);
+
+ if (result != VK_SUCCESS)
+ {
+ resultCollector.fail("Failed to create Device No." + de::toString(deviceNdx) + ", Error Code: " + de::toString(result));
+ break;
+ }
+
+ {
+ const DeviceDriver deviceDriver(instanceDriver, devices[deviceNdx]);
+ VkQueue queue;
+
+ DE_ASSERT(queueIndex < queueCount);
+ deviceDriver.getDeviceQueue(devices[deviceNdx], queueFamilyIndex, queueIndex, &queue);
+ VK_CHECK(deviceDriver.queueWaitIdle(queue));
+ }
+ }
+ }
+ catch (const vk::Error& error)
+ {
+ resultCollector.fail(de::toString(error.getError()));
+ }
+ catch (...)
+ {
+ for (int deviceNdx = (int)devices.size()-1; deviceNdx >= 0; deviceNdx--)
+ {
+ if (devices[deviceNdx] != (VkDevice)DE_NULL)
+ {
+ DeviceDriver deviceDriver(instanceDriver, devices[deviceNdx]);
+ deviceDriver.destroyDevice(devices[deviceNdx], DE_NULL/*pAllocator*/);
+ }
+ }
+
+ throw;
+ }
+
+ for (int deviceNdx = (int)devices.size()-1; deviceNdx >= 0; deviceNdx--)
+ {
+ if (devices[deviceNdx] != (VkDevice)DE_NULL)
+ {
+ DeviceDriver deviceDriver(instanceDriver, devices[deviceNdx]);
+ deviceDriver.destroyDevice(devices[deviceNdx], DE_NULL/*pAllocator*/);
+ }
+ }
+
+ return tcu::TestStatus(resultCollector.getResult(), resultCollector.getMessage());
+}
+
+tcu::TestStatus createDeviceWithUnsupportedExtensionsTest (Context& context)
+{
+ tcu::TestLog& log = context.getTestContext().getLog();
+ const PlatformInterface& platformInterface = context.getPlatformInterface();
+ const Unique<VkInstance> instance (createDefaultInstance(platformInterface));
+ const InstanceDriver instanceDriver (platformInterface, instance.get());
+ const char* enabledExtensions[] = {"VK_UNSUPPORTED_EXTENSION", "THIS_IS_NOT_AN_EXTENSION", "VK_DONT_SUPPORT_ME"};
+ const VkPhysicalDevice physicalDevice = chooseDevice(instanceDriver, instance.get(), context.getTestContext().getCommandLine());
+ const float queuePriority = 1.0f;
+ const VkDeviceQueueCreateInfo deviceQueueCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
+ DE_NULL,
+ (VkDeviceQueueCreateFlags)0u,
+ 0, //queueFamiliIndex;
+ 1, //queueCount;
+ &queuePriority, //pQueuePriorities;
+ };
+ const VkDeviceCreateInfo deviceCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, //sType;
+ DE_NULL, //pNext;
+ (VkDeviceCreateFlags)0u,
+ 1, //queueRecordCount;
+ &deviceQueueCreateInfo, //pRequestedQueues;
+ 0, //layerCount;
+ DE_NULL, //ppEnabledLayerNames;
+ DE_LENGTH_OF_ARRAY(enabledExtensions), //extensionCount;
+ enabledExtensions, //ppEnabledExtensionNames;
+ DE_NULL, //pEnabledFeatures;
+ };
+
+ log << TestLog::Message << "Enabled extensions are: " << TestLog::EndMessage;
+
+ for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(enabledExtensions); ndx++)
+ log << TestLog::Message << enabledExtensions[ndx] << TestLog::EndMessage;
+
+ {
+ VkDevice device = (VkDevice)0;
+ const VkResult result = instanceDriver.createDevice(physicalDevice, &deviceCreateInfo, DE_NULL/*pAllocator*/, &device);
+ const bool gotDevice = !!device;
+
+ if (device)
+ {
+ const DeviceDriver deviceIface (instanceDriver, device);
+ deviceIface.destroyDevice(device, DE_NULL/*pAllocator*/);
+ }
+
+ if (result == VK_ERROR_EXTENSION_NOT_PRESENT)
+ {
+ TCU_CHECK(!gotDevice);
+ return tcu::TestStatus::pass("Pass, create device with unsupported extension is rejected.");
+ }
+ else
+ return tcu::TestStatus::fail("Fail, create device with unsupported extension but succeed.");
+ }
+}
+
+tcu::TestStatus createDeviceWithVariousQueueCountsTest (Context& context)
+{
+ tcu::TestLog& log = context.getTestContext().getLog();
+ const int queueCountDiff = 1;
+ const PlatformInterface& platformInterface = context.getPlatformInterface();
+ const Unique<VkInstance> instance (createDefaultInstance(platformInterface));
+ const InstanceDriver instanceDriver (platformInterface, instance.get());
+ const VkPhysicalDevice physicalDevice = chooseDevice(instanceDriver, instance.get(), context.getTestContext().getCommandLine());
+ const vector<VkQueueFamilyProperties> queueFamilyProperties = getPhysicalDeviceQueueFamilyProperties(instanceDriver, physicalDevice);
+ vector<VkDeviceQueueCreateInfo> deviceQueueCreateInfos;
+
+ for (deUint32 queueFamilyNdx = 0; queueFamilyNdx < (deUint32)queueFamilyProperties.size(); queueFamilyNdx++)
+ {
+ const deUint32 maxQueueCount = queueFamilyProperties[queueFamilyNdx].queueCount;
+
+ for (deUint32 queueCount = 1; queueCount <= maxQueueCount; queueCount += queueCountDiff)
+ {
+ const VkDeviceQueueCreateInfo queueCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
+ DE_NULL,
+ (VkDeviceQueueCreateFlags)0u,
+ queueFamilyNdx,
+ queueCount,
+ DE_NULL
+ };
+
+ deviceQueueCreateInfos.push_back(queueCreateInfo);
+ }
+ }
+
+ for (size_t testNdx = 0; testNdx < deviceQueueCreateInfos.size(); testNdx++)
+ {
+ const VkDeviceQueueCreateInfo& queueCreateInfo = deviceQueueCreateInfos[testNdx];
+ const VkDeviceCreateInfo deviceCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, //sType;
+ DE_NULL, //pNext;
+ (VkDeviceCreateFlags)0u,
+ 1, //queueRecordCount;
+ &queueCreateInfo, //pRequestedQueues;
+ 0, //layerCount;
+ DE_NULL, //ppEnabledLayerNames;
+ 0, //extensionCount;
+ DE_NULL, //ppEnabledExtensionNames;
+ DE_NULL, //pEnabledFeatures;
+ };
+ const Unique<VkDevice> device (createDevice(instanceDriver, physicalDevice, &deviceCreateInfo));
+ const DeviceDriver deviceDriver (instanceDriver, device.get());
+ const deUint32 queueFamilyIndex = deviceCreateInfo.pQueueCreateInfos->queueFamilyIndex;
+ const deUint32 queueCount = deviceCreateInfo.pQueueCreateInfos->queueCount;
+
+ for (deUint32 queueIndex = 0; queueIndex < queueCount; queueIndex++)
+ {
+ VkQueue queue;
+ VkResult result;
+
+ deviceDriver.getDeviceQueue(device.get(), queueFamilyIndex, queueIndex, &queue);
+ TCU_CHECK(!!queue);
+
+ result = deviceDriver.queueWaitIdle(queue);
+ if (result != VK_SUCCESS)
+ {
+ log << TestLog::Message
+ << "vkQueueWaitIdle failed"
+ << ", queueIndex = " << queueIndex
+ << ", queueCreateInfo " << queueCreateInfo
+ << ", Error Code: " << result
+ << TestLog::EndMessage;
+ return tcu::TestStatus::fail("Fail");
+ }
+ }
+ }
+ return tcu::TestStatus::pass("Pass");
+}
+
+} // anonymous
+
+tcu::TestCaseGroup* createDeviceInitializationTests (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> deviceInitializationTests (new tcu::TestCaseGroup(testCtx, "device_init", "Device Initialization Tests"));
+
+ addFunctionCase(deviceInitializationTests.get(), "create_instance_name_version", "", createInstanceTest);
+ addFunctionCase(deviceInitializationTests.get(), "create_instance_invalid_api_version", "", createInstanceWithInvalidApiVersionTest);
+ addFunctionCase(deviceInitializationTests.get(), "create_instance_unsupported_extensions", "", createInstanceWithUnsupportedExtensionsTest);
+ addFunctionCase(deviceInitializationTests.get(), "create_device", "", createDeviceTest);
+ addFunctionCase(deviceInitializationTests.get(), "create_multiple_devices", "", createMultipleDevicesTest);
+ addFunctionCase(deviceInitializationTests.get(), "create_device_unsupported_extensions", "", createDeviceWithUnsupportedExtensionsTest);
+ addFunctionCase(deviceInitializationTests.get(), "create_device_various_queue_counts", "", createDeviceWithVariousQueueCountsTest);
+
+ return deviceInitializationTests.release();
+}
+
+} // api
+} // vkt
--- /dev/null
+#ifndef _VKTAPIDEVICEINITIALIZATIONTESTS_HPP
+#define _VKTAPIDEVICEINITIALIZATIONTESTS_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Device Initialization tests
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+namespace api
+{
+
+tcu::TestCaseGroup* createDeviceInitializationTests (tcu::TestContext& testCtx);
+
+} // api
+} // vkt
+
+#endif // _VKTAPIDEVICEINITIALIZATIONTESTS_HPP
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Object management tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktApiObjectManagementTests.hpp"
+#include "vktTestCaseUtil.hpp"
+
+#include "vkDefs.hpp"
+#include "vkRef.hpp"
+#include "vkRefUtil.hpp"
+#include "vkQueryUtil.hpp"
+#include "vkMemUtil.hpp"
+#include "vkPrograms.hpp"
+#include "vkTypeUtil.hpp"
+#include "vkPlatform.hpp"
+#include "vkStrUtil.hpp"
+
+#include "tcuVector.hpp"
+#include "tcuResultCollector.hpp"
+#include "tcuCommandLine.hpp"
+#include "tcuTestLog.hpp"
+
+#include "deUniquePtr.hpp"
+#include "deSharedPtr.hpp"
+#include "deArrayUtil.hpp"
+#include "deSpinBarrier.hpp"
+#include "deThread.hpp"
+#include "deInt32.h"
+
+namespace vkt
+{
+namespace api
+{
+
+namespace
+{
+
+using namespace vk;
+
+using de::UniquePtr;
+using de::MovePtr;
+using de::SharedPtr;
+
+using tcu::IVec3;
+using tcu::UVec3;
+using tcu::ResultCollector;
+using tcu::TestStatus;
+using tcu::TestLog;
+
+using std::string;
+using std::vector;
+
+class ThreadGroupThread;
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Thread group
+ *
+ * Thread group manages collection of threads that are expected to be
+ * launched simultaneously as a group.
+ *
+ * Shared barrier is provided for synchronizing execution. Terminating thread
+ * early either by returning from ThreadGroupThread::runThread() or throwing
+ * an exception is safe, and other threads will continue execution. The
+ * thread that has been terminated is simply removed from the synchronization
+ * group.
+ *
+ * TestException-based exceptions are collected and translated into a
+ * tcu::TestStatus by using tcu::ResultCollector.
+ *
+ * Use cases for ThreadGroup include for example testing thread-safety of
+ * certain API operations by poking API simultaneously from multiple
+ * threads.
+ *//*--------------------------------------------------------------------*/
+class ThreadGroup
+{
+public:
+ ThreadGroup (void);
+ ~ThreadGroup (void);
+
+ void add (de::MovePtr<ThreadGroupThread> thread);
+ TestStatus run (void);
+
+private:
+ typedef std::vector<de::SharedPtr<ThreadGroupThread> > ThreadVector;
+
+ ThreadVector m_threads;
+ de::SpinBarrier m_barrier;
+} DE_WARN_UNUSED_TYPE;
+
+class ThreadGroupThread : private de::Thread
+{
+public:
+ ThreadGroupThread (void);
+ virtual ~ThreadGroupThread (void);
+
+ void start (de::SpinBarrier* groupBarrier);
+
+ ResultCollector& getResultCollector (void) { return m_resultCollector; }
+
+ using de::Thread::join;
+
+protected:
+ virtual void runThread (void) = 0;
+
+ void barrier (void);
+
+private:
+ ThreadGroupThread (const ThreadGroupThread&);
+ ThreadGroupThread& operator= (const ThreadGroupThread&);
+
+ void run (void);
+
+ ResultCollector m_resultCollector;
+ de::SpinBarrier* m_barrier;
+};
+
+// ThreadGroup
+
+ThreadGroup::ThreadGroup (void)
+ : m_barrier(1)
+{
+}
+
+ThreadGroup::~ThreadGroup (void)
+{
+}
+
+void ThreadGroup::add (de::MovePtr<ThreadGroupThread> thread)
+{
+ m_threads.push_back(de::SharedPtr<ThreadGroupThread>(thread.release()));
+}
+
+tcu::TestStatus ThreadGroup::run (void)
+{
+ tcu::ResultCollector resultCollector;
+
+ m_barrier.reset((int)m_threads.size());
+
+ for (ThreadVector::iterator threadIter = m_threads.begin(); threadIter != m_threads.end(); ++threadIter)
+ (*threadIter)->start(&m_barrier);
+
+ for (ThreadVector::iterator threadIter = m_threads.begin(); threadIter != m_threads.end(); ++threadIter)
+ {
+ tcu::ResultCollector& threadResult = (*threadIter)->getResultCollector();
+ (*threadIter)->join();
+ resultCollector.addResult(threadResult.getResult(), threadResult.getMessage());
+ }
+
+ return tcu::TestStatus(resultCollector.getResult(), resultCollector.getMessage());
+}
+
+// ThreadGroupThread
+
+ThreadGroupThread::ThreadGroupThread (void)
+ : m_barrier(DE_NULL)
+{
+}
+
+ThreadGroupThread::~ThreadGroupThread (void)
+{
+}
+
+void ThreadGroupThread::start (de::SpinBarrier* groupBarrier)
+{
+ m_barrier = groupBarrier;
+ de::Thread::start();
+}
+
+void ThreadGroupThread::run (void)
+{
+ try
+ {
+ runThread();
+ }
+ catch (const tcu::TestException& e)
+ {
+ getResultCollector().addResult(e.getTestResult(), e.getMessage());
+ }
+ catch (const std::exception& e)
+ {
+ getResultCollector().addResult(QP_TEST_RESULT_FAIL, e.what());
+ }
+ catch (...)
+ {
+ getResultCollector().addResult(QP_TEST_RESULT_FAIL, "Exception");
+ }
+
+ m_barrier->removeThread(de::SpinBarrier::WAIT_MODE_AUTO);
+}
+
+inline void ThreadGroupThread::barrier (void)
+{
+ m_barrier->sync(de::SpinBarrier::WAIT_MODE_AUTO);
+}
+
+deUint32 getDefaultTestThreadCount (void)
+{
+ return de::clamp(deGetNumAvailableLogicalCores(), 2u, 8u);
+}
+
+// Utilities
+
+struct Environment
+{
+ const PlatformInterface& vkp;
+ const DeviceInterface& vkd;
+ VkDevice device;
+ deUint32 queueFamilyIndex;
+ const BinaryCollection& programBinaries;
+ deUint32 maxResourceConsumers; // Maximum number of objects using same Object::Resources concurrently
+
+ Environment (Context& context, deUint32 maxResourceConsumers_)
+ : vkp (context.getPlatformInterface())
+ , vkd (context.getDeviceInterface())
+ , device (context.getDevice())
+ , queueFamilyIndex (context.getUniversalQueueFamilyIndex())
+ , programBinaries (context.getBinaryCollection())
+ , maxResourceConsumers (maxResourceConsumers_)
+ {
+ }
+
+ Environment (const PlatformInterface& vkp_,
+ const DeviceInterface& vkd_,
+ VkDevice device_,
+ deUint32 queueFamilyIndex_,
+ const BinaryCollection& programBinaries_,
+ deUint32 maxResourceConsumers_)
+ : vkp (vkp_)
+ , vkd (vkd_)
+ , device (device_)
+ , queueFamilyIndex (queueFamilyIndex_)
+ , programBinaries (programBinaries_)
+ , maxResourceConsumers (maxResourceConsumers_)
+ {
+ }
+};
+
+template<typename Case>
+struct Dependency
+{
+ typename Case::Resources resources;
+ Unique<typename Case::Type> object;
+
+ Dependency (const Environment& env, const typename Case::Parameters& params)
+ : resources (env, params)
+ , object (Case::create(env, resources, params))
+ {}
+};
+
+// Object definitions
+
+enum
+{
+ DEFAULT_MAX_CONCURRENT_OBJECTS = 16*1024
+};
+
+struct Instance
+{
+ typedef VkInstance Type;
+
+ enum { MAX_CONCURRENT = 32 };
+
+ struct Parameters
+ {
+ Parameters (void) {}
+ };
+
+ struct Resources
+ {
+ Resources (const Environment&, const Parameters&) {}
+ };
+
+ static Move<VkInstance> create (const Environment& env, const Resources&, const Parameters&)
+ {
+ const VkApplicationInfo appInfo =
+ {
+ VK_STRUCTURE_TYPE_APPLICATION_INFO,
+ DE_NULL,
+ DE_NULL, // pApplicationName
+ 0u, // applicationVersion
+ DE_NULL, // pEngineName
+ 0u, // engineVersion
+ VK_API_VERSION
+ };
+ const VkInstanceCreateInfo instanceInfo =
+ {
+ VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
+ DE_NULL,
+ (VkInstanceCreateFlags)0,
+ &appInfo,
+ 0u, // enabledLayerNameCount
+ DE_NULL, // ppEnabledLayerNames
+ 0u, // enabledExtensionNameCount
+ DE_NULL, // ppEnabledExtensionNames
+ };
+
+ return createInstance(env.vkp, &instanceInfo);
+ }
+};
+
+struct Device
+{
+ typedef VkDevice Type;
+
+ enum { MAX_CONCURRENT = 32 };
+
+ struct Parameters
+ {
+ deUint32 deviceIndex;
+ VkQueueFlags queueFlags;
+
+ Parameters (deUint32 deviceIndex_, VkQueueFlags queueFlags_)
+ : deviceIndex (deviceIndex_)
+ , queueFlags (queueFlags_)
+ {}
+ };
+
+ struct Resources
+ {
+ Dependency<Instance> instance;
+ InstanceDriver vki;
+ VkPhysicalDevice physicalDevice;
+ deUint32 queueFamilyIndex;
+
+ Resources (const Environment& env, const Parameters& params)
+ : instance (env, Instance::Parameters())
+ , vki (env.vkp, *instance.object)
+ , physicalDevice (0)
+ , queueFamilyIndex (~0u)
+ {
+ {
+ const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(vki, *instance.object);
+
+ if (physicalDevices.size() <= (size_t)params.deviceIndex)
+ TCU_THROW(NotSupportedError, "Device not found");
+
+ physicalDevice = physicalDevices[params.deviceIndex];
+ }
+
+ {
+ const vector<VkQueueFamilyProperties> queueProps = getPhysicalDeviceQueueFamilyProperties(vki, physicalDevice);
+ bool foundMatching = false;
+
+ for (size_t curQueueNdx = 0; curQueueNdx < queueProps.size(); curQueueNdx++)
+ {
+ if ((queueProps[curQueueNdx].queueFlags & params.queueFlags) == params.queueFlags)
+ {
+ queueFamilyIndex = (deUint32)curQueueNdx;
+ foundMatching = true;
+ }
+ }
+
+ if (!foundMatching)
+ TCU_THROW(NotSupportedError, "Matching queue not found");
+ }
+ }
+ };
+
+ static Move<VkDevice> create (const Environment&, const Resources& res, const Parameters&)
+ {
+ const float queuePriority = 1.0;
+
+ const VkDeviceQueueCreateInfo queues[] =
+ {
+ {
+ VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
+ DE_NULL,
+ (VkDeviceQueueCreateFlags)0,
+ res.queueFamilyIndex,
+ 1u, // queueCount
+ &queuePriority, // pQueuePriorities
+ }
+ };
+ const VkDeviceCreateInfo deviceInfo =
+ {
+ VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
+ DE_NULL,
+ (VkDeviceCreateFlags)0,
+ DE_LENGTH_OF_ARRAY(queues),
+ queues,
+ 0u, // enabledLayerNameCount
+ DE_NULL, // ppEnabledLayerNames
+ 0u, // enabledExtensionNameCount
+ DE_NULL, // ppEnabledExtensionNames
+ DE_NULL, // pEnabledFeatures
+ };
+
+ return createDevice(res.vki, res.physicalDevice, &deviceInfo);
+ }
+};
+
+struct DeviceMemory
+{
+ typedef VkDeviceMemory Type;
+
+ enum { MAX_CONCURRENT = DEFAULT_MAX_CONCURRENT_OBJECTS };
+
+ struct Parameters
+ {
+ VkDeviceSize size;
+ deUint32 memoryTypeIndex;
+
+ Parameters (VkDeviceSize size_, deUint32 memoryTypeIndex_)
+ : size (size_)
+ , memoryTypeIndex (memoryTypeIndex_)
+ {
+ DE_ASSERT(memoryTypeIndex < VK_MAX_MEMORY_TYPES);
+ }
+ };
+
+ struct Resources
+ {
+ Resources (const Environment&, const Parameters&) {}
+ };
+
+ static Move<VkDeviceMemory> create (const Environment& env, const Resources&, const Parameters& params)
+ {
+ const VkMemoryAllocateInfo allocInfo =
+ {
+ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+ DE_NULL,
+ params.size,
+ params.memoryTypeIndex
+ };
+
+ return allocateMemory(env.vkd, env.device, &allocInfo);
+ }
+};
+
+DeviceMemory::Parameters getDeviceMemoryParameters (const VkMemoryRequirements& memReqs)
+{
+ return DeviceMemory::Parameters(memReqs.size, deCtz32(memReqs.memoryTypeBits));
+}
+
+DeviceMemory::Parameters getDeviceMemoryParameters (const Environment& env, VkImage image)
+{
+ return getDeviceMemoryParameters(getImageMemoryRequirements(env.vkd, env.device, image));
+}
+
+DeviceMemory::Parameters getDeviceMemoryParameters (const Environment& env, VkBuffer image)
+{
+ return getDeviceMemoryParameters(getBufferMemoryRequirements(env.vkd, env.device, image));
+}
+
+struct Buffer
+{
+ typedef VkBuffer Type;
+
+ enum { MAX_CONCURRENT = DEFAULT_MAX_CONCURRENT_OBJECTS };
+
+ struct Parameters
+ {
+ VkDeviceSize size;
+ VkBufferUsageFlags usage;
+
+ Parameters (VkDeviceSize size_,
+ VkBufferUsageFlags usage_)
+ : size (size_)
+ , usage (usage_)
+ {}
+ };
+
+ struct Resources
+ {
+ Resources (const Environment&, const Parameters&) {}
+ };
+
+ static Move<VkBuffer> create (const Environment& env, const Resources&, const Parameters& params)
+ {
+ const VkBufferCreateInfo bufferInfo =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
+ DE_NULL,
+ (VkBufferCreateFlags)0,
+ params.size,
+ params.usage,
+ VK_SHARING_MODE_EXCLUSIVE,
+ 1u,
+ &env.queueFamilyIndex
+ };
+
+ return createBuffer(env.vkd, env.device, &bufferInfo);
+ }
+};
+
+struct BufferView
+{
+ typedef VkBufferView Type;
+
+ enum { MAX_CONCURRENT = DEFAULT_MAX_CONCURRENT_OBJECTS };
+
+ struct Parameters
+ {
+ Buffer::Parameters buffer;
+ VkFormat format;
+ VkDeviceSize offset;
+ VkDeviceSize range;
+
+ Parameters (const Buffer::Parameters& buffer_,
+ VkFormat format_,
+ VkDeviceSize offset_,
+ VkDeviceSize range_)
+ : buffer (buffer_)
+ , format (format_)
+ , offset (offset_)
+ , range (range_)
+ {}
+ };
+
+ struct Resources
+ {
+ Dependency<Buffer> buffer;
+ Dependency<DeviceMemory> memory;
+
+ Resources (const Environment& env, const Parameters& params)
+ : buffer(env, params.buffer)
+ , memory(env, getDeviceMemoryParameters(env, *buffer.object))
+ {
+ VK_CHECK(env.vkd.bindBufferMemory(env.device, *buffer.object, *memory.object, 0));
+ }
+ };
+
+ static Move<VkBufferView> create (const Environment& env, const Resources& res, const Parameters& params)
+ {
+ const VkBufferViewCreateInfo bufferViewInfo =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,
+ DE_NULL,
+ (VkBufferViewCreateFlags)0,
+ *res.buffer.object,
+ params.format,
+ params.offset,
+ params.range
+ };
+
+ return createBufferView(env.vkd, env.device, &bufferViewInfo);
+ }
+};
+
+struct Image
+{
+ typedef VkImage Type;
+
+ enum { MAX_CONCURRENT = DEFAULT_MAX_CONCURRENT_OBJECTS };
+
+ struct Parameters
+ {
+ VkImageCreateFlags flags;
+ VkImageType imageType;
+ VkFormat format;
+ VkExtent3D extent;
+ deUint32 mipLevels;
+ deUint32 arraySize;
+ VkSampleCountFlagBits samples;
+ VkImageTiling tiling;
+ VkImageUsageFlags usage;
+ VkImageLayout initialLayout;
+
+ Parameters (VkImageCreateFlags flags_,
+ VkImageType imageType_,
+ VkFormat format_,
+ VkExtent3D extent_,
+ deUint32 mipLevels_,
+ deUint32 arraySize_,
+ VkSampleCountFlagBits samples_,
+ VkImageTiling tiling_,
+ VkImageUsageFlags usage_,
+ VkImageLayout initialLayout_)
+ : flags (flags_)
+ , imageType (imageType_)
+ , format (format_)
+ , extent (extent_)
+ , mipLevels (mipLevels_)
+ , arraySize (arraySize_)
+ , samples (samples_)
+ , tiling (tiling_)
+ , usage (usage_)
+ , initialLayout (initialLayout_)
+ {}
+ };
+
+ struct Resources
+ {
+ Resources (const Environment&, const Parameters&) {}
+ };
+
+ static Move<VkImage> create (const Environment& env, const Resources&, const Parameters& params)
+ {
+ const VkImageCreateInfo imageInfo =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
+ DE_NULL,
+ params.flags,
+ params.imageType,
+ params.format,
+ params.extent,
+ params.mipLevels,
+ params.arraySize,
+ params.samples,
+ params.tiling,
+ params.usage,
+ VK_SHARING_MODE_EXCLUSIVE, // sharingMode
+ 1u, // queueFamilyIndexCount
+ &env.queueFamilyIndex, // pQueueFamilyIndices
+ params.initialLayout
+ };
+
+ return createImage(env.vkd, env.device, &imageInfo);
+ }
+};
+
+struct ImageView
+{
+ typedef VkImageView Type;
+
+ enum { MAX_CONCURRENT = DEFAULT_MAX_CONCURRENT_OBJECTS };
+
+ struct Parameters
+ {
+ Image::Parameters image;
+ VkImageViewType viewType;
+ VkFormat format;
+ VkComponentMapping components;
+ VkImageSubresourceRange subresourceRange;
+
+ Parameters (const Image::Parameters& image_,
+ VkImageViewType viewType_,
+ VkFormat format_,
+ VkComponentMapping components_,
+ VkImageSubresourceRange subresourceRange_)
+ : image (image_)
+ , viewType (viewType_)
+ , format (format_)
+ , components (components_)
+ , subresourceRange (subresourceRange_)
+ {}
+ };
+
+ struct Resources
+ {
+ Dependency<Image> image;
+ Dependency<DeviceMemory> memory;
+
+ Resources (const Environment& env, const Parameters& params)
+ : image (env, params.image)
+ , memory(env, getDeviceMemoryParameters(env, *image.object))
+ {
+ VK_CHECK(env.vkd.bindImageMemory(env.device, *image.object, *memory.object, 0));
+ }
+ };
+
+ static Move<VkImageView> create (const Environment& env, const Resources& res, const Parameters& params)
+ {
+ const VkImageViewCreateInfo imageViewInfo =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
+ DE_NULL,
+ (VkImageViewCreateFlags)0,
+ *res.image.object,
+ params.viewType,
+ params.format,
+ params.components,
+ params.subresourceRange,
+ };
+
+ return createImageView(env.vkd, env.device, &imageViewInfo);
+ }
+};
+
+struct Semaphore
+{
+ typedef VkSemaphore Type;
+
+ enum { MAX_CONCURRENT = 100 };
+
+ struct Parameters
+ {
+ VkSemaphoreCreateFlags flags;
+
+ Parameters (VkSemaphoreCreateFlags flags_)
+ : flags(flags_)
+ {}
+ };
+
+ struct Resources
+ {
+ Resources (const Environment&, const Parameters&) {}
+ };
+
+ static Move<VkSemaphore> create (const Environment& env, const Resources&, const Parameters& params)
+ {
+ const VkSemaphoreCreateInfo semaphoreInfo =
+ {
+ VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
+ DE_NULL,
+ params.flags
+ };
+
+ return createSemaphore(env.vkd, env.device, &semaphoreInfo);
+ }
+};
+
+struct Fence
+{
+ typedef VkFence Type;
+
+ enum { MAX_CONCURRENT = 100 };
+
+ struct Parameters
+ {
+ VkFenceCreateFlags flags;
+
+ Parameters (VkFenceCreateFlags flags_)
+ : flags(flags_)
+ {}
+ };
+
+ struct Resources
+ {
+ Resources (const Environment&, const Parameters&) {}
+ };
+
+ static Move<VkFence> create (const Environment& env, const Resources&, const Parameters& params)
+ {
+ const VkFenceCreateInfo fenceInfo =
+ {
+ VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
+ DE_NULL,
+ params.flags
+ };
+
+ return createFence(env.vkd, env.device, &fenceInfo);
+ }
+};
+
+struct Event
+{
+ typedef VkEvent Type;
+
+ enum { MAX_CONCURRENT = 100 };
+
+ struct Parameters
+ {
+ VkEventCreateFlags flags;
+
+ Parameters (VkEventCreateFlags flags_)
+ : flags(flags_)
+ {}
+ };
+
+ struct Resources
+ {
+ Resources (const Environment&, const Parameters&) {}
+ };
+
+ static Move<VkEvent> create (const Environment& env, const Resources&, const Parameters& params)
+ {
+ const VkEventCreateInfo eventInfo =
+ {
+ VK_STRUCTURE_TYPE_EVENT_CREATE_INFO,
+ DE_NULL,
+ params.flags
+ };
+
+ return createEvent(env.vkd, env.device, &eventInfo);
+ }
+};
+
+struct QueryPool
+{
+ typedef VkQueryPool Type;
+
+ enum { MAX_CONCURRENT = DEFAULT_MAX_CONCURRENT_OBJECTS };
+
+ struct Parameters
+ {
+ VkQueryType queryType;
+ deUint32 entryCount;
+ VkQueryPipelineStatisticFlags pipelineStatistics;
+
+ Parameters (VkQueryType queryType_,
+ deUint32 entryCount_,
+ VkQueryPipelineStatisticFlags pipelineStatistics_)
+ : queryType (queryType_)
+ , entryCount (entryCount_)
+ , pipelineStatistics (pipelineStatistics_)
+ {}
+ };
+
+ struct Resources
+ {
+ Resources (const Environment&, const Parameters&) {}
+ };
+
+ static Move<VkQueryPool> create (const Environment& env, const Resources&, const Parameters& params)
+ {
+ const VkQueryPoolCreateInfo queryPoolInfo =
+ {
+ VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,
+ DE_NULL,
+ (VkQueryPoolCreateFlags)0,
+ params.queryType,
+ params.entryCount,
+ params.pipelineStatistics
+ };
+
+ return createQueryPool(env.vkd, env.device, &queryPoolInfo);
+ }
+};
+
+struct ShaderModule
+{
+ typedef VkShaderModule Type;
+
+ enum { MAX_CONCURRENT = DEFAULT_MAX_CONCURRENT_OBJECTS };
+
+ struct Parameters
+ {
+ VkShaderStageFlagBits shaderStage;
+ string binaryName;
+
+ Parameters (VkShaderStageFlagBits shaderStage_,
+ const std::string& binaryName_)
+ : shaderStage (shaderStage_)
+ , binaryName (binaryName_)
+ {}
+ };
+
+ struct Resources
+ {
+ const ProgramBinary& binary;
+
+ Resources (const Environment& env, const Parameters& params)
+ : binary(env.programBinaries.get(params.binaryName))
+ {}
+ };
+
+ static const char* getSource (VkShaderStageFlagBits stage)
+ {
+ switch (stage)
+ {
+ case VK_SHADER_STAGE_VERTEX_BIT:
+ return "#version 310 es\n"
+ "layout(location = 0) in highp vec4 a_position;\n"
+ "void main () { gl_Position = a_position; }\n";
+
+ case VK_SHADER_STAGE_FRAGMENT_BIT:
+ return "#version 310 es\n"
+ "layout(location = 0) out mediump vec4 o_color;\n"
+ "void main () { o_color = vec4(1.0, 0.5, 0.25, 1.0); }";
+
+ case VK_SHADER_STAGE_COMPUTE_BIT:
+ return "#version 310 es\n"
+ "layout(binding = 0) buffer Input { highp uint dataIn[]; };\n"
+ "layout(binding = 1) buffer Output { highp uint dataOut[]; };\n"
+ "void main (void)\n"
+ "{\n"
+ " dataOut[gl_GlobalInvocationID.x] = ~dataIn[gl_GlobalInvocationID.x];\n"
+ "}\n";
+
+ default:
+ DE_FATAL("Not implemented");
+ return DE_NULL;
+ }
+ }
+
+ static void initPrograms (SourceCollections& dst, Parameters params)
+ {
+ const char* const source = getSource(params.shaderStage);
+
+ DE_ASSERT(source);
+
+ dst.glslSources.add(params.binaryName)
+ << glu::ShaderSource(getGluShaderType(params.shaderStage), source);
+ }
+
+ static Move<VkShaderModule> create (const Environment& env, const Resources& res, const Parameters&)
+ {
+ const VkShaderModuleCreateInfo shaderModuleInfo =
+ {
+ VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
+ DE_NULL,
+ (VkShaderModuleCreateFlags)0,
+ res.binary.getSize(),
+ (const deUint32*)res.binary.getBinary(),
+ };
+
+ return createShaderModule(env.vkd, env.device, &shaderModuleInfo);
+ }
+};
+
+struct PipelineCache
+{
+ typedef VkPipelineCache Type;
+
+ enum { MAX_CONCURRENT = DEFAULT_MAX_CONCURRENT_OBJECTS };
+
+ struct Parameters
+ {
+ Parameters (void) {}
+ };
+
+ struct Resources
+ {
+ Resources (const Environment&, const Parameters&) {}
+ };
+
+ static Move<VkPipelineCache> create (const Environment& env, const Resources&, const Parameters&)
+ {
+ const VkPipelineCacheCreateInfo pipelineCacheInfo =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO,
+ DE_NULL,
+ (VkPipelineCacheCreateFlags)0u,
+ 0u, // initialDataSize
+ DE_NULL, // pInitialData
+ };
+
+ return createPipelineCache(env.vkd, env.device, &pipelineCacheInfo);
+ }
+};
+
+struct Sampler
+{
+ typedef VkSampler Type;
+
+ enum { MAX_CONCURRENT = DEFAULT_MAX_CONCURRENT_OBJECTS };
+
+ struct Parameters
+ {
+ VkFilter magFilter;
+ VkFilter minFilter;
+ VkSamplerMipmapMode mipmapMode;
+ VkSamplerAddressMode addressModeU;
+ VkSamplerAddressMode addressModeV;
+ VkSamplerAddressMode addressModeW;
+ float mipLodBias;
+ float maxAnisotropy;
+ VkBool32 compareEnable;
+ VkCompareOp compareOp;
+ float minLod;
+ float maxLod;
+ VkBorderColor borderColor;
+ VkBool32 unnormalizedCoordinates;
+
+ // \todo [2015-09-17 pyry] Other configurations
+ Parameters (void)
+ : magFilter (VK_FILTER_NEAREST)
+ , minFilter (VK_FILTER_NEAREST)
+ , mipmapMode (VK_SAMPLER_MIPMAP_MODE_BASE)
+ , addressModeU (VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)
+ , addressModeV (VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)
+ , addressModeW (VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)
+ , mipLodBias (0.0f)
+ , maxAnisotropy (0.0f)
+ , compareEnable (VK_FALSE)
+ , compareOp (VK_COMPARE_OP_ALWAYS)
+ , minLod (-1000.f)
+ , maxLod (+1000.f)
+ , borderColor (VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK)
+ , unnormalizedCoordinates (VK_FALSE)
+ {}
+ };
+
+ struct Resources
+ {
+ Resources (const Environment&, const Parameters&) {}
+ };
+
+ static Move<VkSampler> create (const Environment& env, const Resources&, const Parameters& params)
+ {
+ const VkSamplerCreateInfo samplerInfo =
+ {
+ VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
+ DE_NULL,
+ (VkSamplerCreateFlags)0,
+ params.magFilter,
+ params.minFilter,
+ params.mipmapMode,
+ params.addressModeU,
+ params.addressModeV,
+ params.addressModeW,
+ params.mipLodBias,
+ params.maxAnisotropy,
+ params.compareEnable,
+ params.compareOp,
+ params.minLod,
+ params.maxLod,
+ params.borderColor,
+ params.unnormalizedCoordinates
+ };
+
+ return createSampler(env.vkd, env.device, &samplerInfo);
+ }
+};
+
+struct DescriptorSetLayout
+{
+ typedef VkDescriptorSetLayout Type;
+
+ enum { MAX_CONCURRENT = DEFAULT_MAX_CONCURRENT_OBJECTS };
+
+ struct Parameters
+ {
+ struct Binding
+ {
+ deUint32 binding;
+ VkDescriptorType descriptorType;
+ deUint32 descriptorCount;
+ VkShaderStageFlags stageFlags;
+ bool useImmutableSampler;
+
+ Binding (deUint32 binding_,
+ VkDescriptorType descriptorType_,
+ deUint32 descriptorCount_,
+ VkShaderStageFlags stageFlags_,
+ bool useImmutableSampler_)
+ : binding (binding_)
+ , descriptorType (descriptorType_)
+ , descriptorCount (descriptorCount_)
+ , stageFlags (stageFlags_)
+ , useImmutableSampler (useImmutableSampler_)
+ {}
+
+ Binding (void) {}
+ };
+
+ vector<Binding> bindings;
+
+ Parameters (const vector<Binding>& bindings_)
+ : bindings(bindings_)
+ {}
+
+ static Parameters empty (void)
+ {
+ return Parameters(vector<Binding>());
+ }
+
+ static Parameters single (deUint32 binding,
+ VkDescriptorType descriptorType,
+ deUint32 descriptorCount,
+ VkShaderStageFlags stageFlags,
+ bool useImmutableSampler = false)
+ {
+ vector<Binding> bindings;
+ bindings.push_back(Binding(binding, descriptorType, descriptorCount, stageFlags, useImmutableSampler));
+ return Parameters(bindings);
+ }
+ };
+
+ struct Resources
+ {
+ vector<VkDescriptorSetLayoutBinding> bindings;
+ MovePtr<Dependency<Sampler> > immutableSampler;
+ vector<VkSampler> immutableSamplersPtr;
+
+ Resources (const Environment& env, const Parameters& params)
+ {
+ // Create immutable sampler if needed
+ for (vector<Parameters::Binding>::const_iterator cur = params.bindings.begin(); cur != params.bindings.end(); cur++)
+ {
+ if (cur->useImmutableSampler && !immutableSampler)
+ {
+ immutableSampler = de::newMovePtr<Dependency<Sampler> >(env, Sampler::Parameters());
+
+ if (cur->useImmutableSampler && immutableSamplersPtr.size() < (size_t)cur->descriptorCount)
+ immutableSamplersPtr.resize(cur->descriptorCount, *immutableSampler->object);
+ }
+ }
+
+ for (vector<Parameters::Binding>::const_iterator cur = params.bindings.begin(); cur != params.bindings.end(); cur++)
+ {
+ const VkDescriptorSetLayoutBinding binding =
+ {
+ cur->binding,
+ cur->descriptorType,
+ cur->descriptorCount,
+ cur->stageFlags,
+ (cur->useImmutableSampler ? &immutableSamplersPtr[0] : DE_NULL)
+ };
+
+ bindings.push_back(binding);
+ }
+ }
+ };
+
+ static Move<VkDescriptorSetLayout> create (const Environment& env, const Resources& res, const Parameters&)
+ {
+ const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutInfo =
+ {
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
+ DE_NULL,
+ (VkDescriptorSetLayoutCreateFlags)0,
+ (deUint32)res.bindings.size(),
+ (res.bindings.empty() ? DE_NULL : &res.bindings[0])
+ };
+
+ return createDescriptorSetLayout(env.vkd, env.device, &descriptorSetLayoutInfo);
+ }
+};
+
+struct PipelineLayout
+{
+ typedef VkPipelineLayout Type;
+
+ enum { MAX_CONCURRENT = DEFAULT_MAX_CONCURRENT_OBJECTS };
+
+ struct Parameters
+ {
+ vector<DescriptorSetLayout::Parameters> descriptorSetLayouts;
+ vector<VkPushConstantRange> pushConstantRanges;
+
+ Parameters (void) {}
+
+ static Parameters empty (void)
+ {
+ return Parameters();
+ }
+
+ static Parameters singleDescriptorSet (const DescriptorSetLayout::Parameters& descriptorSetLayout)
+ {
+ Parameters params;
+ params.descriptorSetLayouts.push_back(descriptorSetLayout);
+ return params;
+ }
+ };
+
+ struct Resources
+ {
+ typedef SharedPtr<Dependency<DescriptorSetLayout> > DescriptorSetLayoutDepSp;
+ typedef vector<DescriptorSetLayoutDepSp> DescriptorSetLayouts;
+
+ DescriptorSetLayouts descriptorSetLayouts;
+ vector<VkDescriptorSetLayout> pSetLayouts;
+
+ Resources (const Environment& env, const Parameters& params)
+ {
+ for (vector<DescriptorSetLayout::Parameters>::const_iterator dsParams = params.descriptorSetLayouts.begin();
+ dsParams != params.descriptorSetLayouts.end();
+ ++dsParams)
+ {
+ descriptorSetLayouts.push_back(DescriptorSetLayoutDepSp(new Dependency<DescriptorSetLayout>(env, *dsParams)));
+ pSetLayouts.push_back(*descriptorSetLayouts.back()->object);
+ }
+ }
+ };
+
+ static Move<VkPipelineLayout> create (const Environment& env, const Resources& res, const Parameters& params)
+ {
+ const VkPipelineLayoutCreateInfo pipelineLayoutInfo =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
+ DE_NULL,
+ (VkPipelineLayoutCreateFlags)0,
+ (deUint32)res.pSetLayouts.size(),
+ (res.pSetLayouts.empty() ? DE_NULL : &res.pSetLayouts[0]),
+ (deUint32)params.pushConstantRanges.size(),
+ (params.pushConstantRanges.empty() ? DE_NULL : ¶ms.pushConstantRanges[0]),
+ };
+
+ return createPipelineLayout(env.vkd, env.device, &pipelineLayoutInfo);
+ }
+};
+
+struct RenderPass
+{
+ typedef VkRenderPass Type;
+
+ enum { MAX_CONCURRENT = DEFAULT_MAX_CONCURRENT_OBJECTS };
+
+ // \todo [2015-09-17 pyry] More interesting configurations
+ struct Parameters
+ {
+ Parameters (void) {}
+ };
+
+ struct Resources
+ {
+ Resources (const Environment&, const Parameters&) {}
+ };
+
+ static Move<VkRenderPass> create (const Environment& env, const Resources&, const Parameters&)
+ {
+ const VkAttachmentDescription attachments[] =
+ {
+ {
+ (VkAttachmentDescriptionFlags)0,
+ VK_FORMAT_R8G8B8A8_UNORM,
+ VK_SAMPLE_COUNT_1_BIT,
+ VK_ATTACHMENT_LOAD_OP_CLEAR,
+ VK_ATTACHMENT_STORE_OP_STORE,
+ VK_ATTACHMENT_LOAD_OP_DONT_CARE,
+ VK_ATTACHMENT_STORE_OP_DONT_CARE,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ },
+ {
+ (VkAttachmentDescriptionFlags)0,
+ VK_FORMAT_D16_UNORM,
+ VK_SAMPLE_COUNT_1_BIT,
+ VK_ATTACHMENT_LOAD_OP_CLEAR,
+ VK_ATTACHMENT_STORE_OP_DONT_CARE,
+ VK_ATTACHMENT_LOAD_OP_DONT_CARE,
+ VK_ATTACHMENT_STORE_OP_DONT_CARE,
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
+ }
+ };
+ const VkAttachmentReference colorAttachments[] =
+ {
+ {
+ 0u, // attachment
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ }
+ };
+ const VkAttachmentReference dsAttachment =
+ {
+ 1u, // attachment
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
+ };
+ const VkSubpassDescription subpasses[] =
+ {
+ {
+ (VkSubpassDescriptionFlags)0,
+ VK_PIPELINE_BIND_POINT_GRAPHICS,
+ 0u, // inputAttachmentCount
+ DE_NULL, // pInputAttachments
+ DE_LENGTH_OF_ARRAY(colorAttachments),
+ colorAttachments,
+ DE_NULL, // pResolveAttachments
+ &dsAttachment,
+ 0u, // preserveAttachmentCount
+ DE_NULL, // pPreserveAttachments
+ }
+ };
+ const VkRenderPassCreateInfo renderPassInfo =
+ {
+ VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
+ DE_NULL,
+ (VkRenderPassCreateFlags)0,
+ DE_LENGTH_OF_ARRAY(attachments),
+ attachments,
+ DE_LENGTH_OF_ARRAY(subpasses),
+ subpasses,
+ 0u, // dependencyCount
+ DE_NULL // pDependencies
+ };
+
+ return createRenderPass(env.vkd, env.device, &renderPassInfo);
+ }
+};
+
+struct GraphicsPipeline
+{
+ typedef VkPipeline Type;
+
+ enum { MAX_CONCURRENT = DEFAULT_MAX_CONCURRENT_OBJECTS };
+
+ // \todo [2015-09-17 pyry] More interesting configurations
+ struct Parameters
+ {
+ Parameters (void) {}
+ };
+
+ struct Resources
+ {
+ Dependency<ShaderModule> vertexShader;
+ Dependency<ShaderModule> fragmentShader;
+ Dependency<PipelineLayout> layout;
+ Dependency<RenderPass> renderPass;
+ Dependency<PipelineCache> pipelineCache;
+
+ Resources (const Environment& env, const Parameters&)
+ : vertexShader (env, ShaderModule::Parameters(VK_SHADER_STAGE_VERTEX_BIT, "vert"))
+ , fragmentShader (env, ShaderModule::Parameters(VK_SHADER_STAGE_FRAGMENT_BIT, "frag"))
+ , layout (env, PipelineLayout::Parameters::singleDescriptorSet(
+ DescriptorSetLayout::Parameters::single(0u, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1u, VK_SHADER_STAGE_FRAGMENT_BIT, true)))
+ , renderPass (env, RenderPass::Parameters())
+ , pipelineCache (env, PipelineCache::Parameters())
+ {}
+ };
+
+ static void initPrograms (SourceCollections& dst, Parameters)
+ {
+ ShaderModule::initPrograms(dst, ShaderModule::Parameters(VK_SHADER_STAGE_VERTEX_BIT, "vert"));
+ ShaderModule::initPrograms(dst, ShaderModule::Parameters(VK_SHADER_STAGE_FRAGMENT_BIT, "frag"));
+ }
+
+ static Move<VkPipeline> create (const Environment& env, const Resources& res, const Parameters&)
+ {
+ const VkPipelineShaderStageCreateInfo stages[] =
+ {
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ DE_NULL,
+ (VkPipelineShaderStageCreateFlags)0,
+ VK_SHADER_STAGE_VERTEX_BIT,
+ *res.vertexShader.object,
+ "main",
+ DE_NULL, // pSpecializationInfo
+ },
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ DE_NULL,
+ (VkPipelineShaderStageCreateFlags)0,
+ VK_SHADER_STAGE_FRAGMENT_BIT,
+ *res.fragmentShader.object,
+ "main",
+ DE_NULL, // pSpecializationInfo
+ }
+ };
+ const VkVertexInputBindingDescription vertexBindings[] =
+ {
+ {
+ 0u, // binding
+ 16u, // stride
+ VK_VERTEX_INPUT_RATE_VERTEX
+ }
+ };
+ const VkVertexInputAttributeDescription vertexAttribs[] =
+ {
+ {
+ 0u, // location
+ 0u, // binding
+ VK_FORMAT_R32G32B32A32_SFLOAT,
+ 0u, // offset
+ }
+ };
+ const VkPipelineVertexInputStateCreateInfo vertexInputState =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
+ DE_NULL,
+ (VkPipelineVertexInputStateCreateFlags)0,
+ DE_LENGTH_OF_ARRAY(vertexBindings),
+ vertexBindings,
+ DE_LENGTH_OF_ARRAY(vertexAttribs),
+ vertexAttribs
+ };
+ const VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
+ DE_NULL,
+ (VkPipelineInputAssemblyStateCreateFlags)0,
+ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
+ VK_FALSE // primitiveRestartEnable
+ };
+ const VkViewport viewports[] =
+ {
+ { 0.0f, 0.0f, 64.f, 64.f, 0.0f, 1.0f }
+ };
+ const VkRect2D scissors[] =
+ {
+ { { 0, 0 }, { 64, 64 } }
+ };
+ const VkPipelineViewportStateCreateInfo viewportState =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
+ DE_NULL,
+ (VkPipelineViewportStateCreateFlags)0,
+ DE_LENGTH_OF_ARRAY(viewports),
+ viewports,
+ DE_LENGTH_OF_ARRAY(scissors),
+ scissors,
+ };
+ const VkPipelineRasterizationStateCreateInfo rasterState =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
+ DE_NULL,
+ (VkPipelineRasterizationStateCreateFlags)0,
+ VK_TRUE, // depthClampEnable
+ VK_FALSE, // rasterizerDiscardEnable
+ VK_POLYGON_MODE_FILL,
+ VK_CULL_MODE_BACK_BIT,
+ VK_FRONT_FACE_COUNTER_CLOCKWISE,
+ VK_FALSE, // depthBiasEnable
+ 0.0f, // depthBiasConstantFactor
+ 0.0f, // depthBiasClamp
+ 0.0f, // depthBiasSlopeFactor
+ 1.0f, // lineWidth
+ };
+ const VkPipelineMultisampleStateCreateInfo multisampleState =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
+ DE_NULL,
+ (VkPipelineMultisampleStateCreateFlags)0,
+ VK_SAMPLE_COUNT_1_BIT,
+ VK_FALSE, // sampleShadingEnable
+ 1.0f, // minSampleShading
+ DE_NULL, // pSampleMask
+ VK_FALSE, // alphaToCoverageEnable
+ VK_FALSE, // alphaToOneEnable
+ };
+ const VkPipelineDepthStencilStateCreateInfo depthStencilState =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
+ DE_NULL,
+ (VkPipelineDepthStencilStateCreateFlags)0,
+ VK_TRUE, // depthTestEnable
+ VK_TRUE, // depthWriteEnable
+ VK_COMPARE_OP_LESS, // depthCompareOp
+ VK_FALSE, // depthBoundsTestEnable
+ VK_FALSE, // stencilTestEnable
+ { VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_ALWAYS, 0u, 0u, 0u },
+ { VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_ALWAYS, 0u, 0u, 0u },
+ -1.0f, // minDepthBounds
+ +1.0f, // maxDepthBounds
+ };
+ const VkPipelineColorBlendAttachmentState colorBlendAttState[]=
+ {
+ {
+ VK_FALSE, // blendEnable
+ VK_BLEND_FACTOR_ONE,
+ VK_BLEND_FACTOR_ZERO,
+ VK_BLEND_OP_ADD,
+ VK_BLEND_FACTOR_ONE,
+ VK_BLEND_FACTOR_ZERO,
+ VK_BLEND_OP_ADD,
+ VK_COLOR_COMPONENT_R_BIT|VK_COLOR_COMPONENT_G_BIT|VK_COLOR_COMPONENT_B_BIT|VK_COLOR_COMPONENT_A_BIT
+ }
+ };
+ const VkPipelineColorBlendStateCreateInfo colorBlendState =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
+ DE_NULL,
+ (VkPipelineColorBlendStateCreateFlags)0,
+ VK_FALSE, // logicOpEnable
+ VK_LOGIC_OP_COPY,
+ DE_LENGTH_OF_ARRAY(colorBlendAttState),
+ colorBlendAttState,
+ { 0.0f, 0.0f, 0.0f, 0.0f } // blendConstants
+ };
+ const VkPipelineDynamicStateCreateInfo dynamicState =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
+ DE_NULL,
+ (VkPipelineDynamicStateCreateFlags)0,
+ 0u, // dynamicStateCount
+ DE_NULL, // pDynamicStates
+ };
+ const VkGraphicsPipelineCreateInfo pipelineInfo =
+ {
+ VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
+ DE_NULL,
+ (VkPipelineCreateFlags)0,
+ DE_LENGTH_OF_ARRAY(stages),
+ stages,
+ &vertexInputState,
+ &inputAssemblyState,
+ DE_NULL, // pTessellationState
+ &viewportState,
+ &rasterState,
+ &multisampleState,
+ &depthStencilState,
+ &colorBlendState,
+ &dynamicState,
+ *res.layout.object,
+ *res.renderPass.object,
+ 0u, // subpass
+ (VkPipeline)0, // basePipelineHandle
+ 0, // basePipelineIndex
+ };
+
+ return createGraphicsPipeline(env.vkd, env.device, *res.pipelineCache.object, &pipelineInfo);
+ }
+};
+
+struct ComputePipeline
+{
+ typedef VkPipeline Type;
+
+ enum { MAX_CONCURRENT = DEFAULT_MAX_CONCURRENT_OBJECTS };
+
+ // \todo [2015-09-17 pyry] More interesting configurations
+ struct Parameters
+ {
+ Parameters (void) {}
+ };
+
+ struct Resources
+ {
+ Dependency<ShaderModule> shaderModule;
+ Dependency<PipelineLayout> layout;
+ Dependency<PipelineCache> pipelineCache;
+
+ static DescriptorSetLayout::Parameters getDescriptorSetLayout (void)
+ {
+ typedef DescriptorSetLayout::Parameters::Binding Binding;
+
+ vector<Binding> bindings;
+
+ bindings.push_back(Binding(0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u, VK_SHADER_STAGE_COMPUTE_BIT, false));
+ bindings.push_back(Binding(1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u, VK_SHADER_STAGE_COMPUTE_BIT, false));
+
+ return DescriptorSetLayout::Parameters(bindings);
+ }
+
+ Resources (const Environment& env, const Parameters&)
+ : shaderModule (env, ShaderModule::Parameters(VK_SHADER_STAGE_COMPUTE_BIT, "comp"))
+ , layout (env, PipelineLayout::Parameters::singleDescriptorSet(getDescriptorSetLayout()))
+ , pipelineCache (env, PipelineCache::Parameters())
+ {}
+ };
+
+ static void initPrograms (SourceCollections& dst, Parameters)
+ {
+ ShaderModule::initPrograms(dst, ShaderModule::Parameters(VK_SHADER_STAGE_COMPUTE_BIT, "comp"));
+ }
+
+ static Move<VkPipeline> create (const Environment& env, const Resources& res, const Parameters&)
+ {
+ const VkComputePipelineCreateInfo pipelineInfo =
+ {
+ VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
+ DE_NULL,
+ (VkPipelineCreateFlags)0,
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ DE_NULL,
+ (VkPipelineShaderStageCreateFlags)0,
+ VK_SHADER_STAGE_COMPUTE_BIT,
+ *res.shaderModule.object,
+ "main",
+ DE_NULL // pSpecializationInfo
+ },
+ *res.layout.object,
+ (VkPipeline)0, // basePipelineHandle
+ 0u, // basePipelineIndex
+ };
+
+ return createComputePipeline(env.vkd, env.device, *res.pipelineCache.object, &pipelineInfo);
+ }
+};
+
+struct DescriptorPool
+{
+ typedef VkDescriptorPool Type;
+
+ enum { MAX_CONCURRENT = DEFAULT_MAX_CONCURRENT_OBJECTS };
+
+ struct Parameters
+ {
+ VkDescriptorPoolCreateFlags flags;
+ deUint32 maxSets;
+ vector<VkDescriptorPoolSize> poolSizes;
+
+ Parameters (VkDescriptorPoolCreateFlags flags_,
+ deUint32 maxSets_,
+ const vector<VkDescriptorPoolSize>& poolSizes_)
+ : flags (flags_)
+ , maxSets (maxSets_)
+ , poolSizes (poolSizes_)
+ {}
+
+ static Parameters singleType (VkDescriptorPoolCreateFlags flags,
+ deUint32 maxSets,
+ VkDescriptorType type,
+ deUint32 count)
+ {
+ vector<VkDescriptorPoolSize> poolSizes;
+ poolSizes.push_back(makeDescriptorPoolSize(type, count));
+ return Parameters(flags, maxSets, poolSizes);
+ }
+ };
+
+ struct Resources
+ {
+ Resources (const Environment&, const Parameters&) {}
+ };
+
+ static Move<VkDescriptorPool> create (const Environment& env, const Resources&, const Parameters& params)
+ {
+ const VkDescriptorPoolCreateInfo descriptorPoolInfo =
+ {
+ VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
+ DE_NULL,
+ params.flags,
+ params.maxSets,
+ (deUint32)params.poolSizes.size(),
+ (params.poolSizes.empty() ? DE_NULL : ¶ms.poolSizes[0])
+ };
+
+ return createDescriptorPool(env.vkd, env.device, &descriptorPoolInfo);
+ }
+};
+
+struct DescriptorSet
+{
+ typedef VkDescriptorSet Type;
+
+ enum { MAX_CONCURRENT = DEFAULT_MAX_CONCURRENT_OBJECTS };
+
+ struct Parameters
+ {
+ DescriptorSetLayout::Parameters descriptorSetLayout;
+
+ Parameters (const DescriptorSetLayout::Parameters& descriptorSetLayout_)
+ : descriptorSetLayout(descriptorSetLayout_)
+ {}
+ };
+
+ struct Resources
+ {
+ Dependency<DescriptorPool> descriptorPool;
+ Dependency<DescriptorSetLayout> descriptorSetLayout;
+
+ static vector<VkDescriptorPoolSize> computePoolSizes (const DescriptorSetLayout::Parameters& layout)
+ {
+ deUint32 countByType[VK_DESCRIPTOR_TYPE_LAST];
+ vector<VkDescriptorPoolSize> typeCounts;
+
+ std::fill(DE_ARRAY_BEGIN(countByType), DE_ARRAY_END(countByType), 0u);
+
+ for (vector<DescriptorSetLayout::Parameters::Binding>::const_iterator cur = layout.bindings.begin();
+ cur != layout.bindings.end();
+ ++cur)
+ {
+ DE_ASSERT((deUint32)cur->descriptorType < VK_DESCRIPTOR_TYPE_LAST);
+ countByType[cur->descriptorType] += cur->descriptorCount;
+ }
+
+ for (deUint32 type = 0; type < VK_DESCRIPTOR_TYPE_LAST; ++type)
+ {
+ if (countByType[type] > 0)
+ typeCounts.push_back(makeDescriptorPoolSize((VkDescriptorType)type, countByType[type]));
+ }
+
+ return typeCounts;
+ }
+
+ Resources (const Environment& env, const Parameters& params)
+ : descriptorPool (env, DescriptorPool::Parameters(VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, env.maxResourceConsumers, computePoolSizes(params.descriptorSetLayout)))
+ , descriptorSetLayout (env, params.descriptorSetLayout)
+ {
+ }
+ };
+
+ static Move<VkDescriptorSet> create (const Environment& env, const Resources& res, const Parameters&)
+ {
+ const VkDescriptorSetAllocateInfo allocateInfo =
+ {
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+ DE_NULL,
+ *res.descriptorPool.object,
+ 1u,
+ &res.descriptorSetLayout.object.get(),
+ };
+
+ return allocateDescriptorSet(env.vkd, env.device, &allocateInfo);
+ }
+};
+
+struct Framebuffer
+{
+ typedef VkFramebuffer Type;
+
+ enum { MAX_CONCURRENT = DEFAULT_MAX_CONCURRENT_OBJECTS };
+
+ struct Parameters
+ {
+ Parameters (void)
+ {}
+ };
+
+ struct Resources
+ {
+ Dependency<ImageView> colorAttachment;
+ Dependency<ImageView> depthStencilAttachment;
+ Dependency<RenderPass> renderPass;
+
+ Resources (const Environment& env, const Parameters&)
+ : colorAttachment (env, ImageView::Parameters(Image::Parameters(0u, VK_IMAGE_TYPE_2D, VK_FORMAT_R8G8B8A8_UNORM,
+ makeExtent3D(256, 256, 1),
+ 1u, 1u,
+ VK_SAMPLE_COUNT_1_BIT,
+ VK_IMAGE_TILING_OPTIMAL,
+ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
+ VK_IMAGE_LAYOUT_UNDEFINED),
+ VK_IMAGE_VIEW_TYPE_2D, VK_FORMAT_R8G8B8A8_UNORM,
+ makeComponentMappingRGBA(),
+ makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u)))
+ , depthStencilAttachment (env, ImageView::Parameters(Image::Parameters(0u, VK_IMAGE_TYPE_2D, VK_FORMAT_D16_UNORM,
+ makeExtent3D(256, 256, 1),
+ 1u, 1u,
+ VK_SAMPLE_COUNT_1_BIT,
+ VK_IMAGE_TILING_OPTIMAL,
+ VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
+ VK_IMAGE_LAYOUT_UNDEFINED),
+ VK_IMAGE_VIEW_TYPE_2D, VK_FORMAT_D16_UNORM,
+ makeComponentMappingRGBA(),
+ makeImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u)))
+ , renderPass (env, RenderPass::Parameters())
+ {}
+ };
+
+ static Move<VkFramebuffer> create (const Environment& env, const Resources& res, const Parameters&)
+ {
+ const VkImageView attachments[] =
+ {
+ *res.colorAttachment.object,
+ *res.depthStencilAttachment.object,
+ };
+ const VkFramebufferCreateInfo framebufferInfo =
+ {
+ VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
+ DE_NULL,
+ (VkFramebufferCreateFlags)0,
+ *res.renderPass.object,
+ (deUint32)DE_LENGTH_OF_ARRAY(attachments),
+ attachments,
+ 256u, // width
+ 256u, // height
+ 1u // layers
+ };
+
+ return createFramebuffer(env.vkd, env.device, &framebufferInfo);
+ }
+};
+
+struct CommandPool
+{
+ typedef VkCommandPool Type;
+
+ enum { MAX_CONCURRENT = DEFAULT_MAX_CONCURRENT_OBJECTS };
+
+ struct Parameters
+ {
+ VkCommandPoolCreateFlags flags;
+
+ Parameters (VkCommandPoolCreateFlags flags_)
+ : flags(flags_)
+ {}
+ };
+
+ struct Resources
+ {
+ Resources (const Environment&, const Parameters&) {}
+ };
+
+ static Move<VkCommandPool> create (const Environment& env, const Resources&, const Parameters& params)
+ {
+ const VkCommandPoolCreateInfo cmdPoolInfo =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
+ DE_NULL,
+ params.flags,
+ env.queueFamilyIndex,
+ };
+
+ return createCommandPool(env.vkd, env.device, &cmdPoolInfo);
+ }
+};
+
+struct CommandBuffer
+{
+ typedef VkCommandBuffer Type;
+
+ enum { MAX_CONCURRENT = DEFAULT_MAX_CONCURRENT_OBJECTS };
+
+ struct Parameters
+ {
+ CommandPool::Parameters commandPool;
+ VkCommandBufferLevel level;
+
+ Parameters (const CommandPool::Parameters& commandPool_,
+ VkCommandBufferLevel level_)
+ : commandPool (commandPool_)
+ , level (level_)
+ {}
+ };
+
+ struct Resources
+ {
+ Dependency<CommandPool> commandPool;
+
+ Resources (const Environment& env, const Parameters& params)
+ : commandPool(env, params.commandPool)
+ {}
+ };
+
+ static Move<VkCommandBuffer> create (const Environment& env, const Resources& res, const Parameters& params)
+ {
+ const VkCommandBufferAllocateInfo cmdBufferInfo =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
+ DE_NULL,
+ *res.commandPool.object,
+ params.level,
+ 1, // bufferCount
+ };
+
+ return allocateCommandBuffer(env.vkd, env.device, &cmdBufferInfo);
+ }
+};
+
+// Test cases
+
+template<typename Object>
+tcu::TestStatus createSingleTest (Context& context, typename Object::Parameters params)
+{
+ const Environment env (context, 1u);
+ const typename Object::Resources res (env, params);
+
+ {
+ Unique<typename Object::Type> obj (Object::create(env, res, params));
+ }
+
+ return tcu::TestStatus::pass("Ok");
+}
+
+template<typename Object>
+tcu::TestStatus createMultipleUniqueResourcesTest (Context& context, typename Object::Parameters params)
+{
+ const Environment env (context, 1u);
+ const typename Object::Resources res0 (env, params);
+ const typename Object::Resources res1 (env, params);
+ const typename Object::Resources res2 (env, params);
+ const typename Object::Resources res3 (env, params);
+
+ {
+ Unique<typename Object::Type> obj0 (Object::create(env, res0, params));
+ Unique<typename Object::Type> obj1 (Object::create(env, res1, params));
+ Unique<typename Object::Type> obj2 (Object::create(env, res2, params));
+ Unique<typename Object::Type> obj3 (Object::create(env, res3, params));
+ }
+
+ return tcu::TestStatus::pass("Ok");
+}
+
+template<typename Object>
+tcu::TestStatus createMultipleSharedResourcesTest (Context& context, typename Object::Parameters params)
+{
+ const Environment env (context, 4u);
+ const typename Object::Resources res (env, params);
+
+ {
+ Unique<typename Object::Type> obj0 (Object::create(env, res, params));
+ Unique<typename Object::Type> obj1 (Object::create(env, res, params));
+ Unique<typename Object::Type> obj2 (Object::create(env, res, params));
+ Unique<typename Object::Type> obj3 (Object::create(env, res, params));
+ }
+
+ return tcu::TestStatus::pass("Ok");
+}
+
+template<typename Object>
+tcu::TestStatus createMaxConcurrentTest (Context& context, typename Object::Parameters params)
+{
+ typedef Unique<typename Object::Type> UniqueObject;
+ typedef SharedPtr<UniqueObject> ObjectPtr;
+
+ const deUint32 numObjects = Object::MAX_CONCURRENT;
+ const Environment env (context, numObjects);
+ const typename Object::Resources res (env, params);
+ vector<ObjectPtr> objects (numObjects);
+
+ context.getTestContext().getLog()
+ << TestLog::Message << "Creating " << numObjects << " " << getTypeName<typename Object::Type>() << "s" << TestLog::EndMessage;
+
+ for (deUint32 ndx = 0; ndx < numObjects; ndx++)
+ objects[ndx] = ObjectPtr(new UniqueObject(Object::create(env, res, params)));
+
+ objects.clear();
+
+ return tcu::TestStatus::pass("Ok");
+}
+
+template<typename Object>
+class CreateThread : public ThreadGroupThread
+{
+public:
+ CreateThread (const Environment& env, const typename Object::Resources& resources, const typename Object::Parameters& params)
+ : m_env (env)
+ , m_resources (resources)
+ , m_params (params)
+ {}
+
+ void runThread (void)
+ {
+ const int numIters = 100;
+ const int itersBetweenSyncs = 20;
+
+ for (int iterNdx = 0; iterNdx < numIters; iterNdx++)
+ {
+ // Sync every Nth iteration to make entering driver at the same time more likely
+ if ((iterNdx % itersBetweenSyncs) == 0)
+ barrier();
+
+ {
+ Unique<typename Object::Type> obj (Object::create(m_env, m_resources, m_params));
+ }
+ }
+ }
+
+private:
+ const Environment& m_env;
+ const typename Object::Resources& m_resources;
+ const typename Object::Parameters& m_params;
+};
+
+template<typename Object>
+tcu::TestStatus multithreadedCreateSharedResourcesTest (Context& context, typename Object::Parameters params)
+{
+ const deUint32 numThreads = getDefaultTestThreadCount();
+ const Environment env (context, numThreads);
+ const typename Object::Resources res (env, params);
+ ThreadGroup threads;
+
+ for (deUint32 ndx = 0; ndx < numThreads; ndx++)
+ threads.add(MovePtr<ThreadGroupThread>(new CreateThread<Object>(env, res, params)));
+
+ return threads.run();
+}
+
+template<typename Object>
+tcu::TestStatus multithreadedCreatePerThreadResourcesTest (Context& context, typename Object::Parameters params)
+{
+ typedef SharedPtr<typename Object::Resources> ResPtr;
+
+ const deUint32 numThreads = getDefaultTestThreadCount();
+ const Environment env (context, 1u);
+ vector<ResPtr> resources (numThreads);
+ ThreadGroup threads;
+
+ for (deUint32 ndx = 0; ndx < numThreads; ndx++)
+ {
+ resources[ndx] = ResPtr(new typename Object::Resources(env, params));
+ threads.add(MovePtr<ThreadGroupThread>(new CreateThread<Object>(env, *resources[ndx], params)));
+ }
+
+ return threads.run();
+}
+
+struct EnvClone
+{
+ Device::Resources deviceRes;
+ Unique<VkDevice> device;
+ DeviceDriver vkd;
+ Environment env;
+
+ EnvClone (const Environment& parent, const Device::Parameters& deviceParams, deUint32 maxResourceConsumers)
+ : deviceRes (parent, deviceParams)
+ , device (Device::create(parent, deviceRes, deviceParams))
+ , vkd (deviceRes.vki, *device)
+ , env (parent.vkp, vkd, *device, deviceRes.queueFamilyIndex, parent.programBinaries, maxResourceConsumers)
+ {
+ }
+};
+
+template<typename Object>
+tcu::TestStatus multithreadedCreatePerThreadDeviceTest (Context& context, typename Object::Parameters params)
+{
+ typedef SharedPtr<EnvClone> EnvPtr;
+ typedef SharedPtr<typename Object::Resources> ResPtr;
+
+ const deUint32 numThreads = getDefaultTestThreadCount();
+ const Device::Parameters deviceParams (context.getTestContext().getCommandLine().getVKDeviceId()-1u, VK_QUEUE_GRAPHICS_BIT|VK_QUEUE_COMPUTE_BIT);
+ const Environment sharedEnv (context, numThreads); // For creating Device's
+ vector<EnvPtr> perThreadEnv (numThreads);
+ vector<ResPtr> resources (numThreads);
+ ThreadGroup threads;
+
+ for (deUint32 ndx = 0; ndx < numThreads; ndx++)
+ {
+ perThreadEnv[ndx] = EnvPtr(new EnvClone(sharedEnv, deviceParams, 1u));
+ resources[ndx] = ResPtr(new typename Object::Resources(perThreadEnv[ndx]->env, params));
+
+ threads.add(MovePtr<ThreadGroupThread>(new CreateThread<Object>(perThreadEnv[ndx]->env, *resources[ndx], params)));
+ }
+
+ return threads.run();
+}
+
+// Utilities for creating groups
+
+template<typename Object>
+struct NamedParameters
+{
+ const char* name;
+ typename Object::Parameters parameters;
+};
+
+template<typename Object>
+struct CaseDescription
+{
+ typename FunctionInstance1<typename Object::Parameters>::Function function;
+ const NamedParameters<Object>* paramsBegin;
+ const NamedParameters<Object>* paramsEnd;
+};
+
+#define EMPTY_CASE_DESC(OBJECT) \
+ { (FunctionInstance1<OBJECT::Parameters>::Function)DE_NULL, DE_NULL, DE_NULL }
+
+#define CASE_DESC(FUNCTION, CASES) \
+ { FUNCTION, DE_ARRAY_BEGIN(CASES), DE_ARRAY_END(CASES) }
+
+struct CaseDescriptions
+{
+ CaseDescription<Instance> instance;
+ CaseDescription<Device> device;
+ CaseDescription<DeviceMemory> deviceMemory;
+ CaseDescription<Buffer> buffer;
+ CaseDescription<BufferView> bufferView;
+ CaseDescription<Image> image;
+ CaseDescription<ImageView> imageView;
+ CaseDescription<Semaphore> semaphore;
+ CaseDescription<Event> event;
+ CaseDescription<Fence> fence;
+ CaseDescription<QueryPool> queryPool;
+ CaseDescription<ShaderModule> shaderModule;
+ CaseDescription<PipelineCache> pipelineCache;
+ CaseDescription<PipelineLayout> pipelineLayout;
+ CaseDescription<RenderPass> renderPass;
+ CaseDescription<GraphicsPipeline> graphicsPipeline;
+ CaseDescription<ComputePipeline> computePipeline;
+ CaseDescription<DescriptorSetLayout> descriptorSetLayout;
+ CaseDescription<Sampler> sampler;
+ CaseDescription<DescriptorPool> descriptorPool;
+ CaseDescription<DescriptorSet> descriptorSet;
+ CaseDescription<Framebuffer> framebuffer;
+ CaseDescription<CommandPool> commandPool;
+ CaseDescription<CommandBuffer> commandBuffer;
+};
+
+template<typename Object>
+void addCases (const MovePtr<tcu::TestCaseGroup>& group, const CaseDescription<Object>& cases)
+{
+ for (const NamedParameters<Object>* cur = cases.paramsBegin; cur != cases.paramsEnd; ++cur)
+ addFunctionCase(group.get(), cur->name, "", cases.function, cur->parameters);
+}
+
+template<typename Object>
+void addCasesWithProgs (const MovePtr<tcu::TestCaseGroup>& group, const CaseDescription<Object>& cases)
+{
+ for (const NamedParameters<Object>* cur = cases.paramsBegin; cur != cases.paramsEnd; ++cur)
+ addFunctionCaseWithPrograms(group.get(), cur->name, "", Object::initPrograms, cases.function, cur->parameters);
+}
+
+tcu::TestCaseGroup* createGroup (tcu::TestContext& testCtx, const char* name, const char* desc, const CaseDescriptions& cases)
+{
+ MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, name, desc));
+
+ addCases (group, cases.instance);
+ addCases (group, cases.device);
+ addCases (group, cases.deviceMemory);
+ addCases (group, cases.buffer);
+ addCases (group, cases.bufferView);
+ addCases (group, cases.image);
+ addCases (group, cases.imageView);
+ addCases (group, cases.semaphore);
+ addCases (group, cases.event);
+ addCases (group, cases.fence);
+ addCases (group, cases.queryPool);
+ addCases (group, cases.sampler);
+ addCasesWithProgs (group, cases.shaderModule);
+ addCases (group, cases.pipelineCache);
+ addCases (group, cases.pipelineLayout);
+ addCases (group, cases.renderPass);
+ addCasesWithProgs (group, cases.graphicsPipeline);
+ addCasesWithProgs (group, cases.computePipeline);
+ addCases (group, cases.descriptorSetLayout);
+ addCases (group, cases.descriptorPool);
+ addCases (group, cases.descriptorSet);
+ addCases (group, cases.framebuffer);
+ addCases (group, cases.commandPool);
+ addCases (group, cases.commandBuffer);
+
+ return group.release();
+}
+
+} // anonymous
+
+tcu::TestCaseGroup* createObjectManagementTests (tcu::TestContext& testCtx)
+{
+ MovePtr<tcu::TestCaseGroup> objectMgmtTests (new tcu::TestCaseGroup(testCtx, "object_management", "Object management tests"));
+
+ const Image::Parameters img1D (0u, VK_IMAGE_TYPE_1D, VK_FORMAT_R8G8B8A8_UNORM, makeExtent3D(256, 1, 1), 1u, 4u, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_UNDEFINED);
+ const Image::Parameters img2D (0u, VK_IMAGE_TYPE_2D, VK_FORMAT_R8G8B8A8_UNORM, makeExtent3D( 64, 64, 1), 1u, 12u, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_SAMPLED_BIT|VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_LAYOUT_UNDEFINED);
+ const Image::Parameters imgCube (VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT, VK_IMAGE_TYPE_2D, VK_FORMAT_R8G8B8A8_UNORM, makeExtent3D( 64, 64, 1), 1u, 12u, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_SAMPLED_BIT|VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_LAYOUT_UNDEFINED);
+ const Image::Parameters img3D (0u, VK_IMAGE_TYPE_3D, VK_FORMAT_R8G8B8A8_UNORM, makeExtent3D( 64, 64, 4), 1u, 1u, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_UNDEFINED);
+ const ImageView::Parameters imgView1D (img1D, VK_IMAGE_VIEW_TYPE_1D, img1D.format, makeComponentMappingRGBA(), makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
+ const ImageView::Parameters imgView1DArr (img1D, VK_IMAGE_VIEW_TYPE_1D_ARRAY, img1D.format, makeComponentMappingRGBA(), makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 4u));
+ const ImageView::Parameters imgView2D (img2D, VK_IMAGE_VIEW_TYPE_2D, img2D.format, makeComponentMappingRGBA(), makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
+ const ImageView::Parameters imgView2DArr (img2D, VK_IMAGE_VIEW_TYPE_2D_ARRAY, img2D.format, makeComponentMappingRGBA(), makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 8u));
+ const ImageView::Parameters imgViewCube (imgCube, VK_IMAGE_VIEW_TYPE_CUBE, img2D.format, makeComponentMappingRGBA(), makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 6u));
+ const ImageView::Parameters imgViewCubeArr (imgCube, VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, img2D.format, makeComponentMappingRGBA(), makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 12u));
+ const ImageView::Parameters imgView3D (img3D, VK_IMAGE_VIEW_TYPE_3D, img3D.format, makeComponentMappingRGBA(), makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
+
+ const DescriptorSetLayout::Parameters singleUboDescLayout = DescriptorSetLayout::Parameters::single(0u, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u, VK_SHADER_STAGE_VERTEX_BIT);
+
+ static NamedParameters<Instance> s_instanceCases[] =
+ {
+ { "instance", Instance::Parameters() },
+ };
+ // \note Device index may change - must not be static
+ const NamedParameters<Device> s_deviceCases[] =
+ {
+ { "device", Device::Parameters(testCtx.getCommandLine().getVKDeviceId()-1u, VK_QUEUE_GRAPHICS_BIT) },
+ };
+ static const NamedParameters<DeviceMemory> s_deviceMemCases[] =
+ {
+ { "device_memory_small", DeviceMemory::Parameters(1024, 0u) },
+ };
+ static const NamedParameters<Buffer> s_bufferCases[] =
+ {
+ { "buffer_uniform_small", Buffer::Parameters(1024u, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT), },
+ { "buffer_uniform_large", Buffer::Parameters(1024u*1024u*16u, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT), },
+ { "buffer_storage_small", Buffer::Parameters(1024u, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), },
+ { "buffer_storage_large", Buffer::Parameters(1024u*1024u*16u, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), },
+ };
+ static const NamedParameters<BufferView> s_bufferViewCases[] =
+ {
+ { "buffer_view_uniform_r8g8b8a8_unorm", BufferView::Parameters(Buffer::Parameters(8192u, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT), VK_FORMAT_R8G8B8A8_UNORM, 0u, 4096u) },
+ { "buffer_view_storage_r8g8b8a8_unorm", BufferView::Parameters(Buffer::Parameters(8192u, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT), VK_FORMAT_R8G8B8A8_UNORM, 0u, 4096u) },
+ };
+ static const NamedParameters<Image> s_imageCases[] =
+ {
+ { "image_1d", img1D },
+ { "image_2d", img2D },
+ { "image_3d", img3D },
+ };
+ static const NamedParameters<ImageView> s_imageViewCases[] =
+ {
+ { "image_view_1d", imgView1D },
+ { "image_view_1d_arr", imgView1DArr },
+ { "image_view_2d", imgView2D },
+ { "image_view_2d_arr", imgView2DArr },
+ { "image_view_cube", imgViewCube },
+ { "image_view_cube_arr", imgViewCubeArr },
+ { "image_view_3d", imgView3D },
+ };
+ static const NamedParameters<Semaphore> s_semaphoreCases[] =
+ {
+ { "semaphore", Semaphore::Parameters(0u), }
+ };
+ static const NamedParameters<Event> s_eventCases[] =
+ {
+ { "event", Event::Parameters(0u) }
+ };
+ static const NamedParameters<Fence> s_fenceCases[] =
+ {
+ { "fence", Fence::Parameters(0u) },
+ { "fence_signaled", Fence::Parameters(VK_FENCE_CREATE_SIGNALED_BIT) }
+ };
+ static const NamedParameters<QueryPool> s_queryPoolCases[] =
+ {
+ { "query_pool", QueryPool::Parameters(VK_QUERY_TYPE_OCCLUSION, 1u, 0u) }
+ };
+ static const NamedParameters<ShaderModule> s_shaderModuleCases[] =
+ {
+ { "shader_module", ShaderModule::Parameters(VK_SHADER_STAGE_COMPUTE_BIT, "test") }
+ };
+ static const NamedParameters<PipelineCache> s_pipelineCacheCases[] =
+ {
+ { "pipeline_cache", PipelineCache::Parameters() }
+ };
+ static const NamedParameters<PipelineLayout> s_pipelineLayoutCases[] =
+ {
+ { "pipeline_layout_empty", PipelineLayout::Parameters::empty() },
+ { "pipeline_layout_single", PipelineLayout::Parameters::singleDescriptorSet(singleUboDescLayout) }
+ };
+ static const NamedParameters<RenderPass> s_renderPassCases[] =
+ {
+ { "render_pass", RenderPass::Parameters() }
+ };
+ static const NamedParameters<GraphicsPipeline> s_graphicsPipelineCases[] =
+ {
+ { "graphics_pipeline", GraphicsPipeline::Parameters() }
+ };
+ static const NamedParameters<ComputePipeline> s_computePipelineCases[] =
+ {
+ { "compute_pipeline", ComputePipeline::Parameters() }
+ };
+ static const NamedParameters<DescriptorSetLayout> s_descriptorSetLayoutCases[] =
+ {
+ { "descriptor_set_layout_empty", DescriptorSetLayout::Parameters::empty() },
+ { "descriptor_set_layout_single", singleUboDescLayout }
+ };
+ static const NamedParameters<Sampler> s_samplerCases[] =
+ {
+ { "sampler", Sampler::Parameters() }
+ };
+ static const NamedParameters<DescriptorPool> s_descriptorPoolCases[] =
+ {
+ { "descriptor_pool", DescriptorPool::Parameters::singleType((VkDescriptorPoolCreateFlags)0, 4u, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3u) },
+ { "descriptor_pool_free_descriptor_set", DescriptorPool::Parameters::singleType(VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 4u, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3u) }
+ };
+ static const NamedParameters<DescriptorSet> s_descriptorSetCases[] =
+ {
+ { "descriptor_set", DescriptorSet::Parameters(singleUboDescLayout) }
+ };
+ static const NamedParameters<Framebuffer> s_framebufferCases[] =
+ {
+ { "framebuffer", Framebuffer::Parameters() }
+ };
+ static const NamedParameters<CommandPool> s_commandPoolCases[] =
+ {
+ { "command_pool", CommandPool::Parameters((VkCommandPoolCreateFlags)0) },
+ { "command_pool_transient", CommandPool::Parameters(VK_COMMAND_POOL_CREATE_TRANSIENT_BIT) }
+ };
+ static const NamedParameters<CommandBuffer> s_commandBufferCases[] =
+ {
+ { "command_buffer_primary", CommandBuffer::Parameters(CommandPool::Parameters((VkCommandPoolCreateFlags)0u), VK_COMMAND_BUFFER_LEVEL_PRIMARY) },
+ { "command_buffer_secondary", CommandBuffer::Parameters(CommandPool::Parameters((VkCommandPoolCreateFlags)0u), VK_COMMAND_BUFFER_LEVEL_SECONDARY) }
+ };
+
+ static const CaseDescriptions s_createSingleGroup =
+ {
+ CASE_DESC(createSingleTest <Instance>, s_instanceCases),
+ CASE_DESC(createSingleTest <Device>, s_deviceCases),
+ CASE_DESC(createSingleTest <DeviceMemory>, s_deviceMemCases),
+ CASE_DESC(createSingleTest <Buffer>, s_bufferCases),
+ CASE_DESC(createSingleTest <BufferView>, s_bufferViewCases),
+ CASE_DESC(createSingleTest <Image>, s_imageCases),
+ CASE_DESC(createSingleTest <ImageView>, s_imageViewCases),
+ CASE_DESC(createSingleTest <Semaphore>, s_semaphoreCases),
+ CASE_DESC(createSingleTest <Event>, s_eventCases),
+ CASE_DESC(createSingleTest <Fence>, s_fenceCases),
+ CASE_DESC(createSingleTest <QueryPool>, s_queryPoolCases),
+ CASE_DESC(createSingleTest <ShaderModule>, s_shaderModuleCases),
+ CASE_DESC(createSingleTest <PipelineCache>, s_pipelineCacheCases),
+ CASE_DESC(createSingleTest <PipelineLayout>, s_pipelineLayoutCases),
+ CASE_DESC(createSingleTest <RenderPass>, s_renderPassCases),
+ CASE_DESC(createSingleTest <GraphicsPipeline>, s_graphicsPipelineCases),
+ CASE_DESC(createSingleTest <ComputePipeline>, s_computePipelineCases),
+ CASE_DESC(createSingleTest <DescriptorSetLayout>, s_descriptorSetLayoutCases),
+ CASE_DESC(createSingleTest <Sampler>, s_samplerCases),
+ CASE_DESC(createSingleTest <DescriptorPool>, s_descriptorPoolCases),
+ CASE_DESC(createSingleTest <DescriptorSet>, s_descriptorSetCases),
+ CASE_DESC(createSingleTest <Framebuffer>, s_framebufferCases),
+ CASE_DESC(createSingleTest <CommandPool>, s_commandPoolCases),
+ CASE_DESC(createSingleTest <CommandBuffer>, s_commandBufferCases),
+ };
+ objectMgmtTests->addChild(createGroup(testCtx, "single", "Create single object", s_createSingleGroup));
+
+ static const CaseDescriptions s_createMultipleUniqueResourcesGroup =
+ {
+ CASE_DESC(createMultipleUniqueResourcesTest <Instance>, s_instanceCases),
+ CASE_DESC(createMultipleUniqueResourcesTest <Device>, s_deviceCases),
+ CASE_DESC(createMultipleUniqueResourcesTest <DeviceMemory>, s_deviceMemCases),
+ CASE_DESC(createMultipleUniqueResourcesTest <Buffer>, s_bufferCases),
+ CASE_DESC(createMultipleUniqueResourcesTest <BufferView>, s_bufferViewCases),
+ CASE_DESC(createMultipleUniqueResourcesTest <Image>, s_imageCases),
+ CASE_DESC(createMultipleUniqueResourcesTest <ImageView>, s_imageViewCases),
+ CASE_DESC(createMultipleUniqueResourcesTest <Semaphore>, s_semaphoreCases),
+ CASE_DESC(createMultipleUniqueResourcesTest <Event>, s_eventCases),
+ CASE_DESC(createMultipleUniqueResourcesTest <Fence>, s_fenceCases),
+ CASE_DESC(createMultipleUniqueResourcesTest <QueryPool>, s_queryPoolCases),
+ CASE_DESC(createMultipleUniqueResourcesTest <ShaderModule>, s_shaderModuleCases),
+ CASE_DESC(createMultipleUniqueResourcesTest <PipelineCache>, s_pipelineCacheCases),
+ CASE_DESC(createMultipleUniqueResourcesTest <PipelineLayout>, s_pipelineLayoutCases),
+ CASE_DESC(createMultipleUniqueResourcesTest <RenderPass>, s_renderPassCases),
+ CASE_DESC(createMultipleUniqueResourcesTest <GraphicsPipeline>, s_graphicsPipelineCases),
+ CASE_DESC(createMultipleUniqueResourcesTest <ComputePipeline>, s_computePipelineCases),
+ CASE_DESC(createMultipleUniqueResourcesTest <DescriptorSetLayout>, s_descriptorSetLayoutCases),
+ CASE_DESC(createMultipleUniqueResourcesTest <Sampler>, s_samplerCases),
+ CASE_DESC(createMultipleUniqueResourcesTest <DescriptorPool>, s_descriptorPoolCases),
+ CASE_DESC(createMultipleUniqueResourcesTest <DescriptorSet>, s_descriptorSetCases),
+ CASE_DESC(createMultipleUniqueResourcesTest <Framebuffer>, s_framebufferCases),
+ CASE_DESC(createMultipleUniqueResourcesTest <CommandPool>, s_commandPoolCases),
+ CASE_DESC(createMultipleUniqueResourcesTest <CommandBuffer>, s_commandBufferCases),
+ };
+ objectMgmtTests->addChild(createGroup(testCtx, "multiple_unique_resources", "Multiple objects with per-object unique resources", s_createMultipleUniqueResourcesGroup));
+
+ static const CaseDescriptions s_createMultipleSharedResourcesGroup =
+ {
+ EMPTY_CASE_DESC(Instance), // No resources used
+ CASE_DESC(createMultipleSharedResourcesTest <Device>, s_deviceCases),
+ CASE_DESC(createMultipleSharedResourcesTest <DeviceMemory>, s_deviceMemCases),
+ CASE_DESC(createMultipleSharedResourcesTest <Buffer>, s_bufferCases),
+ CASE_DESC(createMultipleSharedResourcesTest <BufferView>, s_bufferViewCases),
+ CASE_DESC(createMultipleSharedResourcesTest <Image>, s_imageCases),
+ CASE_DESC(createMultipleSharedResourcesTest <ImageView>, s_imageViewCases),
+ CASE_DESC(createMultipleSharedResourcesTest <Semaphore>, s_semaphoreCases),
+ CASE_DESC(createMultipleSharedResourcesTest <Event>, s_eventCases),
+ CASE_DESC(createMultipleSharedResourcesTest <Fence>, s_fenceCases),
+ CASE_DESC(createMultipleSharedResourcesTest <QueryPool>, s_queryPoolCases),
+ CASE_DESC(createMultipleSharedResourcesTest <ShaderModule>, s_shaderModuleCases),
+ CASE_DESC(createMultipleSharedResourcesTest <PipelineCache>, s_pipelineCacheCases),
+ CASE_DESC(createMultipleSharedResourcesTest <PipelineLayout>, s_pipelineLayoutCases),
+ CASE_DESC(createMultipleSharedResourcesTest <RenderPass>, s_renderPassCases),
+ CASE_DESC(createMultipleSharedResourcesTest <GraphicsPipeline>, s_graphicsPipelineCases),
+ CASE_DESC(createMultipleSharedResourcesTest <ComputePipeline>, s_computePipelineCases),
+ CASE_DESC(createMultipleSharedResourcesTest <DescriptorSetLayout>, s_descriptorSetLayoutCases),
+ CASE_DESC(createMultipleSharedResourcesTest <Sampler>, s_samplerCases),
+ CASE_DESC(createMultipleSharedResourcesTest <DescriptorPool>, s_descriptorPoolCases),
+ CASE_DESC(createMultipleSharedResourcesTest <DescriptorSet>, s_descriptorSetCases),
+ CASE_DESC(createMultipleSharedResourcesTest <Framebuffer>, s_framebufferCases),
+ CASE_DESC(createMultipleSharedResourcesTest <CommandPool>, s_commandPoolCases),
+ CASE_DESC(createMultipleSharedResourcesTest <CommandBuffer>, s_commandBufferCases),
+ };
+ objectMgmtTests->addChild(createGroup(testCtx, "multiple_shared_resources", "Multiple objects with shared resources", s_createMultipleSharedResourcesGroup));
+
+ static const CaseDescriptions s_createMaxConcurrentGroup =
+ {
+ CASE_DESC(createMaxConcurrentTest <Instance>, s_instanceCases),
+ CASE_DESC(createMaxConcurrentTest <Device>, s_deviceCases),
+ CASE_DESC(createMaxConcurrentTest <DeviceMemory>, s_deviceMemCases),
+ CASE_DESC(createMaxConcurrentTest <Buffer>, s_bufferCases),
+ CASE_DESC(createMaxConcurrentTest <BufferView>, s_bufferViewCases),
+ CASE_DESC(createMaxConcurrentTest <Image>, s_imageCases),
+ CASE_DESC(createMaxConcurrentTest <ImageView>, s_imageViewCases),
+ CASE_DESC(createMaxConcurrentTest <Semaphore>, s_semaphoreCases),
+ CASE_DESC(createMaxConcurrentTest <Event>, s_eventCases),
+ CASE_DESC(createMaxConcurrentTest <Fence>, s_fenceCases),
+ CASE_DESC(createMaxConcurrentTest <QueryPool>, s_queryPoolCases),
+ CASE_DESC(createMaxConcurrentTest <ShaderModule>, s_shaderModuleCases),
+ CASE_DESC(createMaxConcurrentTest <PipelineCache>, s_pipelineCacheCases),
+ CASE_DESC(createMaxConcurrentTest <PipelineLayout>, s_pipelineLayoutCases),
+ CASE_DESC(createMaxConcurrentTest <RenderPass>, s_renderPassCases),
+ CASE_DESC(createMaxConcurrentTest <GraphicsPipeline>, s_graphicsPipelineCases),
+ CASE_DESC(createMaxConcurrentTest <ComputePipeline>, s_computePipelineCases),
+ CASE_DESC(createMaxConcurrentTest <DescriptorSetLayout>, s_descriptorSetLayoutCases),
+ CASE_DESC(createMaxConcurrentTest <Sampler>, s_samplerCases),
+ CASE_DESC(createMaxConcurrentTest <DescriptorPool>, s_descriptorPoolCases),
+ CASE_DESC(createMaxConcurrentTest <DescriptorSet>, s_descriptorSetCases),
+ CASE_DESC(createMaxConcurrentTest <Framebuffer>, s_framebufferCases),
+ CASE_DESC(createMaxConcurrentTest <CommandPool>, s_commandPoolCases),
+ CASE_DESC(createMaxConcurrentTest <CommandBuffer>, s_commandBufferCases),
+ };
+ objectMgmtTests->addChild(createGroup(testCtx, "max_concurrent", "Maximum number of concurrently live objects", s_createMaxConcurrentGroup));
+
+ static const CaseDescriptions s_multithreadedCreatePerThreadDeviceGroup =
+ {
+ EMPTY_CASE_DESC(Instance), // Does not make sense
+ EMPTY_CASE_DESC(Device), // Does not make sense
+ CASE_DESC(multithreadedCreatePerThreadDeviceTest <DeviceMemory>, s_deviceMemCases),
+ CASE_DESC(multithreadedCreatePerThreadDeviceTest <Buffer>, s_bufferCases),
+ CASE_DESC(multithreadedCreatePerThreadDeviceTest <BufferView>, s_bufferViewCases),
+ CASE_DESC(multithreadedCreatePerThreadDeviceTest <Image>, s_imageCases),
+ CASE_DESC(multithreadedCreatePerThreadDeviceTest <ImageView>, s_imageViewCases),
+ CASE_DESC(multithreadedCreatePerThreadDeviceTest <Semaphore>, s_semaphoreCases),
+ CASE_DESC(multithreadedCreatePerThreadDeviceTest <Event>, s_eventCases),
+ CASE_DESC(multithreadedCreatePerThreadDeviceTest <Fence>, s_fenceCases),
+ CASE_DESC(multithreadedCreatePerThreadDeviceTest <QueryPool>, s_queryPoolCases),
+ CASE_DESC(multithreadedCreatePerThreadDeviceTest <ShaderModule>, s_shaderModuleCases),
+ CASE_DESC(multithreadedCreatePerThreadDeviceTest <PipelineCache>, s_pipelineCacheCases),
+ CASE_DESC(multithreadedCreatePerThreadDeviceTest <PipelineLayout>, s_pipelineLayoutCases),
+ CASE_DESC(multithreadedCreatePerThreadDeviceTest <RenderPass>, s_renderPassCases),
+ CASE_DESC(multithreadedCreatePerThreadDeviceTest <GraphicsPipeline>, s_graphicsPipelineCases),
+ CASE_DESC(multithreadedCreatePerThreadDeviceTest <ComputePipeline>, s_computePipelineCases),
+ CASE_DESC(multithreadedCreatePerThreadDeviceTest <DescriptorSetLayout>, s_descriptorSetLayoutCases),
+ CASE_DESC(multithreadedCreatePerThreadDeviceTest <Sampler>, s_samplerCases),
+ CASE_DESC(multithreadedCreatePerThreadDeviceTest <DescriptorPool>, s_descriptorPoolCases),
+ CASE_DESC(multithreadedCreatePerThreadDeviceTest <DescriptorSet>, s_descriptorSetCases),
+ CASE_DESC(multithreadedCreatePerThreadDeviceTest <Framebuffer>, s_framebufferCases),
+ CASE_DESC(multithreadedCreatePerThreadDeviceTest <CommandPool>, s_commandPoolCases),
+ CASE_DESC(multithreadedCreatePerThreadDeviceTest <CommandBuffer>, s_commandBufferCases),
+ };
+ objectMgmtTests->addChild(createGroup(testCtx, "multithreaded_per_thread_device", "Multithreaded object construction with per-thread device ", s_multithreadedCreatePerThreadDeviceGroup));
+
+ static const CaseDescriptions s_multithreadedCreatePerThreadResourcesGroup =
+ {
+ CASE_DESC(multithreadedCreatePerThreadResourcesTest <Instance>, s_instanceCases),
+ CASE_DESC(multithreadedCreatePerThreadResourcesTest <Device>, s_deviceCases),
+ CASE_DESC(multithreadedCreatePerThreadResourcesTest <DeviceMemory>, s_deviceMemCases),
+ CASE_DESC(multithreadedCreatePerThreadResourcesTest <Buffer>, s_bufferCases),
+ CASE_DESC(multithreadedCreatePerThreadResourcesTest <BufferView>, s_bufferViewCases),
+ CASE_DESC(multithreadedCreatePerThreadResourcesTest <Image>, s_imageCases),
+ CASE_DESC(multithreadedCreatePerThreadResourcesTest <ImageView>, s_imageViewCases),
+ CASE_DESC(multithreadedCreatePerThreadResourcesTest <Semaphore>, s_semaphoreCases),
+ CASE_DESC(multithreadedCreatePerThreadResourcesTest <Event>, s_eventCases),
+ CASE_DESC(multithreadedCreatePerThreadResourcesTest <Fence>, s_fenceCases),
+ CASE_DESC(multithreadedCreatePerThreadResourcesTest <QueryPool>, s_queryPoolCases),
+ CASE_DESC(multithreadedCreatePerThreadResourcesTest <ShaderModule>, s_shaderModuleCases),
+ CASE_DESC(multithreadedCreatePerThreadResourcesTest <PipelineCache>, s_pipelineCacheCases),
+ CASE_DESC(multithreadedCreatePerThreadResourcesTest <PipelineLayout>, s_pipelineLayoutCases),
+ CASE_DESC(multithreadedCreatePerThreadResourcesTest <RenderPass>, s_renderPassCases),
+ CASE_DESC(multithreadedCreatePerThreadResourcesTest <GraphicsPipeline>, s_graphicsPipelineCases),
+ CASE_DESC(multithreadedCreatePerThreadResourcesTest <ComputePipeline>, s_computePipelineCases),
+ CASE_DESC(multithreadedCreatePerThreadResourcesTest <DescriptorSetLayout>, s_descriptorSetLayoutCases),
+ CASE_DESC(multithreadedCreatePerThreadResourcesTest <Sampler>, s_samplerCases),
+ CASE_DESC(multithreadedCreatePerThreadResourcesTest <DescriptorPool>, s_descriptorPoolCases),
+ CASE_DESC(multithreadedCreatePerThreadResourcesTest <DescriptorSet>, s_descriptorSetCases),
+ CASE_DESC(multithreadedCreatePerThreadResourcesTest <Framebuffer>, s_framebufferCases),
+ CASE_DESC(multithreadedCreatePerThreadResourcesTest <CommandPool>, s_commandPoolCases),
+ CASE_DESC(multithreadedCreatePerThreadResourcesTest <CommandBuffer>, s_commandBufferCases),
+ };
+ objectMgmtTests->addChild(createGroup(testCtx, "multithreaded_per_thread_resources", "Multithreaded object construction with per-thread resources", s_multithreadedCreatePerThreadResourcesGroup));
+
+ static const CaseDescriptions s_multithreadedCreateSharedResourcesGroup =
+ {
+ EMPTY_CASE_DESC(Instance),
+ CASE_DESC(multithreadedCreateSharedResourcesTest <Device>, s_deviceCases),
+ CASE_DESC(multithreadedCreateSharedResourcesTest <DeviceMemory>, s_deviceMemCases),
+ CASE_DESC(multithreadedCreateSharedResourcesTest <Buffer>, s_bufferCases),
+ CASE_DESC(multithreadedCreateSharedResourcesTest <BufferView>, s_bufferViewCases),
+ CASE_DESC(multithreadedCreateSharedResourcesTest <Image>, s_imageCases),
+ CASE_DESC(multithreadedCreateSharedResourcesTest <ImageView>, s_imageViewCases),
+ CASE_DESC(multithreadedCreateSharedResourcesTest <Semaphore>, s_semaphoreCases),
+ CASE_DESC(multithreadedCreateSharedResourcesTest <Event>, s_eventCases),
+ CASE_DESC(multithreadedCreateSharedResourcesTest <Fence>, s_fenceCases),
+ CASE_DESC(multithreadedCreateSharedResourcesTest <QueryPool>, s_queryPoolCases),
+ CASE_DESC(multithreadedCreateSharedResourcesTest <ShaderModule>, s_shaderModuleCases),
+ CASE_DESC(multithreadedCreateSharedResourcesTest <PipelineCache>, s_pipelineCacheCases),
+ CASE_DESC(multithreadedCreateSharedResourcesTest <PipelineLayout>, s_pipelineLayoutCases),
+ CASE_DESC(multithreadedCreateSharedResourcesTest <RenderPass>, s_renderPassCases),
+ CASE_DESC(multithreadedCreateSharedResourcesTest <GraphicsPipeline>, s_graphicsPipelineCases),
+ CASE_DESC(multithreadedCreateSharedResourcesTest <ComputePipeline>, s_computePipelineCases),
+ CASE_DESC(multithreadedCreateSharedResourcesTest <DescriptorSetLayout>, s_descriptorSetLayoutCases),
+ CASE_DESC(multithreadedCreateSharedResourcesTest <Sampler>, s_samplerCases),
+ CASE_DESC(multithreadedCreateSharedResourcesTest <DescriptorPool>, s_descriptorPoolCases),
+ EMPTY_CASE_DESC(DescriptorSet), // \note Needs per-thread DescriptorPool
+ CASE_DESC(multithreadedCreateSharedResourcesTest <Framebuffer>, s_framebufferCases),
+ CASE_DESC(multithreadedCreateSharedResourcesTest <CommandPool>, s_commandPoolCases),
+ EMPTY_CASE_DESC(CommandBuffer), // \note Needs per-thread CommandPool
+ };
+ objectMgmtTests->addChild(createGroup(testCtx, "multithreaded_shared_resources", "Multithreaded object construction with shared resources", s_multithreadedCreateSharedResourcesGroup));
+
+ return objectMgmtTests.release();
+}
+
+} // api
+} // vkt
--- /dev/null
+#ifndef _VKTAPIOBJECTMANAGEMENTTESTS_HPP
+#define _VKTAPIOBJECTMANAGEMENTTESTS_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Object management tests
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+namespace api
+{
+
+tcu::TestCaseGroup* createObjectManagementTests (tcu::TestContext& testCtx);
+
+} // api
+} // vkt
+
+#endif // _VKTAPIOBJECTMANAGEMENTTESTS_HPP
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Simple Smoke Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktApiTests.hpp"
+
+#include "vktTestCaseUtil.hpp"
+
+#include "vkDefs.hpp"
+#include "vkPlatform.hpp"
+#include "vkStrUtil.hpp"
+#include "vkRef.hpp"
+#include "vkRefUtil.hpp"
+#include "vkQueryUtil.hpp"
+#include "vkMemUtil.hpp"
+#include "vkDeviceUtil.hpp"
+#include "vkPrograms.hpp"
+#include "vkTypeUtil.hpp"
+
+#include "tcuTestLog.hpp"
+#include "tcuFormatUtil.hpp"
+
+#include "deUniquePtr.hpp"
+
+namespace vkt
+{
+namespace api
+{
+
+namespace
+{
+
+using namespace vk;
+using std::vector;
+using tcu::TestLog;
+using de::UniquePtr;
+
+tcu::TestStatus createSamplerTest (Context& context)
+{
+ const VkDevice vkDevice = context.getDevice();
+ const DeviceInterface& vk = context.getDeviceInterface();
+
+ {
+ const struct VkSamplerCreateInfo samplerInfo =
+ {
+ VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ 0u, // flags
+ VK_FILTER_NEAREST, // magFilter
+ VK_FILTER_NEAREST, // minFilter
+ VK_SAMPLER_MIPMAP_MODE_BASE, // mipmapMode
+ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeU
+ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeV
+ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeW
+ 0.0f, // mipLodBias
+ 0.0f, // maxAnisotropy
+ DE_FALSE, // compareEnable
+ VK_COMPARE_OP_ALWAYS, // compareOp
+ 0.0f, // minLod
+ 0.0f, // maxLod
+ VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // borderColor
+ VK_FALSE, // unnormalizedCoords
+ };
+
+ Move<VkSampler> tmpSampler = createSampler(vk, vkDevice, &samplerInfo);
+ Move<VkSampler> tmp2Sampler;
+
+ tmp2Sampler = tmpSampler;
+
+ const Unique<VkSampler> sampler (tmp2Sampler);
+ }
+
+ return tcu::TestStatus::pass("Creating sampler succeeded");
+}
+
+void createShaderProgs (SourceCollections& dst)
+{
+ dst.glslSources.add("test") << glu::VertexSource(
+ "#version 300 es\n"
+ "in highp vec4 a_position;\n"
+ "void main (void) { gl_Position = a_position; }\n");
+}
+
+tcu::TestStatus createShaderModuleTest (Context& context)
+{
+ const VkDevice vkDevice = context.getDevice();
+ const DeviceInterface& vk = context.getDeviceInterface();
+ const Unique<VkShaderModule> shader (createShaderModule(vk, vkDevice, context.getBinaryCollection().get("test"), 0));
+
+ return tcu::TestStatus::pass("Creating shader module succeeded");
+}
+
+void createTriangleAsmProgs (SourceCollections& dst)
+{
+ dst.spirvAsmSources.add("vert") <<
+ " OpCapability Shader\n"
+ "%1 = OpExtInstImport \"GLSL.std.450\"\n"
+ " OpMemoryModel Logical GLSL450\n"
+ " OpEntryPoint Vertex %4 \"main\" %10 %12 %16 %17\n"
+ " OpSource ESSL 300\n"
+ " OpName %4 \"main\"\n"
+ " OpName %10 \"gl_Position\"\n"
+ " OpName %12 \"a_position\"\n"
+ " OpName %16 \"gl_VertexID\"\n"
+ " OpName %17 \"gl_InstanceID\"\n"
+ " OpDecorate %10 BuiltIn Position\n"
+ " OpDecorate %12 Location 0\n"
+ " OpDecorate %16 BuiltIn VertexId\n"
+ " OpDecorate %17 BuiltIn InstanceId\n"
+ "%2 = OpTypeVoid\n"
+ "%3 = OpTypeFunction %2\n"
+ "%7 = OpTypeFloat 32\n"
+ "%8 = OpTypeVector %7 4\n"
+ "%9 = OpTypePointer Output %8\n"
+ "%10 = OpVariable %9 Output\n"
+ "%11 = OpTypePointer Input %8\n"
+ "%12 = OpVariable %11 Input\n"
+ "%14 = OpTypeInt 32 1\n"
+ "%15 = OpTypePointer Input %14\n"
+ "%16 = OpVariable %15 Input\n"
+ "%17 = OpVariable %15 Input\n"
+ "%4 = OpFunction %2 None %3\n"
+ "%5 = OpLabel\n"
+ "%13 = OpLoad %8 %12\n"
+ " OpStore %10 %13\n"
+ " OpBranch %6\n"
+ "%6 = OpLabel\n"
+ " OpReturn\n"
+ " OpFunctionEnd\n";
+ dst.spirvAsmSources.add("frag") <<
+ " OpCapability Shader\n"
+ "%1 = OpExtInstImport \"GLSL.std.450\"\n"
+ " OpMemoryModel Logical GLSL450\n"
+ " OpEntryPoint Fragment %4 \"main\" %10\n"
+ " OpExecutionMode %4 OriginLowerLeft\n"
+ " OpSource ESSL 300\n"
+ " OpName %4 \"main\"\n"
+ " OpName %10 \"o_color\"\n"
+ " OpDecorate %10 RelaxedPrecision\n"
+ " OpDecorate %10 Location 0\n"
+ "%2 = OpTypeVoid\n"
+ "%3 = OpTypeFunction %2\n"
+ "%7 = OpTypeFloat 32\n"
+ "%8 = OpTypeVector %7 4\n"
+ "%9 = OpTypePointer Output %8\n"
+ "%10 = OpVariable %9 Output\n"
+ "%11 = OpConstant %7 1065353216\n"
+ "%12 = OpConstant %7 0\n"
+ "%13 = OpConstantComposite %8 %11 %12 %11 %11\n"
+ "%4 = OpFunction %2 None %3\n"
+ "%5 = OpLabel\n"
+ " OpStore %10 %13\n"
+ " OpBranch %6\n"
+ "%6 = OpLabel\n"
+ " OpReturn\n"
+ " OpFunctionEnd\n";
+}
+
+void createTriangleProgs (SourceCollections& dst)
+{
+ dst.glslSources.add("vert") << glu::VertexSource(
+ "#version 300 es\n"
+ "layout(location = 0) in highp vec4 a_position;\n"
+ "void main (void) { gl_Position = a_position; }\n");
+ dst.glslSources.add("frag") << glu::FragmentSource(
+ "#version 300 es\n"
+ "layout(location = 0) out lowp vec4 o_color;\n"
+ "void main (void) { o_color = vec4(1.0, 0.0, 1.0, 1.0); }\n");
+}
+
+tcu::TestStatus renderTriangleTest (Context& context)
+{
+ const VkDevice vkDevice = context.getDevice();
+ const DeviceInterface& vk = context.getDeviceInterface();
+ const VkQueue queue = context.getUniversalQueue();
+ const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
+ SimpleAllocator memAlloc (vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
+ const tcu::IVec2 renderSize (256, 256);
+
+ const tcu::Vec4 vertices[] =
+ {
+ tcu::Vec4(-0.5f, -0.5f, 0.0f, 1.0f),
+ tcu::Vec4(+0.5f, -0.5f, 0.0f, 1.0f),
+ tcu::Vec4( 0.0f, +0.5f, 0.0f, 1.0f)
+ };
+
+ const VkBufferCreateInfo vertexBufferParams =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ 0u, // flags
+ (VkDeviceSize)sizeof(vertices), // size
+ VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // usage
+ VK_SHARING_MODE_EXCLUSIVE, // sharingMode
+ 1u, // queueFamilyIndexCount
+ &queueFamilyIndex, // pQueueFamilyIndices
+ };
+ const Unique<VkBuffer> vertexBuffer (createBuffer(vk, vkDevice, &vertexBufferParams));
+ const UniquePtr<Allocation> vertexBufferMemory (memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible));
+
+ VK_CHECK(vk.bindBufferMemory(vkDevice, *vertexBuffer, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset()));
+
+ const VkDeviceSize imageSizeBytes = (VkDeviceSize)(sizeof(deUint32)*renderSize.x()*renderSize.y());
+ const VkBufferCreateInfo readImageBufferParams =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ (VkBufferCreateFlags)0u, // flags
+ imageSizeBytes, // size
+ VK_BUFFER_USAGE_TRANSFER_DST_BIT, // usage
+ VK_SHARING_MODE_EXCLUSIVE, // sharingMode
+ 1u, // queueFamilyIndexCount
+ &queueFamilyIndex, // pQueueFamilyIndices
+ };
+ const Unique<VkBuffer> readImageBuffer (createBuffer(vk, vkDevice, &readImageBufferParams));
+ const UniquePtr<Allocation> readImageBufferMemory (memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *readImageBuffer), MemoryRequirement::HostVisible));
+
+ VK_CHECK(vk.bindBufferMemory(vkDevice, *readImageBuffer, readImageBufferMemory->getMemory(), readImageBufferMemory->getOffset()));
+
+ const VkImageCreateInfo imageParams =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ 0u, // flags
+ VK_IMAGE_TYPE_2D, // imageType
+ VK_FORMAT_R8G8B8A8_UNORM, // format
+ { renderSize.x(), renderSize.y(), 1 }, // extent
+ 1u, // mipLevels
+ 1u, // arraySize
+ VK_SAMPLE_COUNT_1_BIT, // samples
+ VK_IMAGE_TILING_OPTIMAL, // tiling
+ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // usage
+ VK_SHARING_MODE_EXCLUSIVE, // sharingMode
+ 1u, // queueFamilyIndexCount
+ &queueFamilyIndex, // pQueueFamilyIndices
+ VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout
+ };
+
+ const Unique<VkImage> image (createImage(vk, vkDevice, &imageParams));
+ const UniquePtr<Allocation> imageMemory (memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *image), MemoryRequirement::Any));
+
+ VK_CHECK(vk.bindImageMemory(vkDevice, *image, imageMemory->getMemory(), imageMemory->getOffset()));
+
+ const VkAttachmentDescription colorAttDesc =
+ {
+ 0u, // flags
+ VK_FORMAT_R8G8B8A8_UNORM, // format
+ VK_SAMPLE_COUNT_1_BIT, // samples
+ VK_ATTACHMENT_LOAD_OP_CLEAR, // loadOp
+ VK_ATTACHMENT_STORE_OP_STORE, // storeOp
+ VK_ATTACHMENT_LOAD_OP_DONT_CARE, // stencilLoadOp
+ VK_ATTACHMENT_STORE_OP_DONT_CARE, // stencilStoreOp
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // initialLayout
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // finalLayout
+ };
+ const VkAttachmentReference colorAttRef =
+ {
+ 0u, // attachment
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // layout
+ };
+ const VkSubpassDescription subpassDesc =
+ {
+ (VkSubpassDescriptionFlags)0u, // flags
+ VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint
+ 0u, // inputAttachmentCount
+ DE_NULL, // pInputAttachments
+ 1u, // colorAttachmentCount
+ &colorAttRef, // pColorAttachments
+ DE_NULL, // pResolveAttachments
+ DE_NULL, // depthStencilAttachment
+ 0u, // preserveAttachmentCount
+ DE_NULL, // pPreserveAttachments
+ };
+ const VkRenderPassCreateInfo renderPassParams =
+ {
+ VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ 0u, // flags
+ 1u, // attachmentCount
+ &colorAttDesc, // pAttachments
+ 1u, // subpassCount
+ &subpassDesc, // pSubpasses
+ 0u, // dependencyCount
+ DE_NULL, // pDependencies
+ };
+ const Unique<VkRenderPass> renderPass (createRenderPass(vk, vkDevice, &renderPassParams));
+
+ const VkImageViewCreateInfo colorAttViewParams =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ 0u, // flags
+ *image, // image
+ VK_IMAGE_VIEW_TYPE_2D, // viewType
+ VK_FORMAT_R8G8B8A8_UNORM, // format
+ {
+ VK_COMPONENT_SWIZZLE_R,
+ VK_COMPONENT_SWIZZLE_G,
+ VK_COMPONENT_SWIZZLE_B,
+ VK_COMPONENT_SWIZZLE_A
+ }, // components
+ {
+ VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
+ 0u, // baseMipLevel
+ 1u, // levelCount
+ 0u, // baseArrayLayer
+ 1u, // layerCount
+ }, // subresourceRange
+ };
+ const Unique<VkImageView> colorAttView (createImageView(vk, vkDevice, &colorAttViewParams));
+
+ // Pipeline layout
+ const VkPipelineLayoutCreateInfo pipelineLayoutParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ (vk::VkPipelineLayoutCreateFlags)0,
+ 0u, // setLayoutCount
+ DE_NULL, // pSetLayouts
+ 0u, // pushConstantRangeCount
+ DE_NULL, // pPushConstantRanges
+ };
+ const Unique<VkPipelineLayout> pipelineLayout (createPipelineLayout(vk, vkDevice, &pipelineLayoutParams));
+
+ // Shaders
+ const Unique<VkShaderModule> vertShaderModule (createShaderModule(vk, vkDevice, context.getBinaryCollection().get("vert"), 0));
+ const Unique<VkShaderModule> fragShaderModule (createShaderModule(vk, vkDevice, context.getBinaryCollection().get("frag"), 0));
+
+ // Pipeline
+ const VkSpecializationInfo emptyShaderSpecParams =
+ {
+ 0u, // mapEntryCount
+ DE_NULL, // pMap
+ 0, // dataSize
+ DE_NULL, // pData
+ };
+ const VkPipelineShaderStageCreateInfo shaderStageParams[] =
+ {
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ 0u, // flags
+ VK_SHADER_STAGE_VERTEX_BIT, // stage
+ *vertShaderModule, // module
+ "main", // pName
+ &emptyShaderSpecParams, // pSpecializationInfo
+ },
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ 0u, // flags
+ VK_SHADER_STAGE_FRAGMENT_BIT, // stage
+ *fragShaderModule, // module
+ "main", // pName
+ &emptyShaderSpecParams, // pSpecializationInfo
+ }
+ };
+ const VkPipelineDepthStencilStateCreateInfo depthStencilParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ 0u, // flags
+ DE_FALSE, // depthTestEnable
+ DE_FALSE, // depthWriteEnable
+ VK_COMPARE_OP_ALWAYS, // depthCompareOp
+ DE_FALSE, // depthBoundsTestEnable
+ DE_FALSE, // stencilTestEnable
+ {
+ VK_STENCIL_OP_KEEP, // failOp
+ VK_STENCIL_OP_KEEP, // passOp
+ VK_STENCIL_OP_KEEP, // depthFailOp
+ VK_COMPARE_OP_ALWAYS, // compareOp
+ 0u, // compareMask
+ 0u, // writeMask
+ 0u, // reference
+ }, // front
+ {
+ VK_STENCIL_OP_KEEP, // failOp
+ VK_STENCIL_OP_KEEP, // passOp
+ VK_STENCIL_OP_KEEP, // depthFailOp
+ VK_COMPARE_OP_ALWAYS, // compareOp
+ 0u, // compareMask
+ 0u, // writeMask
+ 0u, // reference
+ }, // back;
+ -1.0f, // float minDepthBounds;
+ +1.0f, // float maxDepthBounds;
+ };
+ const VkViewport viewport0 =
+ {
+ 0.0f, // x
+ 0.0f, // y
+ (float)renderSize.x(), // width
+ (float)renderSize.y(), // height
+ 0.0f, // minDepth
+ 1.0f, // maxDepth
+ };
+ const VkRect2D scissor0 =
+ {
+ {
+ 0u, // x
+ 0u, // y
+ }, // offset
+ {
+ renderSize.x(), // width
+ renderSize.y(), // height
+ }, // extent;
+ };
+ const VkPipelineViewportStateCreateInfo viewportParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ 0u, // flags
+ 1u, // viewportCount
+ &viewport0, // pViewports
+ 1u, // scissorCount
+ &scissor0 // pScissors
+ };
+ const VkSampleMask sampleMask = ~0u;
+ const VkPipelineMultisampleStateCreateInfo multisampleParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ 0u, // flags
+ VK_SAMPLE_COUNT_1_BIT, // rasterizationSamples
+ VK_FALSE, // sampleShadingEnable
+ 0.0f, // minSampleShading
+ &sampleMask, // sampleMask
+ VK_FALSE, // alphaToCoverageEnable
+ VK_FALSE, // alphaToOneEnable
+ };
+ const VkPipelineRasterizationStateCreateInfo rasterParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ 0u, // flags
+ VK_TRUE, // depthClampEnable
+ VK_FALSE, // rasterizerDiscardEnable
+ VK_POLYGON_MODE_FILL, // polygonMode
+ VK_CULL_MODE_NONE, // cullMode
+ VK_FRONT_FACE_COUNTER_CLOCKWISE, // frontFace
+ VK_FALSE, // depthBiasEnable
+ 0.0f, // depthBiasConstantFactor
+ 0.0f, // depthBiasClamp
+ 0.0f, // depthBiasSlopeFactor
+ 1.0f, // lineWidth
+ };
+ const VkPipelineInputAssemblyStateCreateInfo inputAssemblyParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ 0u, // flags
+ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // topology
+ DE_FALSE, // primitiveRestartEnable
+ };
+ const VkVertexInputBindingDescription vertexBinding0 =
+ {
+ 0u, // binding
+ (deUint32)sizeof(tcu::Vec4), // stride
+ VK_VERTEX_INPUT_RATE_VERTEX, // inputRate
+ };
+ const VkVertexInputAttributeDescription vertexAttrib0 =
+ {
+ 0u, // location
+ 0u, // binding
+ VK_FORMAT_R32G32B32A32_SFLOAT, // format
+ 0u, // offset
+ };
+ const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ 0u, // flags
+ 1u, // vertexBindingDescriptionCount
+ &vertexBinding0, // pVertexBindingDescriptions
+ 1u, // vertexAttributeDescriptionCount
+ &vertexAttrib0, // pVertexAttributeDescriptions
+ };
+ const VkPipelineColorBlendAttachmentState attBlendParams =
+ {
+ VK_FALSE, // blendEnable
+ VK_BLEND_FACTOR_ONE, // srcColorBlendFactor
+ VK_BLEND_FACTOR_ZERO, // dstColorBlendFactor
+ VK_BLEND_OP_ADD, // colorBlendOp
+ VK_BLEND_FACTOR_ONE, // srcAlphaBlendFactor
+ VK_BLEND_FACTOR_ZERO, // dstAlphaBlendFactor
+ VK_BLEND_OP_ADD, // alphaBlendOp
+ (VK_COLOR_COMPONENT_R_BIT|
+ VK_COLOR_COMPONENT_G_BIT|
+ VK_COLOR_COMPONENT_B_BIT|
+ VK_COLOR_COMPONENT_A_BIT), // colorWriteMask
+ };
+ const VkPipelineColorBlendStateCreateInfo blendParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ 0u, // flags
+ DE_FALSE, // logicOpEnable
+ VK_LOGIC_OP_COPY, // logicOp
+ 1u, // attachmentCount
+ &attBlendParams, // pAttachments
+ { 0.0f, 0.0f, 0.0f, 0.0f }, // blendConstants[4]
+ };
+ const VkPipelineDynamicStateCreateInfo dynamicStateInfo =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ 0u, // flags
+ 0u, // dynamicStateCount
+ DE_NULL // pDynamicStates
+ };
+ const VkGraphicsPipelineCreateInfo pipelineParams =
+ {
+ VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ 0u, // flags
+ (deUint32)DE_LENGTH_OF_ARRAY(shaderStageParams), // stageCount
+ shaderStageParams, // pStages
+ &vertexInputStateParams, // pVertexInputState
+ &inputAssemblyParams, // pInputAssemblyState
+ DE_NULL, // pTessellationState
+ &viewportParams, // pViewportState
+ &rasterParams, // pRasterizationState
+ &multisampleParams, // pMultisampleState
+ &depthStencilParams, // pDepthStencilState
+ &blendParams, // pColorBlendState
+ &dynamicStateInfo, // pDynamicState
+ *pipelineLayout, // layout
+ *renderPass, // renderPass
+ 0u, // subpass
+ DE_NULL, // basePipelineHandle
+ 0u, // basePipelineIndex
+ };
+
+ const Unique<VkPipeline> pipeline (createGraphicsPipeline(vk, vkDevice, DE_NULL, &pipelineParams));
+
+ // Framebuffer
+ const VkFramebufferCreateInfo framebufferParams =
+ {
+ VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ 0u, // flags
+ *renderPass, // renderPass
+ 1u, // attachmentCount
+ &*colorAttView, // pAttachments
+ (deUint32)renderSize.x(), // width
+ (deUint32)renderSize.y(), // height
+ 1u, // layers
+ };
+ const Unique<VkFramebuffer> framebuffer (createFramebuffer(vk, vkDevice, &framebufferParams));
+
+ const VkCommandPoolCreateInfo cmdPoolParams =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags
+ queueFamilyIndex, // queueFamilyIndex
+ };
+ const Unique<VkCommandPool> cmdPool (createCommandPool(vk, vkDevice, &cmdPoolParams));
+
+ // Command buffer
+ const VkCommandBufferAllocateInfo cmdBufParams =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType
+ DE_NULL, // pNext
+ *cmdPool, // pool
+ VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level
+ 1u, // bufferCount
+ };
+ const Unique<VkCommandBuffer> cmdBuf (allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
+
+ const VkCommandBufferBeginInfo cmdBufBeginParams =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
+ DE_NULL, // pNext
+ 0u, // flags
+ DE_NULL, // renderPass
+ 0u, // subpass
+ DE_NULL, // framebuffer
+ VK_FALSE, // occlusionQueryEnable
+ (VkQueryControlFlags)0u, // queryFlags
+ (VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
+ };
+
+ // Record commands
+ VK_CHECK(vk.beginCommandBuffer(*cmdBuf, &cmdBufBeginParams));
+
+ {
+ const VkMemoryBarrier vertFlushBarrier =
+ {
+ VK_STRUCTURE_TYPE_MEMORY_BARRIER, // sType
+ DE_NULL, // pNext
+ VK_ACCESS_HOST_WRITE_BIT, // srcAccessMask
+ VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, // dstAccessMask
+ };
+ const VkImageMemoryBarrier colorAttBarrier =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
+ DE_NULL, // pNext
+ 0u, // srcAccessMask
+ (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT|
+ VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT), // dstAccessMask
+ VK_IMAGE_LAYOUT_UNDEFINED, // oldLayout
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // newLayout
+ queueFamilyIndex, // srcQueueFamilyIndex
+ queueFamilyIndex, // dstQueueFamilyIndex
+ *image, // image
+ {
+ VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
+ 0u, // baseMipLevel
+ 1u, // levelCount
+ 0u, // baseArrayLayer
+ 1u, // layerCount
+ } // subresourceRange
+ };
+ const void* barriers[] = { &vertFlushBarrier, &colorAttBarrier };
+ vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, DE_FALSE, (deUint32)DE_LENGTH_OF_ARRAY(barriers), barriers);
+ }
+
+ {
+ const VkClearValue clearValue = makeClearValueColorF32(0.125f, 0.25f, 0.75f, 1.0f);
+ const VkRenderPassBeginInfo passBeginParams =
+ {
+ VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // sType
+ DE_NULL, // pNext
+ *renderPass, // renderPass
+ *framebuffer, // framebuffer
+ { { 0, 0 }, { renderSize.x(), renderSize.y() } }, // renderArea
+ 1u, // clearValueCount
+ &clearValue, // pClearValues
+ };
+ vk.cmdBeginRenderPass(*cmdBuf, &passBeginParams, VK_SUBPASS_CONTENTS_INLINE);
+ }
+
+ vk.cmdBindPipeline(*cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
+ {
+ const VkDeviceSize bindingOffset = 0;
+ vk.cmdBindVertexBuffers(*cmdBuf, 0u, 1u, &vertexBuffer.get(), &bindingOffset);
+ }
+ vk.cmdDraw(*cmdBuf, 3u, 1u, 0u, 0u);
+ vk.cmdEndRenderPass(*cmdBuf);
+
+ {
+ const VkImageMemoryBarrier renderFinishBarrier =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
+ DE_NULL, // pNext
+ VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // outputMask
+ VK_ACCESS_TRANSFER_READ_BIT, // inputMask
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // oldLayout
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // newLayout
+ queueFamilyIndex, // srcQueueFamilyIndex
+ queueFamilyIndex, // dstQueueFamilyIndex
+ *image, // image
+ {
+ VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
+ 0u, // baseMipLevel
+ 1u, // mipLevels
+ 0u, // baseArraySlice
+ 1u, // arraySize
+ } // subresourceRange
+ };
+ const void* barriers[] = { &renderFinishBarrier };
+ vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, DE_FALSE, (deUint32)DE_LENGTH_OF_ARRAY(barriers), barriers);
+ }
+
+ {
+ const VkBufferImageCopy copyParams =
+ {
+ (VkDeviceSize)0u, // bufferOffset
+ (deUint32)renderSize.x(), // bufferRowLength
+ (deUint32)renderSize.y(), // bufferImageHeight
+ {
+ VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
+ 0u, // mipLevel
+ 0u, // baseArrayLayer
+ 1u, // layerCount
+ }, // imageSubresource
+ { 0u, 0u, 0u }, // imageOffset
+ { renderSize.x(), renderSize.y(), 1u } // imageExtent
+ };
+ vk.cmdCopyImageToBuffer(*cmdBuf, *image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *readImageBuffer, 1u, ©Params);
+ }
+
+ {
+ const VkBufferMemoryBarrier copyFinishBarrier =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // sType
+ DE_NULL, // pNext
+ VK_ACCESS_TRANSFER_WRITE_BIT, // srcAccessMask
+ VK_ACCESS_HOST_READ_BIT, // dstAccessMask
+ queueFamilyIndex, // srcQueueFamilyIndex
+ queueFamilyIndex, // dstQueueFamilyIndex
+ *readImageBuffer, // buffer
+ 0u, // offset
+ imageSizeBytes // size
+ };
+ const void* barriers[] = { ©FinishBarrier };
+ vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, DE_FALSE, (deUint32)DE_LENGTH_OF_ARRAY(barriers), barriers);
+ }
+
+ VK_CHECK(vk.endCommandBuffer(*cmdBuf));
+
+ // Upload vertex data
+ {
+ const VkMappedMemoryRange range =
+ {
+ VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // sType
+ DE_NULL, // pNext
+ vertexBufferMemory->getMemory(), // memory
+ 0, // offset
+ (VkDeviceSize)sizeof(vertices), // size
+ };
+ void* vertexBufPtr = vertexBufferMemory->getHostPtr();
+
+ deMemcpy(vertexBufPtr, &vertices[0], sizeof(vertices));
+ VK_CHECK(vk.flushMappedMemoryRanges(vkDevice, 1u, &range));
+ }
+
+ // Submit & wait for completion
+ {
+ const VkFenceCreateInfo fenceParams =
+ {
+ VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ 0u, // flags
+ };
+ const VkSubmitInfo submitInfo =
+ {
+ VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType
+ DE_NULL, // pNext
+ 0u, // waitSemaphoreCount
+ DE_NULL, // pWaitSemaphores
+ 1u, // commandBufferCount
+ &cmdBuf.get(), // pCommandBuffers
+ 0u, // signalSemaphoreCount
+ DE_NULL, // pSignalSemaphores
+ };
+ const Unique<VkFence> fence (createFence(vk, vkDevice, &fenceParams));
+
+ VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence));
+ VK_CHECK(vk.waitForFences(vkDevice, 1u, &fence.get(), DE_TRUE, ~0ull));
+ }
+
+ // Log image
+ {
+ const VkMappedMemoryRange range =
+ {
+ VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // sType
+ DE_NULL, // pNext
+ readImageBufferMemory->getMemory(), // memory
+ 0, // offset
+ imageSizeBytes, // size
+ };
+ void* imagePtr = readImageBufferMemory->getHostPtr();
+
+ VK_CHECK(vk.invalidateMappedMemoryRanges(vkDevice, 1u, &range));
+ context.getTestContext().getLog() << TestLog::Image("Result", "Result", tcu::ConstPixelBufferAccess(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), renderSize.x(), renderSize.y(), 1, imagePtr));
+ }
+
+ return tcu::TestStatus::pass("Rendering succeeded");
+}
+
+} // anonymous
+
+tcu::TestCaseGroup* createSmokeTests (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> smokeTests (new tcu::TestCaseGroup(testCtx, "smoke", "Smoke Tests"));
+
+ addFunctionCase (smokeTests.get(), "create_sampler", "", createSamplerTest);
+ addFunctionCaseWithPrograms (smokeTests.get(), "create_shader", "", createShaderProgs, createShaderModuleTest);
+ addFunctionCaseWithPrograms (smokeTests.get(), "triangle", "", createTriangleProgs, renderTriangleTest);
+ addFunctionCaseWithPrograms (smokeTests.get(), "asm_triangle", "", createTriangleAsmProgs, renderTriangleTest);
+
+ return smokeTests.release();
+}
+
+} // api
+} // vkt
--- /dev/null
+#ifndef _VKTAPISMOKETESTS_HPP
+#define _VKTAPISMOKETESTS_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Simple Smoke Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+namespace api
+{
+
+tcu::TestCaseGroup* createSmokeTests (tcu::TestContext& testCtx);
+
+} // api
+} // vkt
+
+#endif // _VKTAPISMOKETESTS_HPP
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief API Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktApiTests.hpp"
+
+#include "deUniquePtr.hpp"
+
+#include "vktApiSmokeTests.hpp"
+#include "vktApiDeviceInitializationTests.hpp"
+#include "vktApiObjectManagementTests.hpp"
+#include "vktApiBufferTests.hpp"
+#include "vktApiBufferViewCreateTests.hpp"
+#include "vktApiBufferViewAccessTests.hpp"
+
+namespace vkt
+{
+namespace api
+{
+
+namespace
+{
+
+tcu::TestCaseGroup* createBufferViewTests (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> bufferViewTests (new tcu::TestCaseGroup(testCtx, "buffer_view", "BufferView tests"));
+
+ bufferViewTests->addChild(createBufferViewCreateTests (testCtx));
+ bufferViewTests->addChild(createBufferViewAccessTests (testCtx));
+
+ return bufferViewTests.release();
+}
+
+} // anonymous
+
+tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> apiTests (new tcu::TestCaseGroup(testCtx, "api", "API Tests"));
+
+ apiTests->addChild(createSmokeTests (testCtx));
+ apiTests->addChild(createDeviceInitializationTests (testCtx));
+ apiTests->addChild(createObjectManagementTests (testCtx));
+ apiTests->addChild(createBufferTests (testCtx));
+ apiTests->addChild(createBufferViewTests (testCtx));
+
+ return apiTests.release();
+}
+
+} // api
+} // vkt
--- /dev/null
+#ifndef _VKTAPITESTS_HPP
+#define _VKTAPITESTS_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief API tests
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+namespace api
+{
+
+tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx);
+
+} // api
+} // vkt
+
+#endif // _VKTAPITESTS_HPP
--- /dev/null
+# dEQP-VK.binding_model
+
+include_directories(..)
+
+set(DEQP_VK_BINDING_MODEL_SRCS
+ vktBindingModelTests.cpp
+ vktBindingModelTests.hpp
+ vktBindingShaderAccessTests.cpp
+ vktBindingShaderAccessTests.hpp
+ )
+
+set(DEQP_VK_BINDING_MODEL_LIBS
+ tcutil
+ vkutil
+ )
+
+add_library(deqp-vk-binding-model STATIC ${DEQP_VK_BINDING_MODEL_SRCS})
+target_link_libraries(deqp-vk-binding-model ${DEQP_VK_BINDING_MODEL_LIBS})
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Binding Model tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktBindingModelTests.hpp"
+
+#include "vktBindingShaderAccessTests.hpp"
+
+#include "deUniquePtr.hpp"
+
+namespace vkt
+{
+namespace BindingModel
+{
+
+tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "binding_model", "Resource binding tests"));
+
+ group->addChild(createShaderAccessTests(testCtx));
+
+ // \todo [2015-07-30 jarkko] .change_binding.{between_renderpasses, within_pass}
+ // \todo [2015-07-30 jarkko] .descriptor_set_chain
+ // \todo [2015-07-30 jarkko] .update_descriptor_set
+
+ return group.release();
+}
+
+} // BindingModel
+} // vkt
--- /dev/null
+#ifndef _VKTBINDINGMODELTESTS_HPP
+#define _VKTBINDINGMODELTESTS_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Binding Model tests
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+namespace BindingModel
+{
+
+tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx);
+
+} // BindingModel
+} // vkt
+
+#endif // _VKTBINDINGMODELTESTS_HPP
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Binding shader access tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktBindingShaderAccessTests.hpp"
+
+#include "vktTestCase.hpp"
+
+#include "vkDefs.hpp"
+#include "vkRef.hpp"
+#include "vkRefUtil.hpp"
+#include "vkPlatform.hpp"
+#include "vkPrograms.hpp"
+#include "vkMemUtil.hpp"
+#include "vkBuilderUtil.hpp"
+#include "vkQueryUtil.hpp"
+#include "vkImageUtil.hpp"
+#include "vkTypeUtil.hpp"
+
+#include "tcuVector.hpp"
+#include "tcuVectorUtil.hpp"
+#include "tcuTexture.hpp"
+#include "tcuTextureUtil.hpp"
+#include "tcuResultCollector.hpp"
+#include "tcuTestLog.hpp"
+#include "tcuRGBA.hpp"
+#include "tcuSurface.hpp"
+#include "tcuImageCompare.hpp"
+
+#include "deUniquePtr.hpp"
+#include "deSharedPtr.hpp"
+#include "deStringUtil.hpp"
+#include "deArrayUtil.hpp"
+
+#include "qpInfo.h"
+
+namespace vkt
+{
+namespace BindingModel
+{
+namespace
+{
+
+enum ResourceFlag
+{
+ RESOURCE_FLAG_IMMUTABLE_SAMPLER = (1u << 0u),
+
+ RESOURCE_FLAG_LAST = (1u << 1u)
+};
+
+static const char* const s_quadrantGenVertexPosSource = " highp int quadPhase = gl_VertexID % 6;\n"
+ " highp int quadXcoord = int(quadPhase == 1 || quadPhase == 4 || quadPhase == 5);\n"
+ " highp int quadYcoord = int(quadPhase == 2 || quadPhase == 3 || quadPhase == 5);\n"
+ " highp int quadOriginX = (gl_VertexID / 6) % 2;\n"
+ " highp int quadOriginY = (gl_VertexID / 6) / 2;\n"
+ " quadrant_id = gl_VertexID / 6;\n"
+ " result_position = vec4(float(quadOriginX + quadXcoord - 1), float(quadOriginY + quadYcoord - 1), 0.0, 1.0);\n";
+
+bool isUniformDescriptorType (vk::VkDescriptorType type)
+{
+ return type == vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ||
+ type == vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
+ type == vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
+}
+
+bool isDynamicDescriptorType (vk::VkDescriptorType type)
+{
+ return type == vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC || type == vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
+}
+
+vk::VkImageType viewTypeToImageType (vk::VkImageViewType type)
+{
+ switch (type)
+ {
+ case vk::VK_IMAGE_VIEW_TYPE_1D:
+ case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY: return vk::VK_IMAGE_TYPE_1D;
+ case vk::VK_IMAGE_VIEW_TYPE_2D:
+ case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY: return vk::VK_IMAGE_TYPE_2D;
+ case vk::VK_IMAGE_VIEW_TYPE_3D: return vk::VK_IMAGE_TYPE_3D;
+ case vk::VK_IMAGE_VIEW_TYPE_CUBE:
+ case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: return vk::VK_IMAGE_TYPE_2D;
+
+ default:
+ DE_FATAL("Impossible");
+ return (vk::VkImageType)0;
+ }
+}
+
+deUint32 getTextureLevelPyramidDataSize (const tcu::TextureLevelPyramid& srcImage)
+{
+ deUint32 dataSize = 0;
+ for (int level = 0; level < srcImage.getNumLevels(); ++level)
+ {
+ const tcu::ConstPixelBufferAccess srcAccess = srcImage.getLevel(level);
+
+ // tightly packed
+ DE_ASSERT(srcAccess.getFormat().getPixelSize() == srcAccess.getPixelPitch());
+
+ dataSize += srcAccess.getWidth() * srcAccess.getHeight() * srcAccess.getDepth() * srcAccess.getFormat().getPixelSize();
+ }
+ return dataSize;
+}
+
+void writeTextureLevelPyramidData (void* dst, deUint32 dstLen, const tcu::TextureLevelPyramid& srcImage, vk::VkImageViewType viewType, std::vector<vk::VkBufferImageCopy>* copySlices)
+{
+ // \note cube is copied face-by-face
+ const deUint32 arraySize = (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? (srcImage.getLevel(0).getHeight()) :
+ (viewType == vk::VK_IMAGE_VIEW_TYPE_2D || viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY) ? (srcImage.getLevel(0).getDepth()) :
+ (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (1) :
+ (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? (srcImage.getLevel(0).getDepth()) :
+ ((deUint32)0);
+ deUint32 levelOffset = 0;
+
+ DE_ASSERT(arraySize != 0);
+
+ for (int level = 0; level < srcImage.getNumLevels(); ++level)
+ {
+ const tcu::ConstPixelBufferAccess srcAccess = srcImage.getLevel(level);
+ const tcu::PixelBufferAccess dstAccess (srcAccess.getFormat(), srcAccess.getSize(), srcAccess.getPitch(), (deUint8*)dst + levelOffset);
+ const deUint32 dataSize = srcAccess.getWidth() * srcAccess.getHeight() * srcAccess.getDepth() * srcAccess.getFormat().getPixelSize();
+ const deUint32 sliceDataSize = dataSize / arraySize;
+ const deInt32 sliceHeight = (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? (1) : (srcAccess.getHeight());
+ const deInt32 sliceDepth = (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (srcAccess.getDepth()) : (1);
+ const tcu::IVec3 sliceSize (srcAccess.getWidth(), sliceHeight, sliceDepth);
+
+ // tightly packed
+ DE_ASSERT(srcAccess.getFormat().getPixelSize() == srcAccess.getPixelPitch());
+
+ for (int sliceNdx = 0; sliceNdx < (int)arraySize; ++sliceNdx)
+ {
+ const vk::VkBufferImageCopy copySlice =
+ {
+ (vk::VkDeviceSize)levelOffset + sliceNdx * sliceDataSize, // bufferOffset
+ (deUint32)sliceSize.x(), // bufferRowLength
+ (deUint32)sliceSize.y(), // bufferImageHeight
+ {
+ vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
+ (deUint32)level, // mipLevel
+ (deUint32)sliceNdx, // arrayLayer
+ 1u, // arraySize
+ }, // imageSubresource
+ {
+ 0,
+ 0,
+ 0,
+ }, // imageOffset
+ {
+ sliceSize.x(),
+ sliceSize.y(),
+ sliceSize.z(),
+ } // imageExtent
+ };
+ copySlices->push_back(copySlice);
+ }
+
+ DE_ASSERT(arraySize * sliceDataSize == dataSize);
+
+ tcu::copy(dstAccess, srcAccess);
+ levelOffset += dataSize;
+ }
+
+ DE_ASSERT(dstLen == levelOffset);
+ DE_UNREF(dstLen);
+}
+
+de::MovePtr<vk::Allocation> allocateAndBindObjectMemory (const vk::DeviceInterface& vki, vk::VkDevice device, vk::Allocator& allocator, vk::VkBuffer buffer, vk::MemoryRequirement requirement)
+{
+ const vk::VkMemoryRequirements requirements = vk::getBufferMemoryRequirements(vki, device, buffer);
+ de::MovePtr<vk::Allocation> allocation = allocator.allocate(requirements, requirement);
+
+ VK_CHECK(vki.bindBufferMemory(device, buffer, allocation->getMemory(), allocation->getOffset()));
+ return allocation;
+}
+
+de::MovePtr<vk::Allocation> allocateAndBindObjectMemory (const vk::DeviceInterface& vki, vk::VkDevice device, vk::Allocator& allocator, vk::VkImage image, vk::MemoryRequirement requirement)
+{
+ const vk::VkMemoryRequirements requirements = vk::getImageMemoryRequirements(vki, device, image);
+ de::MovePtr<vk::Allocation> allocation = allocator.allocate(requirements, requirement);
+
+ VK_CHECK(vki.bindImageMemory(device, image, allocation->getMemory(), allocation->getOffset()));
+ return allocation;
+}
+
+vk::VkDescriptorImageInfo makeDescriptorImageInfo (vk::VkSampler sampler)
+{
+ return vk::makeDescriptorImageInfo(sampler, (vk::VkImageView)0, (vk::VkImageLayout)0);
+}
+
+vk::VkDescriptorImageInfo makeDescriptorImageInfo (vk::VkImageView imageView, vk::VkImageLayout layout)
+{
+ return vk::makeDescriptorImageInfo((vk::VkSampler)0, imageView, layout);
+}
+
+void drawQuadrantReferenceResult (const tcu::PixelBufferAccess& dst, const tcu::Vec4& c1, const tcu::Vec4& c2, const tcu::Vec4& c3, const tcu::Vec4& c4)
+{
+ tcu::clear(tcu::getSubregion(dst, 0, 0, dst.getWidth() / 2, dst.getHeight() / 2), c1);
+ tcu::clear(tcu::getSubregion(dst, dst.getWidth() / 2, 0, dst.getWidth() - dst.getWidth() / 2, dst.getHeight() / 2), c2);
+ tcu::clear(tcu::getSubregion(dst, 0, dst.getHeight() / 2, dst.getWidth() / 2, dst.getHeight() - dst.getHeight() / 2), c3);
+ tcu::clear(tcu::getSubregion(dst, dst.getWidth() / 2, dst.getHeight() / 2, dst.getWidth() - dst.getWidth() / 2, dst.getHeight() - dst.getHeight() / 2), c4);
+}
+
+class SingleTargetRenderInstance : public vkt::TestInstance
+{
+public:
+ SingleTargetRenderInstance (Context& context,
+ const tcu::UVec2& size);
+
+private:
+ static vk::Move<vk::VkImage> createColorAttachment (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::Allocator& allocator,
+ const tcu::TextureFormat& format,
+ const tcu::UVec2& size,
+ de::MovePtr<vk::Allocation>* outAllocation);
+
+ static vk::Move<vk::VkImageView> createColorAttachmentView (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ const tcu::TextureFormat& format,
+ vk::VkImage image);
+
+ static vk::Move<vk::VkRenderPass> createRenderPass (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ const tcu::TextureFormat& format);
+
+ static vk::Move<vk::VkFramebuffer> createFramebuffer (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::VkRenderPass renderpass,
+ vk::VkImageView colorAttachmentView,
+ const tcu::UVec2& size);
+
+ static vk::Move<vk::VkCommandPool> createCommandPool (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ deUint32 queueFamilyIndex);
+
+ virtual void logTestPlan (void) const = 0;
+ virtual void renderToTarget (void) = 0;
+ virtual tcu::TestStatus verifyResultImage (const tcu::ConstPixelBufferAccess& result) const = 0;
+
+ void readRenderTarget (tcu::TextureLevel& dst);
+ tcu::TestStatus iterate (void);
+
+protected:
+ const tcu::TextureFormat m_targetFormat;
+ const tcu::UVec2 m_targetSize;
+
+ const vk::DeviceInterface& m_vki;
+ const vk::VkDevice m_device;
+ const vk::VkQueue m_queue;
+ const deUint32 m_queueFamilyIndex;
+ vk::Allocator& m_allocator;
+ de::MovePtr<vk::Allocation> m_colorAttachmentMemory;
+ const vk::Unique<vk::VkImage> m_colorAttachmentImage;
+ const vk::Unique<vk::VkImageView> m_colorAttachmentView;
+ const vk::Unique<vk::VkRenderPass> m_renderPass;
+ const vk::Unique<vk::VkFramebuffer> m_framebuffer;
+ const vk::Unique<vk::VkCommandPool> m_cmdPool;
+
+ bool m_firstIteration;
+};
+
+SingleTargetRenderInstance::SingleTargetRenderInstance (Context& context,
+ const tcu::UVec2& size)
+ : vkt::TestInstance (context)
+ , m_targetFormat (tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)
+ , m_targetSize (size)
+ , m_vki (context.getDeviceInterface())
+ , m_device (context.getDevice())
+ , m_queue (context.getUniversalQueue())
+ , m_queueFamilyIndex (context.getUniversalQueueFamilyIndex())
+ , m_allocator (context.getDefaultAllocator())
+ , m_colorAttachmentMemory (DE_NULL)
+ , m_colorAttachmentImage (createColorAttachment(m_vki, m_device, m_allocator, m_targetFormat, m_targetSize, &m_colorAttachmentMemory))
+ , m_colorAttachmentView (createColorAttachmentView(m_vki, m_device, m_targetFormat, *m_colorAttachmentImage))
+ , m_renderPass (createRenderPass(m_vki, m_device, m_targetFormat))
+ , m_framebuffer (createFramebuffer(m_vki, m_device, *m_renderPass, *m_colorAttachmentView, m_targetSize))
+ , m_cmdPool (createCommandPool(m_vki, m_device, context.getUniversalQueueFamilyIndex()))
+ , m_firstIteration (true)
+{
+}
+
+vk::Move<vk::VkImage> SingleTargetRenderInstance::createColorAttachment (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::Allocator& allocator,
+ const tcu::TextureFormat& format,
+ const tcu::UVec2& size,
+ de::MovePtr<vk::Allocation>* outAllocation)
+{
+ const vk::VkImageCreateInfo imageInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
+ DE_NULL,
+ (vk::VkImageCreateFlags)0,
+ vk::VK_IMAGE_TYPE_2D, // imageType
+ vk::mapTextureFormat(format), // format
+ { (deInt32)size.x(), (deInt32)size.y(), 1 }, // extent
+ 1, // mipLevels
+ 1, // arraySize
+ vk::VK_SAMPLE_COUNT_1_BIT, // samples
+ vk::VK_IMAGE_TILING_OPTIMAL, // tiling
+ vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // usage
+ vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
+ 0u, // queueFamilyCount
+ DE_NULL, // pQueueFamilyIndices
+ vk::VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout
+ };
+
+ vk::Move<vk::VkImage> image (vk::createImage(vki, device, &imageInfo));
+ de::MovePtr<vk::Allocation> allocation (allocateAndBindObjectMemory(vki, device, allocator, *image, vk::MemoryRequirement::Any));
+
+ *outAllocation = allocation;
+ return image;
+}
+
+vk::Move<vk::VkImageView> SingleTargetRenderInstance::createColorAttachmentView (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ const tcu::TextureFormat& format,
+ vk::VkImage image)
+{
+ const vk::VkImageViewCreateInfo createInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
+ DE_NULL,
+ (vk::VkImageViewCreateFlags)0,
+ image, // image
+ vk::VK_IMAGE_VIEW_TYPE_2D, // viewType
+ vk::mapTextureFormat(format), // format
+ vk::makeComponentMappingRGBA(),
+ {
+ vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
+ 0u, // baseMipLevel
+ 1u, // mipLevels
+ 0u, // baseArrayLayer
+ 1u, // arraySize
+ },
+ };
+
+ return vk::createImageView(vki, device, &createInfo);
+}
+
+vk::Move<vk::VkRenderPass> SingleTargetRenderInstance::createRenderPass (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ const tcu::TextureFormat& format)
+{
+ const vk::VkAttachmentDescription attachmentDescription =
+ {
+ (vk::VkAttachmentDescriptionFlags)0,
+ vk::mapTextureFormat(format), // format
+ vk::VK_SAMPLE_COUNT_1_BIT, // samples
+ vk::VK_ATTACHMENT_LOAD_OP_CLEAR, // loadOp
+ vk::VK_ATTACHMENT_STORE_OP_STORE, // storeOp
+ vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // stencilLoadOp
+ vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // stencilStoreOp
+ vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // initialLayout
+ vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // finalLayout
+ };
+ const vk::VkAttachmentReference colorAttachment =
+ {
+ 0u, // attachment
+ vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // layout
+ };
+ const vk::VkAttachmentReference depthStencilAttachment =
+ {
+ vk::VK_NO_ATTACHMENT, // attachment
+ vk::VK_IMAGE_LAYOUT_UNDEFINED // layout
+ };
+ const vk::VkSubpassDescription subpass =
+ {
+ (vk::VkSubpassDescriptionFlags)0,
+ vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint
+ 0u, // inputAttachmentCount
+ DE_NULL, // pInputAttachments
+ 1u, // colorAttachmentCount
+ &colorAttachment, // pColorAttachments
+ DE_NULL, // pResolveAttachments
+ &depthStencilAttachment, // pDepthStencilAttachment
+ 0u, // preserveAttachmentCount
+ DE_NULL // pPreserveAttachments
+ };
+ const vk::VkRenderPassCreateInfo renderPassCreateInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
+ DE_NULL,
+ (vk::VkRenderPassCreateFlags)0,
+ 1u, // attachmentCount
+ &attachmentDescription, // pAttachments
+ 1u, // subpassCount
+ &subpass, // pSubpasses
+ 0u, // dependencyCount
+ DE_NULL, // pDependencies
+ };
+
+ return vk::createRenderPass(vki, device, &renderPassCreateInfo);
+}
+
+vk::Move<vk::VkFramebuffer> SingleTargetRenderInstance::createFramebuffer (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::VkRenderPass renderpass,
+ vk::VkImageView colorAttachmentView,
+ const tcu::UVec2& size)
+{
+ const vk::VkFramebufferCreateInfo framebufferCreateInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
+ DE_NULL,
+ (vk::VkFramebufferCreateFlags)0,
+ renderpass, // renderPass
+ 1u, // attachmentCount
+ &colorAttachmentView, // pAttachments
+ size.x(), // width
+ size.y(), // height
+ 1, // layers
+ };
+
+ return vk::createFramebuffer(vki, device, &framebufferCreateInfo);
+}
+
+vk::Move<vk::VkCommandPool> SingleTargetRenderInstance::createCommandPool (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ deUint32 queueFamilyIndex)
+{
+ const vk::VkCommandPoolCreateInfo createInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
+ DE_NULL,
+ vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // flags
+ queueFamilyIndex, // queueFamilyIndex
+ };
+ return vk::createCommandPool(vki, device, &createInfo);
+}
+
+void SingleTargetRenderInstance::readRenderTarget (tcu::TextureLevel& dst)
+{
+ const deUint64 pixelDataSize = (deUint64)(m_targetSize.x() * m_targetSize.y() * m_targetFormat.getPixelSize());
+ const vk::VkBufferCreateInfo bufferCreateInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
+ DE_NULL,
+ 0u, // flags
+ pixelDataSize, // size
+ vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT, // usage
+ vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
+ 0u, // queueFamilyCount
+ DE_NULL, // pQueueFamilyIndices
+ };
+ const vk::Unique<vk::VkBuffer> buffer (vk::createBuffer(m_vki, m_device, &bufferCreateInfo));
+ const vk::VkImageSubresourceRange fullSubrange =
+ {
+ vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
+ 0u, // baseMipLevel
+ 1u, // mipLevels
+ 0u, // baseArraySlice
+ 1u, // arraySize
+ };
+ const vk::VkImageMemoryBarrier imageBarrier =
+ {
+ vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
+ DE_NULL,
+ vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // srcAccessMask
+ vk::VK_ACCESS_TRANSFER_READ_BIT, // dstAccessMask
+ vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // oldLayout
+ vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // newLayout
+ vk::VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
+ vk::VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex
+ *m_colorAttachmentImage, // image
+ fullSubrange, // subresourceRange
+ };
+ const vk::VkBufferMemoryBarrier memoryBarrier =
+ {
+ vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
+ DE_NULL,
+ vk::VK_ACCESS_TRANSFER_WRITE_BIT, // srcAccessMask
+ vk::VK_ACCESS_HOST_READ_BIT, // dstAccessMask
+ vk::VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
+ vk::VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex
+ *buffer, // buffer
+ 0u, // offset
+ (vk::VkDeviceSize)pixelDataSize // size
+ };
+ const vk::VkCommandBufferAllocateInfo cmdBufAllocInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
+ DE_NULL,
+ *m_cmdPool, // cmdPool
+ vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level
+ 1u, // bufferCount
+ };
+ const vk::VkFenceCreateInfo fenceCreateInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
+ DE_NULL,
+ 0u, // flags
+ };
+ const vk::VkCommandBufferBeginInfo cmdBufBeginInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+ DE_NULL,
+ vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // flags
+ (vk::VkRenderPass)0u, // renderPass
+ 0u, // subpass
+ (vk::VkFramebuffer)0u, // framebuffer
+ vk::VK_FALSE, // occlusionQueryEnable
+ (vk::VkQueryControlFlags)0,
+ (vk::VkQueryPipelineStatisticFlags)0,
+ };
+ const vk::VkImageSubresourceLayers firstSlice =
+ {
+ vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspect
+ 0, // mipLevel
+ 0, // arrayLayer
+ 1, // arraySize
+ };
+ const vk::VkBufferImageCopy copyRegion =
+ {
+ 0u, // bufferOffset
+ m_targetSize.x(), // bufferRowLength
+ m_targetSize.y(), // bufferImageHeight
+ firstSlice, // imageSubresource
+ { 0, 0, 0 }, // imageOffset
+ { (deInt32)m_targetSize.x(), (deInt32)m_targetSize.y(), 1 } // imageExtent
+ };
+
+ const de::MovePtr<vk::Allocation> bufferMemory = allocateAndBindObjectMemory(m_vki, m_device, m_allocator, *buffer, vk::MemoryRequirement::HostVisible);
+
+ const vk::Unique<vk::VkCommandBuffer> cmd (vk::allocateCommandBuffer(m_vki, m_device, &cmdBufAllocInfo));
+ const vk::Unique<vk::VkFence> cmdCompleteFence (vk::createFence(m_vki, m_device, &fenceCreateInfo));
+ const void* const imageBarrierPtr = &imageBarrier;
+ const void* const bufferBarrierPtr = &memoryBarrier;
+ const deUint64 infiniteTimeout = ~(deUint64)0u;
+
+ // copy content to buffer
+ VK_CHECK(m_vki.beginCommandBuffer(*cmd, &cmdBufBeginInfo));
+ m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_FALSE, 1, &imageBarrierPtr);
+ m_vki.cmdCopyImageToBuffer(*cmd, *m_colorAttachmentImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *buffer, 1, ©Region);
+ m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_FALSE, 1, &bufferBarrierPtr);
+ VK_CHECK(m_vki.endCommandBuffer(*cmd));
+
+ // wait for transfer to complete
+ {
+ const vk::VkSubmitInfo submitInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
+ DE_NULL,
+ 0u,
+ (const vk::VkSemaphore*)0,
+ 1u,
+ &cmd.get(),
+ 0u,
+ (const vk::VkSemaphore*)0,
+ };
+
+ VK_CHECK(m_vki.queueSubmit(m_queue, 1, &submitInfo, *cmdCompleteFence));
+ }
+ VK_CHECK(m_vki.waitForFences(m_device, 1, &cmdCompleteFence.get(), 0u, infiniteTimeout)); // \note: timeout is failure
+
+ dst.setStorage(m_targetFormat, m_targetSize.x(), m_targetSize.y());
+
+ // copy data
+ invalidateMappedMemoryRange(m_vki, m_device, bufferMemory->getMemory(), bufferMemory->getOffset(), pixelDataSize);
+ tcu::copy(dst, tcu::ConstPixelBufferAccess(dst.getFormat(), dst.getSize(), bufferMemory->getHostPtr()));
+}
+
+tcu::TestStatus SingleTargetRenderInstance::iterate (void)
+{
+ tcu::TextureLevel resultImage;
+
+ // log
+ if (m_firstIteration)
+ {
+ logTestPlan();
+ m_firstIteration = false;
+ }
+
+ // render
+ {
+ // transition to VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
+ const vk::VkImageSubresourceRange fullSubrange =
+ {
+ vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
+ 0u, // baseMipLevel
+ 1u, // mipLevels
+ 0u, // baseArraySlice
+ 1u, // arraySize
+ };
+ const vk::VkImageMemoryBarrier imageBarrier =
+ {
+ vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
+ DE_NULL,
+ 0u, // srcAccessMask
+ vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // dstAccessMask
+ vk::VK_IMAGE_LAYOUT_UNDEFINED, // oldLayout
+ vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // newLayout
+ vk::VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
+ vk::VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex
+ *m_colorAttachmentImage, // image
+ fullSubrange, // subresourceRange
+ };
+ const vk::VkCommandBufferAllocateInfo cmdBufAllocInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
+ DE_NULL,
+ *m_cmdPool, // cmdPool
+ vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level
+ 1u, // count
+ };
+ const vk::VkCommandBufferBeginInfo cmdBufBeginInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+ DE_NULL,
+ vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // flags
+ (vk::VkRenderPass)0u, // renderPass
+ 0u, // subpass
+ (vk::VkFramebuffer)0u, // framebuffer
+ vk::VK_FALSE, // occlusionQueryEnable
+ (vk::VkQueryControlFlags)0,
+ (vk::VkQueryPipelineStatisticFlags)0,
+ };
+
+ const vk::Unique<vk::VkCommandBuffer> cmd (vk::allocateCommandBuffer(m_vki, m_device, &cmdBufAllocInfo));
+ const void* const imageBarrierPtr = &imageBarrier;
+
+ VK_CHECK(m_vki.beginCommandBuffer(*cmd, &cmdBufBeginInfo));
+ m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_FALSE, 1, &imageBarrierPtr);
+ VK_CHECK(m_vki.endCommandBuffer(*cmd));
+
+ {
+ const vk::VkSubmitInfo submitInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
+ DE_NULL,
+ 0u,
+ (const vk::VkSemaphore*)0,
+ 1u,
+ &cmd.get(),
+ 0u,
+ (const vk::VkSemaphore*)0,
+ };
+
+ VK_CHECK(m_vki.queueSubmit(m_queue, 1, &submitInfo, (vk::VkFence)0));
+ }
+
+ // and then render to
+ renderToTarget();
+ }
+
+ // read and verify
+ readRenderTarget(resultImage);
+ return verifyResultImage(resultImage.getAccess());
+}
+
+class RenderInstanceShaders
+{
+public:
+ RenderInstanceShaders (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ const vk::VkPhysicalDeviceFeatures& deviceFeatures,
+ const vk::BinaryCollection& programCollection);
+
+ inline bool hasTessellationStage (void) const { return *m_tessCtrlShaderModule != 0 || *m_tessEvalShaderModule != 0; }
+ inline deUint32 getNumStages (void) const { return (deUint32)m_stageInfos.size(); }
+ inline const vk::VkPipelineShaderStageCreateInfo* getStages (void) const { return &m_stageInfos[0]; }
+
+private:
+ void addStage (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ const vk::VkPhysicalDeviceFeatures& deviceFeatures,
+ const vk::BinaryCollection& programCollection,
+ const char* name,
+ vk::VkShaderStageFlagBits stage,
+ vk::Move<vk::VkShaderModule>* outModule);
+
+ vk::VkPipelineShaderStageCreateInfo getShaderStageCreateInfo (vk::VkShaderStageFlagBits stage, vk::VkShaderModule shader) const;
+
+ vk::Move<vk::VkShaderModule> m_vertexShaderModule;
+ vk::Move<vk::VkShaderModule> m_tessCtrlShaderModule;
+ vk::Move<vk::VkShaderModule> m_tessEvalShaderModule;
+ vk::Move<vk::VkShaderModule> m_geometryShaderModule;
+ vk::Move<vk::VkShaderModule> m_fragmentShaderModule;
+ std::vector<vk::VkPipelineShaderStageCreateInfo> m_stageInfos;
+};
+
+RenderInstanceShaders::RenderInstanceShaders (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ const vk::VkPhysicalDeviceFeatures& deviceFeatures,
+ const vk::BinaryCollection& programCollection)
+{
+ addStage(vki, device, deviceFeatures, programCollection, "vertex", vk::VK_SHADER_STAGE_VERTEX_BIT, &m_vertexShaderModule);
+ addStage(vki, device, deviceFeatures, programCollection, "tess_ctrl", vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, &m_tessCtrlShaderModule);
+ addStage(vki, device, deviceFeatures, programCollection, "tess_eval", vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, &m_tessEvalShaderModule);
+ addStage(vki, device, deviceFeatures, programCollection, "geometry", vk::VK_SHADER_STAGE_GEOMETRY_BIT, &m_geometryShaderModule);
+ addStage(vki, device, deviceFeatures, programCollection, "fragment", vk::VK_SHADER_STAGE_FRAGMENT_BIT, &m_fragmentShaderModule);
+
+ DE_ASSERT(!m_stageInfos.empty());
+}
+
+void RenderInstanceShaders::addStage (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ const vk::VkPhysicalDeviceFeatures& deviceFeatures,
+ const vk::BinaryCollection& programCollection,
+ const char* name,
+ vk::VkShaderStageFlagBits stage,
+ vk::Move<vk::VkShaderModule>* outModule)
+{
+ if (programCollection.contains(name))
+ {
+ if (vk::isShaderStageSupported(deviceFeatures, stage))
+ {
+ vk::Move<vk::VkShaderModule> module = createShaderModule(vki, device, programCollection.get(name), (vk::VkShaderModuleCreateFlags)0);
+
+ m_stageInfos.push_back(getShaderStageCreateInfo(stage, *module));
+ *outModule = module;
+ }
+ else
+ TCU_THROW(NotSupportedError, (de::toString(stage) + " is not supported").c_str());
+ }
+}
+
+vk::VkPipelineShaderStageCreateInfo RenderInstanceShaders::getShaderStageCreateInfo (vk::VkShaderStageFlagBits stage, vk::VkShaderModule shader) const
+{
+ const vk::VkPipelineShaderStageCreateInfo stageCreateInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ DE_NULL,
+ (vk::VkPipelineShaderStageCreateFlags)0,
+ stage, // stage
+ shader, // shader
+ "main",
+ DE_NULL, // pSpecializationInfo
+ };
+ return stageCreateInfo;
+}
+
+class SingleCmdRenderInstance : public SingleTargetRenderInstance
+{
+public:
+ SingleCmdRenderInstance (Context& context,
+ bool isPrimaryCmdBuf,
+ const tcu::UVec2& renderSize);
+
+private:
+ vk::Move<vk::VkPipeline> createPipeline (vk::VkPipelineLayout pipelineLayout);
+
+ virtual vk::VkPipelineLayout getPipelineLayout (void) const = 0;
+ virtual void writeDrawCmdBuffer (vk::VkCommandBuffer cmd) const = 0;
+
+ void renderToTarget (void);
+
+ const bool m_isPrimaryCmdBuf;
+};
+
+SingleCmdRenderInstance::SingleCmdRenderInstance (Context& context,
+ bool isPrimaryCmdBuf,
+ const tcu::UVec2& renderSize)
+ : SingleTargetRenderInstance (context, renderSize)
+ , m_isPrimaryCmdBuf (isPrimaryCmdBuf)
+{
+}
+
+vk::Move<vk::VkPipeline> SingleCmdRenderInstance::createPipeline (vk::VkPipelineLayout pipelineLayout)
+{
+ const RenderInstanceShaders shaderStages (m_vki, m_device, m_context.getDeviceFeatures(), m_context.getBinaryCollection());
+ const vk::VkPrimitiveTopology topology = shaderStages.hasTessellationStage() ? vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ const vk::VkPipelineVertexInputStateCreateInfo vertexInputState =
+ {
+ vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
+ DE_NULL,
+ (vk::VkPipelineVertexInputStateCreateFlags)0,
+ 0u, // bindingCount
+ DE_NULL, // pVertexBindingDescriptions
+ 0u, // attributeCount
+ DE_NULL, // pVertexAttributeDescriptions
+ };
+ const vk::VkPipelineInputAssemblyStateCreateInfo iaState =
+ {
+ vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
+ DE_NULL,
+ (vk::VkPipelineInputAssemblyStateCreateFlags)0,
+ topology, // topology
+ vk::VK_FALSE, // primitiveRestartEnable
+ };
+ const vk::VkPipelineTessellationStateCreateInfo tessState =
+ {
+ vk::VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,
+ DE_NULL,
+ (vk::VkPipelineTesselationStateCreateFlags)0,
+ 3u, // patchControlPoints
+ };
+ const vk::VkViewport viewport =
+ {
+ 0.0f, // originX
+ 0.0f, // originY
+ float(m_targetSize.x()), // width
+ float(m_targetSize.y()), // height
+ 0.0f, // minDepth
+ 1.0f, // maxDepth
+ };
+ const vk::VkRect2D renderArea =
+ {
+ { 0, 0 }, // offset
+ { (deInt32)m_targetSize.x(), (deInt32)m_targetSize.y() }, // extent
+ };
+ const vk::VkPipelineViewportStateCreateInfo vpState =
+ {
+ vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
+ DE_NULL,
+ (vk::VkPipelineViewportStateCreateFlags)0,
+ 1u, // viewportCount
+ &viewport,
+ 1u,
+ &renderArea,
+ };
+ const vk::VkPipelineRasterizationStateCreateInfo rsState =
+ {
+ vk::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
+ DE_NULL,
+ (vk::VkPipelineRasterizationStateCreateFlags)0,
+ vk::VK_TRUE, // depthClipEnable
+ vk::VK_FALSE, // rasterizerDiscardEnable
+ vk::VK_POLYGON_MODE_FILL, // fillMode
+ vk::VK_CULL_MODE_NONE, // cullMode
+ vk::VK_FRONT_FACE_COUNTER_CLOCKWISE, // frontFace
+ vk::VK_FALSE, // depthBiasEnable
+ 0.0f, // depthBias
+ 0.0f, // depthBiasClamp
+ 0.0f, // slopeScaledDepthBias
+ 1.0f, // lineWidth
+ };
+ const vk::VkSampleMask sampleMask = 0x01u;
+ const vk::VkPipelineMultisampleStateCreateInfo msState =
+ {
+ vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
+ DE_NULL,
+ (vk::VkPipelineMultisampleStateCreateFlags)0,
+ vk::VK_SAMPLE_COUNT_1_BIT, // rasterSamples
+ vk::VK_FALSE, // sampleShadingEnable
+ 0.0f, // minSampleShading
+ &sampleMask, // sampleMask
+ vk::VK_FALSE, // alphaToCoverageEnable
+ vk::VK_FALSE, // alphaToOneEnable
+ };
+ const vk::VkPipelineDepthStencilStateCreateInfo dsState =
+ {
+ vk::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
+ DE_NULL,
+ (vk::VkPipelineDepthStencilStateCreateFlags)0,
+ vk::VK_FALSE, // depthTestEnable
+ vk::VK_FALSE, // depthWriteEnable
+ vk::VK_COMPARE_OP_ALWAYS, // depthCompareOp
+ vk::VK_FALSE, // depthBoundsTestEnable
+ vk::VK_FALSE, // stencilTestEnable
+ { vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_COMPARE_OP_ALWAYS, 0u, 0u, 0u }, // front
+ { vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_COMPARE_OP_ALWAYS, 0u, 0u, 0u }, // back
+ -1.0f, // minDepthBounds
+ +1.0f, // maxDepthBounds
+ };
+ const vk::VkPipelineColorBlendAttachmentState cbAttachment =
+ {
+ vk::VK_FALSE, // blendEnable
+ vk::VK_BLEND_FACTOR_ZERO, // srcBlendColor
+ vk::VK_BLEND_FACTOR_ZERO, // destBlendColor
+ vk::VK_BLEND_OP_ADD, // blendOpColor
+ vk::VK_BLEND_FACTOR_ZERO, // srcBlendAlpha
+ vk::VK_BLEND_FACTOR_ZERO, // destBlendAlpha
+ vk::VK_BLEND_OP_ADD, // blendOpAlpha
+ (vk::VK_COLOR_COMPONENT_R_BIT |
+ vk::VK_COLOR_COMPONENT_G_BIT |
+ vk::VK_COLOR_COMPONENT_B_BIT |
+ vk::VK_COLOR_COMPONENT_A_BIT), // channelWriteMask
+ };
+ const vk::VkPipelineColorBlendStateCreateInfo cbState =
+ {
+ vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
+ DE_NULL,
+ (vk::VkPipelineColorBlendStateCreateFlags)0,
+ vk::VK_FALSE, // logicOpEnable
+ vk::VK_LOGIC_OP_CLEAR, // logicOp
+ 1u, // attachmentCount
+ &cbAttachment, // pAttachments
+ { 0.0f, 0.0f, 0.0f, 0.0f }, // blendConst
+ };
+ const vk::VkPipelineDynamicStateCreateInfo dynState =
+ {
+ vk::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
+ DE_NULL,
+ (vk::VkPipelineDynamicStateCreateFlags)0,
+ 0u, // dynamicStateCount
+ DE_NULL, // pDynamicStates
+ };
+ const vk::VkGraphicsPipelineCreateInfo createInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
+ DE_NULL,
+ (vk::VkPipelineCreateFlags)0,
+ shaderStages.getNumStages(), // stageCount
+ shaderStages.getStages(), // pStages
+ &vertexInputState, // pVertexInputState
+ &iaState, // pInputAssemblyState
+ (shaderStages.hasTessellationStage() ? &tessState : DE_NULL), // pTessellationState
+ &vpState, // pViewportState
+ &rsState, // pRasterState
+ &msState, // pMultisampleState
+ &dsState, // pDepthStencilState
+ &cbState, // pColorBlendState
+ &dynState, // pDynamicState
+ pipelineLayout, // layout
+ *m_renderPass, // renderPass
+ 0u, // subpass
+ (vk::VkPipeline)0, // basePipelineHandle
+ 0u, // basePipelineIndex
+ };
+ return createGraphicsPipeline(m_vki, m_device, (vk::VkPipelineCache)0u, &createInfo);
+}
+
+void SingleCmdRenderInstance::renderToTarget (void)
+{
+ const vk::VkRect2D renderArea =
+ {
+ { 0, 0 }, // offset
+ { (deInt32)m_targetSize.x(), (deInt32)m_targetSize.y() }, // extent
+ };
+ const vk::VkCommandBufferAllocateInfo mainCmdBufCreateInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
+ DE_NULL,
+ *m_cmdPool, // cmdPool
+ vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level
+ 1u, // count
+ };
+ const vk::VkCommandBufferBeginInfo mainCmdBufBeginInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+ DE_NULL,
+ vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // flags
+ (vk::VkRenderPass)0u, // renderPass
+ 0u, // subpass
+ (vk::VkFramebuffer)0u, // framebuffer
+ vk::VK_FALSE, // occlusionQueryEnable
+ (vk::VkQueryControlFlags)0,
+ (vk::VkQueryPipelineStatisticFlags)0,
+ };
+ const vk::VkCommandBufferAllocateInfo passCmdBufCreateInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
+ DE_NULL,
+ *m_cmdPool, // cmdPool
+ vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY, // level
+ 1u, // count
+ };
+ const vk::VkCommandBufferBeginInfo passCmdBufBeginInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+ DE_NULL,
+ vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT |
+ vk::VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, // flags
+ (vk::VkRenderPass)*m_renderPass, // renderPass
+ 0u, // subpass
+ (vk::VkFramebuffer)*m_framebuffer, // framebuffer
+ vk::VK_FALSE, // occlusionQueryEnable
+ (vk::VkQueryControlFlags)0,
+ (vk::VkQueryPipelineStatisticFlags)0,
+ };
+ const vk::VkFenceCreateInfo fenceCreateInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
+ DE_NULL,
+ 0u, // flags
+ };
+ const vk::VkClearValue clearValue = vk::makeClearValueColorF32(0.0f, 0.0f, 0.0f, 0.0f);
+ const vk::VkRenderPassBeginInfo renderPassBeginInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
+ DE_NULL,
+ *m_renderPass, // renderPass
+ *m_framebuffer, // framebuffer
+ renderArea, // renderArea
+ 1u, // clearValueCount
+ &clearValue, // pClearValues
+ };
+
+ const vk::VkPipelineLayout pipelineLayout (getPipelineLayout());
+ const vk::Unique<vk::VkPipeline> pipeline (createPipeline(pipelineLayout));
+ const vk::Unique<vk::VkCommandBuffer> mainCmd (vk::allocateCommandBuffer(m_vki, m_device, &mainCmdBufCreateInfo));
+ const vk::Unique<vk::VkCommandBuffer> passCmd ((m_isPrimaryCmdBuf) ? (vk::Move<vk::VkCommandBuffer>()) : (vk::allocateCommandBuffer(m_vki, m_device, &passCmdBufCreateInfo)));
+ const vk::Unique<vk::VkFence> fence (vk::createFence(m_vki, m_device, &fenceCreateInfo));
+ const deUint64 infiniteTimeout = ~(deUint64)0u;
+ const vk::VkSubpassContents passContents = (m_isPrimaryCmdBuf) ? (vk::VK_SUBPASS_CONTENTS_INLINE) : (vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
+
+ VK_CHECK(m_vki.beginCommandBuffer(*mainCmd, &mainCmdBufBeginInfo));
+ m_vki.cmdBeginRenderPass(*mainCmd, &renderPassBeginInfo, passContents);
+
+ if (m_isPrimaryCmdBuf)
+ {
+ m_vki.cmdBindPipeline(*mainCmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
+ writeDrawCmdBuffer(*mainCmd);
+ }
+ else
+ {
+ VK_CHECK(m_vki.beginCommandBuffer(*passCmd, &passCmdBufBeginInfo));
+ m_vki.cmdBindPipeline(*passCmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
+ writeDrawCmdBuffer(*passCmd);
+ VK_CHECK(m_vki.endCommandBuffer(*passCmd));
+
+ m_vki.cmdExecuteCommands(*mainCmd, 1, &passCmd.get());
+ }
+
+ m_vki.cmdEndRenderPass(*mainCmd);
+ VK_CHECK(m_vki.endCommandBuffer(*mainCmd));
+
+ // submit and wait for them to finish before exiting scope. (Killing in-flight objects is a no-no).
+ {
+ const vk::VkSubmitInfo submitInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
+ DE_NULL,
+ 0u,
+ (const vk::VkSemaphore*)0,
+ 1u,
+ &mainCmd.get(),
+ 0u,
+ (const vk::VkSemaphore*)0,
+ };
+ VK_CHECK(m_vki.queueSubmit(m_queue, 1, &submitInfo, *fence));
+ }
+ VK_CHECK(m_vki.waitForFences(m_device, 1, &fence.get(), 0u, infiniteTimeout)); // \note: timeout is failure
+}
+
+enum ShaderInputInterface
+{
+ SHADER_INPUT_SINGLE_DESCRIPTOR = 0, //!< one descriptor
+ SHADER_INPUT_MULTIPLE_DESCRIPTORS, //!< multiple descriptors
+ SHADER_INPUT_DESCRIPTOR_ARRAY, //!< descriptor array
+
+ SHADER_INPUT_LAST
+};
+
+deUint32 getInterfaceNumResources (ShaderInputInterface shaderInterface)
+{
+ switch (shaderInterface)
+ {
+ case SHADER_INPUT_SINGLE_DESCRIPTOR: return 1u;
+ case SHADER_INPUT_MULTIPLE_DESCRIPTORS: return 2u;
+ case SHADER_INPUT_DESCRIPTOR_ARRAY: return 2u;
+
+ default:
+ DE_FATAL("Impossible");
+ return 0u;
+ }
+}
+
+class BufferRenderInstance : public SingleCmdRenderInstance
+{
+public:
+ BufferRenderInstance (Context& context,
+ bool isPrimaryCmdBuf,
+ vk::VkDescriptorType descriptorType,
+ vk::VkShaderStageFlags stageFlags,
+ ShaderInputInterface shaderInterface,
+ bool viewOffset,
+ bool dynamicOffset,
+ bool dynamicOffsetNonZero);
+
+ static vk::Move<vk::VkBuffer> createSourceBuffer (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::Allocator& allocator,
+ vk::VkDescriptorType descriptorType,
+ deUint32 offset,
+ deUint32 bufferSize,
+ de::MovePtr<vk::Allocation>* outMemory);
+
+ static vk::Move<vk::VkDescriptorPool> createDescriptorPool (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::VkDescriptorType descriptorType,
+ ShaderInputInterface shaderInterface);
+
+ static vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::VkDescriptorType descriptorType,
+ ShaderInputInterface shaderInterface,
+ vk::VkShaderStageFlags stageFlags);
+
+ static vk::Move<vk::VkDescriptorSet> createDescriptorSet (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::VkDescriptorSetLayout descriptorSetLayout,
+ vk::VkDescriptorPool descriptorPool,
+ vk::VkDescriptorType descriptorType,
+ ShaderInputInterface shaderInterface,
+ vk::VkBuffer sourceBufferA,
+ const deUint32 viewOffsetA,
+ vk::VkBuffer sourceBufferB,
+ const deUint32 viewOffsetB);
+
+ static vk::Move<vk::VkPipelineLayout> createPipelineLayout (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::VkDescriptorSetLayout descriptorSetLayout);
+
+ void logTestPlan (void) const;
+ vk::VkPipelineLayout getPipelineLayout (void) const;
+ void writeDrawCmdBuffer (vk::VkCommandBuffer cmd) const;
+ tcu::TestStatus verifyResultImage (const tcu::ConstPixelBufferAccess& result) const;
+
+ enum
+ {
+ RENDER_SIZE = 128,
+ BUFFER_DATA_SIZE = 8 * sizeof(float),
+ BUFFER_SIZE_A = 2048, //!< a lot more than required
+ BUFFER_SIZE_B = 2560, //!< a lot more than required
+
+ STATIC_OFFSET_VALUE_A = 256,
+ DYNAMIC_OFFSET_VALUE_A = 512,
+ STATIC_OFFSET_VALUE_B = 1024,
+ DYNAMIC_OFFSET_VALUE_B = 768,
+ };
+
+ const vk::VkDescriptorType m_descriptorType;
+ const ShaderInputInterface m_shaderInterface;
+ const bool m_setViewOffset;
+ const bool m_setDynamicOffset;
+ const bool m_dynamicOffsetNonZero;
+ const vk::VkShaderStageFlags m_stageFlags;
+
+ const deUint32 m_viewOffsetA;
+ const deUint32 m_viewOffsetB;
+ const deUint32 m_dynamicOffsetA;
+ const deUint32 m_dynamicOffsetB;
+ const deUint32 m_effectiveOffsetA;
+ const deUint32 m_effectiveOffsetB;
+ const deUint32 m_bufferSizeA;
+ const deUint32 m_bufferSizeB;
+
+ de::MovePtr<vk::Allocation> m_bufferMemoryA;
+ de::MovePtr<vk::Allocation> m_bufferMemoryB;
+ const vk::Unique<vk::VkBuffer> m_sourceBufferA;
+ const vk::Unique<vk::VkBuffer> m_sourceBufferB;
+ const vk::Unique<vk::VkDescriptorPool> m_descriptorPool;
+ const vk::Unique<vk::VkDescriptorSetLayout> m_descriptorSetLayout;
+ const vk::Unique<vk::VkDescriptorSet> m_descriptorSet;
+ const vk::Unique<vk::VkPipelineLayout> m_pipelineLayout;
+};
+
+BufferRenderInstance::BufferRenderInstance (Context& context,
+ bool isPrimaryCmdBuf,
+ vk::VkDescriptorType descriptorType,
+ vk::VkShaderStageFlags stageFlags,
+ ShaderInputInterface shaderInterface,
+ bool viewOffset,
+ bool dynamicOffset,
+ bool dynamicOffsetNonZero)
+ : SingleCmdRenderInstance (context, isPrimaryCmdBuf, tcu::UVec2(RENDER_SIZE, RENDER_SIZE))
+ , m_descriptorType (descriptorType)
+ , m_shaderInterface (shaderInterface)
+ , m_setViewOffset (viewOffset)
+ , m_setDynamicOffset (dynamicOffset)
+ , m_dynamicOffsetNonZero (dynamicOffsetNonZero)
+ , m_stageFlags (stageFlags)
+ , m_viewOffsetA ((m_setViewOffset) ? ((deUint32)STATIC_OFFSET_VALUE_A) : (0u))
+ , m_viewOffsetB ((m_setViewOffset) ? ((deUint32)STATIC_OFFSET_VALUE_B) : (0u))
+ , m_dynamicOffsetA ((dynamicOffsetNonZero) ? ((deUint32)DYNAMIC_OFFSET_VALUE_A) : (0u))
+ , m_dynamicOffsetB ((dynamicOffsetNonZero) ? ((deUint32)DYNAMIC_OFFSET_VALUE_B) : (0u))
+ , m_effectiveOffsetA ((isDynamicDescriptorType(m_descriptorType)) ? (m_viewOffsetA + m_dynamicOffsetA) : (m_viewOffsetA))
+ , m_effectiveOffsetB ((isDynamicDescriptorType(m_descriptorType)) ? (m_viewOffsetB + m_dynamicOffsetB) : (m_viewOffsetB))
+ , m_bufferSizeA (BUFFER_SIZE_A)
+ , m_bufferSizeB (BUFFER_SIZE_B)
+ , m_bufferMemoryA (DE_NULL)
+ , m_bufferMemoryB (DE_NULL)
+ , m_sourceBufferA (createSourceBuffer(m_vki, m_device, m_allocator, m_descriptorType, m_effectiveOffsetA, m_bufferSizeA, &m_bufferMemoryA))
+ , m_sourceBufferB ((getInterfaceNumResources(m_shaderInterface) == 1u)
+ ? vk::Move<vk::VkBuffer>()
+ : createSourceBuffer(m_vki, m_device, m_allocator, m_descriptorType, m_effectiveOffsetB, m_bufferSizeB, &m_bufferMemoryB))
+ , m_descriptorPool (createDescriptorPool(m_vki, m_device, m_descriptorType, m_shaderInterface))
+ , m_descriptorSetLayout (createDescriptorSetLayout(m_vki, m_device, m_descriptorType, m_shaderInterface, m_stageFlags))
+ , m_descriptorSet (createDescriptorSet(m_vki, m_device, *m_descriptorSetLayout, *m_descriptorPool, m_descriptorType, m_shaderInterface, *m_sourceBufferA, m_viewOffsetA, *m_sourceBufferB, m_viewOffsetB))
+ , m_pipelineLayout (createPipelineLayout(m_vki, m_device, *m_descriptorSetLayout))
+{
+ if (m_setDynamicOffset)
+ DE_ASSERT(isDynamicDescriptorType(m_descriptorType));
+ if (m_dynamicOffsetNonZero)
+ DE_ASSERT(m_setDynamicOffset);
+}
+
+vk::Move<vk::VkBuffer> BufferRenderInstance::createSourceBuffer (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::Allocator& allocator,
+ vk::VkDescriptorType descriptorType,
+ deUint32 offset,
+ deUint32 bufferSize,
+ de::MovePtr<vk::Allocation>* outMemory)
+{
+ static const float s_colors[] =
+ {
+ 0.0f, 1.0f, 0.0f, 1.0f, // green
+ 1.0f, 1.0f, 0.0f, 1.0f, // yellow
+ };
+ DE_STATIC_ASSERT(sizeof(s_colors) == BUFFER_DATA_SIZE);
+ DE_ASSERT(offset + BUFFER_DATA_SIZE <= bufferSize);
+ DE_ASSERT(offset % sizeof(float) == 0);
+ DE_ASSERT(bufferSize % sizeof(float) == 0);
+
+ const bool isUniformBuffer = isUniformDescriptorType(descriptorType);
+ const vk::VkBufferUsageFlags usageFlags = (isUniformBuffer) ? (vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) : (vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
+ const float preGuardValue = 0.5f;
+ const float postGuardValue = 0.75f;
+ const vk::VkBufferCreateInfo bufferCreateInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
+ DE_NULL,
+ 0u, // flags
+ bufferSize, // size
+ usageFlags, // usage
+ vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
+ 0u, // queueFamilyCount
+ DE_NULL, // pQueueFamilyIndices
+ };
+ vk::Move<vk::VkBuffer> buffer (vk::createBuffer(vki, device, &bufferCreateInfo));
+ de::MovePtr<vk::Allocation> bufferMemory = allocateAndBindObjectMemory(vki, device, allocator, *buffer, vk::MemoryRequirement::HostVisible);
+ void* const mapPtr = bufferMemory->getHostPtr();
+
+ // guard with interesting values
+ for (size_t preGuardOffset = 0; preGuardOffset + sizeof(float) <= (size_t)offset; preGuardOffset += sizeof(float))
+ deMemcpy((deUint8*)mapPtr + preGuardOffset, &preGuardValue, sizeof(float));
+
+ deMemcpy((deUint8*)mapPtr + offset, s_colors, sizeof(s_colors));
+ for (size_t postGuardOffset = (size_t)offset + sizeof(s_colors); postGuardOffset + sizeof(float) <= (size_t)bufferSize; postGuardOffset += sizeof(float))
+ deMemcpy((deUint8*)mapPtr + postGuardOffset, &postGuardValue, sizeof(float));
+ deMemset((deUint8*)mapPtr + offset + sizeof(s_colors), 0x5A, (size_t)bufferSize - (size_t)offset - sizeof(s_colors)); // fill with interesting pattern that produces valid floats
+
+ flushMappedMemoryRange(vki, device, bufferMemory->getMemory(), bufferMemory->getOffset(), bufferSize);
+
+ *outMemory = bufferMemory;
+ return buffer;
+}
+
+vk::Move<vk::VkDescriptorPool> BufferRenderInstance::createDescriptorPool (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::VkDescriptorType descriptorType,
+ ShaderInputInterface shaderInterface)
+{
+ return vk::DescriptorPoolBuilder()
+ .addType(descriptorType, getInterfaceNumResources(shaderInterface))
+ .build(vki, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
+}
+
+vk::Move<vk::VkDescriptorSetLayout> BufferRenderInstance::createDescriptorSetLayout (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::VkDescriptorType descriptorType,
+ ShaderInputInterface shaderInterface,
+ vk::VkShaderStageFlags stageFlags)
+{
+ vk::DescriptorSetLayoutBuilder builder;
+
+ switch (shaderInterface)
+ {
+ case SHADER_INPUT_SINGLE_DESCRIPTOR:
+ builder.addSingleBinding(descriptorType, stageFlags);
+ break;
+
+ case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
+ builder.addSingleBinding(descriptorType, stageFlags);
+ builder.addSingleBinding(descriptorType, stageFlags);
+ break;
+
+ case SHADER_INPUT_DESCRIPTOR_ARRAY:
+ builder.addArrayBinding(descriptorType, 2u, stageFlags);
+ break;
+
+ default:
+ DE_FATAL("Impossible");
+ }
+
+ return builder.build(vki, device);
+}
+
+vk::Move<vk::VkDescriptorSet> BufferRenderInstance::createDescriptorSet (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::VkDescriptorSetLayout descriptorSetLayout,
+ vk::VkDescriptorPool descriptorPool,
+ vk::VkDescriptorType descriptorType,
+ ShaderInputInterface shaderInterface,
+ vk::VkBuffer bufferA,
+ deUint32 offsetA,
+ vk::VkBuffer bufferB,
+ deUint32 offsetB)
+{
+ const vk::VkDescriptorBufferInfo bufferInfos[2] =
+ {
+ vk::makeDescriptorBufferInfo(bufferA, (vk::VkDeviceSize)offsetA, (vk::VkDeviceSize)BUFFER_DATA_SIZE),
+ vk::makeDescriptorBufferInfo(bufferB, (vk::VkDeviceSize)offsetB, (vk::VkDeviceSize)BUFFER_DATA_SIZE),
+ };
+ const vk::VkDescriptorSetAllocateInfo allocInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+ DE_NULL,
+ descriptorPool,
+ 1u,
+ &descriptorSetLayout
+ };
+
+ vk::Move<vk::VkDescriptorSet> descriptorSet = allocateDescriptorSet(vki, device, &allocInfo);
+ vk::DescriptorSetUpdateBuilder builder;
+
+ switch (shaderInterface)
+ {
+ case SHADER_INPUT_SINGLE_DESCRIPTOR:
+ builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &bufferInfos[0]);
+ break;
+
+ case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
+ builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &bufferInfos[0]);
+ builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), descriptorType, &bufferInfos[1]);
+ break;
+
+ case SHADER_INPUT_DESCRIPTOR_ARRAY:
+ builder.writeArray(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, 2u, bufferInfos);
+ break;
+
+ default:
+ DE_FATAL("Impossible");
+ }
+
+ builder.update(vki, device);
+ return descriptorSet;
+}
+
+vk::Move<vk::VkPipelineLayout> BufferRenderInstance::createPipelineLayout (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::VkDescriptorSetLayout descriptorSetLayout)
+{
+ const vk::VkPipelineLayoutCreateInfo createInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
+ DE_NULL,
+ (vk::VkPipelineLayoutCreateFlags)0,
+ 1, // descriptorSetCount
+ &descriptorSetLayout, // pSetLayouts
+ 0u, // pushConstantRangeCount
+ DE_NULL, // pPushConstantRanges
+ };
+
+ return vk::createPipelineLayout(vki, device, &createInfo);
+}
+
+void BufferRenderInstance::logTestPlan (void) const
+{
+ std::ostringstream msg;
+
+ msg << "Rendering 2x2 yellow-green grid.\n"
+ << "Single descriptor set. Descriptor set contains "
+ << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
+ (m_shaderInterface == SHADER_INPUT_MULTIPLE_DESCRIPTORS) ? "two" :
+ (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
+ (const char*)DE_NULL)
+ << " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
+ << "Buffer view(s) have " << ((m_setViewOffset) ? ("non-") : ("")) << "zero offset.\n";
+
+ if (isDynamicDescriptorType(m_descriptorType))
+ {
+ if (m_setDynamicOffset)
+ {
+ msg << "Source buffer(s) are given a dynamic offset at bind time.\n"
+ << "The supplied dynamic offset is " << ((m_dynamicOffsetNonZero) ? ("non-") : ("")) << "zero.\n";
+ }
+ else
+ {
+ msg << "Dynamic offset is not supplied at bind time. Expecting bind to offset 0.\n";
+ }
+ }
+
+ if (m_stageFlags == 0u)
+ {
+ msg << "Descriptors are not accessed in any shader stage.\n";
+ }
+ else
+ {
+ msg << "Descriptors are accessed in {"
+ << (((m_stageFlags & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0) ? (" vertex") : (""))
+ << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0) ? (" tess_control") : (""))
+ << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0) ? (" tess_evaluation") : (""))
+ << (((m_stageFlags & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0) ? (" geometry") : (""))
+ << (((m_stageFlags & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0) ? (" fragment") : (""))
+ << " } stages.\n";
+ }
+
+ m_context.getTestContext().getLog()
+ << tcu::TestLog::Message
+ << msg.str()
+ << tcu::TestLog::EndMessage;
+}
+
+vk::VkPipelineLayout BufferRenderInstance::getPipelineLayout (void) const
+{
+ return *m_pipelineLayout;
+}
+
+void BufferRenderInstance::writeDrawCmdBuffer (vk::VkCommandBuffer cmd) const
+{
+ const bool isUniformBuffer = isUniformDescriptorType(m_descriptorType);
+
+ // \note dynamic offset replaces the view offset, i.e. it is not offset relative to the view offset
+ const deUint32 dynamicOffsets[] =
+ {
+ m_dynamicOffsetA,
+ m_dynamicOffsetB,
+ };
+ const deUint32 numOffsets = (!m_setDynamicOffset) ? (0u) : (getInterfaceNumResources(m_shaderInterface));
+ const deUint32* const dynamicOffsetPtr = (!m_setDynamicOffset) ? (DE_NULL) : (dynamicOffsets);
+
+ // make host writes device-visible
+ const vk::VkAccessFlags inputBit = (isUniformBuffer) ? (vk::VK_ACCESS_UNIFORM_READ_BIT) : (vk::VK_ACCESS_SHADER_READ_BIT);
+ const vk::VkBufferMemoryBarrier memoryBarrierA =
+ {
+ vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
+ DE_NULL,
+ vk::VK_ACCESS_HOST_WRITE_BIT, // outputMask
+ inputBit, // inputMask
+ vk::VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
+ vk::VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex
+ *m_sourceBufferA, // buffer
+ 0u, // offset
+ (vk::VkDeviceSize)m_bufferSizeA, // size
+ };
+ const vk::VkBufferMemoryBarrier memoryBarrierB =
+ {
+ vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
+ DE_NULL,
+ vk::VK_ACCESS_HOST_WRITE_BIT, // outputMask
+ inputBit, // inputMask
+ vk::VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
+ vk::VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex
+ *m_sourceBufferB, // buffer
+ 0u, // offset
+ (vk::VkDeviceSize)m_bufferSizeB, // size
+ };
+ const void* const memoryBarriers[2] =
+ {
+ &memoryBarrierA,
+ &memoryBarrierB,
+ };
+ const deUint32 numMemoryBarriers = getInterfaceNumResources(m_shaderInterface);
+
+ m_vki.cmdBindDescriptorSets(cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, getPipelineLayout(), 0, 1, &m_descriptorSet.get(), numOffsets, dynamicOffsetPtr);
+ m_vki.cmdPipelineBarrier(cmd, 0u, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_FALSE, numMemoryBarriers, memoryBarriers);
+ m_vki.cmdDraw(cmd, 6 * 4, 1, 0, 0); // render four quads (two separate triangles)
+}
+
+tcu::TestStatus BufferRenderInstance::verifyResultImage (const tcu::ConstPixelBufferAccess& result) const
+{
+ const tcu::Vec4 green (0.0f, 1.0f, 0.0f, 1.0f);
+ const tcu::Vec4 yellow (1.0f, 1.0f, 0.0f, 1.0f);
+ tcu::Surface reference (m_targetSize.x(), m_targetSize.y());
+
+ drawQuadrantReferenceResult(reference.getAccess(), yellow, green, green, yellow);
+
+ if (!bilinearCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference.getAccess(), result, tcu::RGBA(1, 1, 1, 1), tcu::COMPARE_LOG_RESULT))
+ return tcu::TestStatus::fail("Image verification failed");
+ else
+ return tcu::TestStatus::pass("Pass");
+}
+
+class ComputeInstanceResultBuffer
+{
+public:
+ enum
+ {
+ DATA_SIZE = sizeof(tcu::Vec4[4])
+ };
+
+ ComputeInstanceResultBuffer (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::Allocator& allocator);
+
+ void readResultContentsTo (tcu::Vec4 (*results)[4]) const;
+
+ inline vk::VkBuffer getBuffer (void) const { return *m_buffer; }
+ inline const void* getResultReadBarrier (void) const { return &m_bufferBarrier; }
+
+private:
+ static vk::Move<vk::VkBuffer> createResultBuffer (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::Allocator& allocator,
+ de::MovePtr<vk::Allocation>* outAllocation);
+
+ static vk::VkBufferMemoryBarrier createResultBufferBarrier (vk::VkBuffer buffer);
+
+ const vk::DeviceInterface& m_vki;
+ const vk::VkDevice m_device;
+
+ de::MovePtr<vk::Allocation> m_bufferMem;
+ const vk::Unique<vk::VkBuffer> m_buffer;
+ const vk::VkBufferMemoryBarrier m_bufferBarrier;
+};
+
+ComputeInstanceResultBuffer::ComputeInstanceResultBuffer (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::Allocator& allocator)
+ : m_vki (vki)
+ , m_device (device)
+ , m_bufferMem (DE_NULL)
+ , m_buffer (createResultBuffer(m_vki, m_device, allocator, &m_bufferMem))
+ , m_bufferBarrier (createResultBufferBarrier(*m_buffer))
+{
+}
+
+void ComputeInstanceResultBuffer::readResultContentsTo (tcu::Vec4 (*results)[4]) const
+{
+ invalidateMappedMemoryRange(m_vki, m_device, m_bufferMem->getMemory(), m_bufferMem->getOffset(), sizeof(*results));
+ deMemcpy(*results, m_bufferMem->getHostPtr(), sizeof(*results));
+}
+
+vk::Move<vk::VkBuffer> ComputeInstanceResultBuffer::createResultBuffer (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::Allocator& allocator,
+ de::MovePtr<vk::Allocation>* outAllocation)
+{
+ const vk::VkBufferCreateInfo createInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
+ DE_NULL,
+ 0u, // flags
+ (vk::VkDeviceSize)DATA_SIZE, // size
+ vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, // usage
+ vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
+ 0u, // queueFamilyCount
+ DE_NULL, // pQueueFamilyIndices
+ };
+ vk::Move<vk::VkBuffer> buffer (vk::createBuffer(vki, device, &createInfo));
+ de::MovePtr<vk::Allocation> allocation (allocateAndBindObjectMemory(vki, device, allocator, *buffer, vk::MemoryRequirement::HostVisible));
+ const float clearValue = -1.0f;
+ void* mapPtr = allocation->getHostPtr();
+
+ for (size_t offset = 0; offset < DATA_SIZE; offset += sizeof(float))
+ deMemcpy(((deUint8*)mapPtr) + offset, &clearValue, sizeof(float));
+
+ flushMappedMemoryRange(vki, device, allocation->getMemory(), allocation->getOffset(), (vk::VkDeviceSize)DATA_SIZE);
+
+ *outAllocation = allocation;
+ return buffer;
+}
+
+vk::VkBufferMemoryBarrier ComputeInstanceResultBuffer::createResultBufferBarrier (vk::VkBuffer buffer)
+{
+ const vk::VkBufferMemoryBarrier bufferBarrier =
+ {
+ vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
+ DE_NULL,
+ vk::VK_ACCESS_SHADER_WRITE_BIT, // outputMask
+ vk::VK_ACCESS_HOST_READ_BIT, // inputMask
+ vk::VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
+ vk::VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex
+ buffer, // buffer
+ (vk::VkDeviceSize)0u, // offset
+ DATA_SIZE, // size
+ };
+ return bufferBarrier;
+}
+
+class ComputePipeline
+{
+public:
+ ComputePipeline (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ const vk::BinaryCollection& programCollection,
+ deUint32 numDescriptorSets,
+ const vk::VkDescriptorSetLayout* descriptorSetLayouts);
+
+ inline vk::VkPipeline getPipeline (void) const { return *m_pipeline; };
+ inline vk::VkPipelineLayout getPipelineLayout (void) const { return *m_pipelineLayout; };
+
+private:
+ static vk::Move<vk::VkPipelineLayout> createPipelineLayout (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ deUint32 numDescriptorSets,
+ const vk::VkDescriptorSetLayout* descriptorSetLayouts);
+
+ static vk::Move<vk::VkPipeline> createPipeline (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ const vk::BinaryCollection& programCollection,
+ vk::VkPipelineLayout layout);
+
+ const vk::Unique<vk::VkPipelineLayout> m_pipelineLayout;
+ const vk::Unique<vk::VkPipeline> m_pipeline;
+};
+
+ComputePipeline::ComputePipeline (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ const vk::BinaryCollection& programCollection,
+ deUint32 numDescriptorSets,
+ const vk::VkDescriptorSetLayout* descriptorSetLayouts)
+ : m_pipelineLayout (createPipelineLayout(vki, device, numDescriptorSets, descriptorSetLayouts))
+ , m_pipeline (createPipeline(vki, device, programCollection, *m_pipelineLayout))
+{
+}
+
+vk::Move<vk::VkPipelineLayout> ComputePipeline::createPipelineLayout (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ deUint32 numDescriptorSets,
+ const vk::VkDescriptorSetLayout* descriptorSetLayouts)
+{
+ const vk::VkPipelineLayoutCreateInfo createInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
+ DE_NULL,
+ (vk::VkPipelineLayoutCreateFlags)0,
+ numDescriptorSets, // descriptorSetCount
+ descriptorSetLayouts, // pSetLayouts
+ 0u, // pushConstantRangeCount
+ DE_NULL, // pPushConstantRanges
+ };
+ return vk::createPipelineLayout(vki, device, &createInfo);
+}
+
+vk::Move<vk::VkPipeline> ComputePipeline::createPipeline (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ const vk::BinaryCollection& programCollection,
+ vk::VkPipelineLayout layout)
+{
+ const vk::Unique<vk::VkShaderModule> computeModule (vk::createShaderModule(vki, device, programCollection.get("compute"), (vk::VkShaderModuleCreateFlags)0u));
+ const vk::VkPipelineShaderStageCreateInfo cs =
+ {
+ vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ DE_NULL,
+ (vk::VkPipelineShaderStageCreateFlags)0,
+ vk::VK_SHADER_STAGE_COMPUTE_BIT, // stage
+ *computeModule, // shader
+ "main",
+ DE_NULL, // pSpecializationInfo
+ };
+ const vk::VkComputePipelineCreateInfo createInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
+ DE_NULL,
+ 0u, // flags
+ cs, // cs
+ layout, // layout
+ (vk::VkPipeline)0, // basePipelineHandle
+ 0u, // basePipelineIndex
+ };
+ return createComputePipeline(vki, device, (vk::VkPipelineCache)0u, &createInfo);
+}
+
+class ComputeCommand
+{
+public:
+ ComputeCommand (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::VkPipeline pipeline,
+ vk::VkPipelineLayout pipelineLayout,
+ const tcu::UVec3& numWorkGroups,
+ int numDescriptorSets,
+ const vk::VkDescriptorSet* descriptorSets,
+ int numDynamicOffsets,
+ const deUint32* dynamicOffsets,
+ int numPreBarriers,
+ const void* const* preBarriers,
+ int numPostBarriers,
+ const void* const* postBarriers);
+
+ void submitAndWait (deUint32 queueFamilyIndex, vk::VkQueue queue) const;
+
+private:
+ const vk::DeviceInterface& m_vki;
+ const vk::VkDevice m_device;
+ const vk::VkPipeline m_pipeline;
+ const vk::VkPipelineLayout m_pipelineLayout;
+ const tcu::UVec3& m_numWorkGroups;
+ const int m_numDescriptorSets;
+ const vk::VkDescriptorSet* const m_descriptorSets;
+ const int m_numDynamicOffsets;
+ const deUint32* const m_dynamicOffsets;
+ const int m_numPreBarriers;
+ const void* const* const m_preBarriers;
+ const int m_numPostBarriers;
+ const void* const* const m_postBarriers;
+};
+
+ComputeCommand::ComputeCommand (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::VkPipeline pipeline,
+ vk::VkPipelineLayout pipelineLayout,
+ const tcu::UVec3& numWorkGroups,
+ int numDescriptorSets,
+ const vk::VkDescriptorSet* descriptorSets,
+ int numDynamicOffsets,
+ const deUint32* dynamicOffsets,
+ int numPreBarriers,
+ const void* const* preBarriers,
+ int numPostBarriers,
+ const void* const* postBarriers)
+ : m_vki (vki)
+ , m_device (device)
+ , m_pipeline (pipeline)
+ , m_pipelineLayout (pipelineLayout)
+ , m_numWorkGroups (numWorkGroups)
+ , m_numDescriptorSets (numDescriptorSets)
+ , m_descriptorSets (descriptorSets)
+ , m_numDynamicOffsets (numDynamicOffsets)
+ , m_dynamicOffsets (dynamicOffsets)
+ , m_numPreBarriers (numPreBarriers)
+ , m_preBarriers (preBarriers)
+ , m_numPostBarriers (numPostBarriers)
+ , m_postBarriers (postBarriers)
+{
+}
+
+void ComputeCommand::submitAndWait (deUint32 queueFamilyIndex, vk::VkQueue queue) const
+{
+ const vk::VkCommandPoolCreateInfo cmdPoolCreateInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
+ DE_NULL,
+ queueFamilyIndex, // queueFamilyIndex
+ vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // flags
+ };
+ const vk::Unique<vk::VkCommandPool> cmdPool (vk::createCommandPool(m_vki, m_device, &cmdPoolCreateInfo));
+
+ const vk::VkFenceCreateInfo fenceCreateInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
+ DE_NULL,
+ 0u, // flags
+ };
+
+ const vk::VkCommandBufferAllocateInfo cmdBufCreateInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
+ DE_NULL,
+ *cmdPool, // cmdPool
+ vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level
+ 1u, // count
+ };
+ const vk::VkCommandBufferBeginInfo cmdBufBeginInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+ DE_NULL,
+ vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // flags
+ (vk::VkRenderPass)0u, // renderPass
+ 0u, // subpass
+ (vk::VkFramebuffer)0u, // framebuffer
+ vk::VK_FALSE, // occlusionQueryEnable
+ (vk::VkQueryControlFlags)0,
+ (vk::VkQueryPipelineStatisticFlags)0,
+ };
+
+ const vk::Unique<vk::VkFence> cmdCompleteFence (vk::createFence(m_vki, m_device, &fenceCreateInfo));
+ const vk::Unique<vk::VkCommandBuffer> cmd (vk::allocateCommandBuffer(m_vki, m_device, &cmdBufCreateInfo));
+ const deUint64 infiniteTimeout = ~(deUint64)0u;
+
+ VK_CHECK(m_vki.beginCommandBuffer(*cmd, &cmdBufBeginInfo));
+
+ m_vki.cmdBindPipeline(*cmd, vk::VK_PIPELINE_BIND_POINT_COMPUTE, m_pipeline);
+ m_vki.cmdBindDescriptorSets(*cmd, vk::VK_PIPELINE_BIND_POINT_COMPUTE, m_pipelineLayout, 0, m_numDescriptorSets, m_descriptorSets, m_numDynamicOffsets, m_dynamicOffsets);
+
+ if (m_numPreBarriers)
+ m_vki.cmdPipelineBarrier(*cmd, 0u, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::VK_FALSE, m_numPreBarriers, m_preBarriers);
+
+ m_vki.cmdDispatch(*cmd, m_numWorkGroups.x(), m_numWorkGroups.y(), m_numWorkGroups.z());
+ m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_FALSE, m_numPostBarriers, m_postBarriers);
+ VK_CHECK(m_vki.endCommandBuffer(*cmd));
+
+ // run
+ {
+ const vk::VkSubmitInfo submitInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
+ DE_NULL,
+ 0u,
+ (const vk::VkSemaphore*)0,
+ 1u,
+ &cmd.get(),
+ 0u,
+ (const vk::VkSemaphore*)0,
+ };
+ VK_CHECK(m_vki.queueSubmit(queue, 1, &submitInfo, *cmdCompleteFence));
+ }
+ VK_CHECK(m_vki.waitForFences(m_device, 1, &cmdCompleteFence.get(), 0u, infiniteTimeout)); // \note: timeout is failure
+}
+
+class BufferComputeInstance : public vkt::TestInstance
+{
+public:
+ BufferComputeInstance (Context& context,
+ vk::VkDescriptorType descriptorType,
+ ShaderInputInterface shaderInterface,
+ bool viewOffset,
+ bool dynamicOffset,
+ bool dynamicOffsetNonZero);
+
+private:
+ vk::Move<vk::VkBuffer> createColorDataBuffer (deUint32 offset, deUint32 bufferSize, const tcu::Vec4& value1, const tcu::Vec4& value2, de::MovePtr<vk::Allocation>* outAllocation);
+ vk::Move<vk::VkBufferView> createBufferView (vk::VkBuffer buffer, deUint32 offset) const;
+ vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout (void) const;
+ vk::Move<vk::VkDescriptorPool> createDescriptorPool (void) const;
+ vk::Move<vk::VkDescriptorSet> createDescriptorSet (vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout, vk::VkBuffer viewA, deUint32 offsetA, vk::VkBuffer viewB, deUint32 offsetB, vk::VkBuffer resBuf) const;
+
+ tcu::TestStatus iterate (void);
+ void logTestPlan (void) const;
+ tcu::TestStatus testResourceAccess (void);
+
+ enum
+ {
+ STATIC_OFFSET_VALUE_A = 256,
+ DYNAMIC_OFFSET_VALUE_A = 512,
+ STATIC_OFFSET_VALUE_B = 1024,
+ DYNAMIC_OFFSET_VALUE_B = 768,
+ };
+
+ const vk::VkDescriptorType m_descriptorType;
+ const ShaderInputInterface m_shaderInterface;
+ const bool m_setViewOffset;
+ const bool m_setDynamicOffset;
+ const bool m_dynamicOffsetNonZero;
+
+ const vk::DeviceInterface& m_vki;
+ const vk::VkDevice m_device;
+ const vk::VkQueue m_queue;
+ const deUint32 m_queueFamilyIndex;
+ vk::Allocator& m_allocator;
+
+ const ComputeInstanceResultBuffer m_result;
+};
+
+BufferComputeInstance::BufferComputeInstance (Context& context,
+ vk::VkDescriptorType descriptorType,
+ ShaderInputInterface shaderInterface,
+ bool viewOffset,
+ bool dynamicOffset,
+ bool dynamicOffsetNonZero)
+ : vkt::TestInstance (context)
+ , m_descriptorType (descriptorType)
+ , m_shaderInterface (shaderInterface)
+ , m_setViewOffset (viewOffset)
+ , m_setDynamicOffset (dynamicOffset)
+ , m_dynamicOffsetNonZero (dynamicOffsetNonZero)
+ , m_vki (context.getDeviceInterface())
+ , m_device (context.getDevice())
+ , m_queue (context.getUniversalQueue())
+ , m_queueFamilyIndex (context.getUniversalQueueFamilyIndex())
+ , m_allocator (context.getDefaultAllocator())
+ , m_result (m_vki, m_device, m_allocator)
+{
+ if (m_dynamicOffsetNonZero)
+ DE_ASSERT(m_setDynamicOffset);
+}
+
+vk::Move<vk::VkBuffer> BufferComputeInstance::createColorDataBuffer (deUint32 offset, deUint32 bufferSize, const tcu::Vec4& value1, const tcu::Vec4& value2, de::MovePtr<vk::Allocation>* outAllocation)
+{
+ DE_ASSERT(offset + sizeof(tcu::Vec4[2]) <= bufferSize);
+
+ const bool isUniformBuffer = isUniformDescriptorType(m_descriptorType);
+ const vk::VkBufferUsageFlags usageFlags = (isUniformBuffer) ? (vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) : (vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
+ const vk::VkBufferCreateInfo createInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
+ DE_NULL,
+ 0u, // flags
+ (vk::VkDeviceSize)bufferSize, // size
+ usageFlags, // usage
+ vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
+ 0u, // queueFamilyCount
+ DE_NULL, // pQueueFamilyIndices
+ };
+ vk::Move<vk::VkBuffer> buffer (vk::createBuffer(m_vki, m_device, &createInfo));
+ de::MovePtr<vk::Allocation> allocation (allocateAndBindObjectMemory(m_vki, m_device, m_allocator, *buffer, vk::MemoryRequirement::HostVisible));
+ void* mapPtr = allocation->getHostPtr();
+
+ if (offset)
+ deMemset(mapPtr, 0x5A, (size_t)offset);
+ deMemcpy((deUint8*)mapPtr + offset, value1.getPtr(), sizeof(tcu::Vec4));
+ deMemcpy((deUint8*)mapPtr + offset + sizeof(tcu::Vec4), value2.getPtr(), sizeof(tcu::Vec4));
+ deMemset((deUint8*)mapPtr + offset + 2 * sizeof(tcu::Vec4), 0x5A, (size_t)bufferSize - (size_t)offset - 2 * sizeof(tcu::Vec4));
+
+ flushMappedMemoryRange(m_vki, m_device, allocation->getMemory(), allocation->getOffset(), bufferSize);
+
+ *outAllocation = allocation;
+ return buffer;
+}
+
+vk::Move<vk::VkDescriptorSetLayout> BufferComputeInstance::createDescriptorSetLayout (void) const
+{
+ vk::DescriptorSetLayoutBuilder builder;
+
+ builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT);
+
+ switch (m_shaderInterface)
+ {
+ case SHADER_INPUT_SINGLE_DESCRIPTOR:
+ builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
+ break;
+
+ case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
+ builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
+ builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
+ break;
+
+ case SHADER_INPUT_DESCRIPTOR_ARRAY:
+ builder.addArrayBinding(m_descriptorType, 2u, vk::VK_SHADER_STAGE_COMPUTE_BIT);
+ break;
+
+ default:
+ DE_FATAL("Impossible");
+ };
+
+ return builder.build(m_vki, m_device);
+}
+
+vk::Move<vk::VkDescriptorPool> BufferComputeInstance::createDescriptorPool (void) const
+{
+ return vk::DescriptorPoolBuilder()
+ .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
+ .addType(m_descriptorType, getInterfaceNumResources(m_shaderInterface))
+ .build(m_vki, m_device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
+}
+
+vk::Move<vk::VkDescriptorSet> BufferComputeInstance::createDescriptorSet (vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout, vk::VkBuffer viewA, deUint32 offsetA, vk::VkBuffer viewB, deUint32 offsetB, vk::VkBuffer resBuf) const
+{
+ const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(resBuf, 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
+ const vk::VkDescriptorBufferInfo bufferInfos[2] =
+ {
+ vk::makeDescriptorBufferInfo(viewA, (vk::VkDeviceSize)offsetA, (vk::VkDeviceSize)sizeof(tcu::Vec4[2])),
+ vk::makeDescriptorBufferInfo(viewB, (vk::VkDeviceSize)offsetB, (vk::VkDeviceSize)sizeof(tcu::Vec4[2])),
+ };
+ const vk::VkDescriptorSetAllocateInfo allocInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+ DE_NULL,
+ pool,
+ 1u,
+ &layout
+ };
+
+ vk::Move<vk::VkDescriptorSet> descriptorSet = allocateDescriptorSet(m_vki, m_device, &allocInfo);
+ vk::DescriptorSetUpdateBuilder builder;
+
+ // result
+ builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
+
+ // buffers
+ switch (m_shaderInterface)
+ {
+ case SHADER_INPUT_SINGLE_DESCRIPTOR:
+ builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, &bufferInfos[0]);
+ break;
+
+ case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
+ builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, &bufferInfos[0]);
+ builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), m_descriptorType, &bufferInfos[1]);
+ break;
+
+ case SHADER_INPUT_DESCRIPTOR_ARRAY:
+ builder.writeArray(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, 2u, bufferInfos);
+ break;
+
+ default:
+ DE_FATAL("Impossible");
+ }
+
+ builder.update(m_vki, m_device);
+ return descriptorSet;
+}
+
+tcu::TestStatus BufferComputeInstance::iterate (void)
+{
+ logTestPlan();
+ return testResourceAccess();
+}
+
+void BufferComputeInstance::logTestPlan (void) const
+{
+ std::ostringstream msg;
+
+ msg << "Accessing resource in a compute program.\n"
+ << "Single descriptor set. Descriptor set contains "
+ << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
+ (m_shaderInterface == SHADER_INPUT_MULTIPLE_DESCRIPTORS) ? "two" :
+ (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
+ (const char*)DE_NULL)
+ << " source descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType)
+ << " and one destination VK_DESCRIPTOR_TYPE_STORAGE_BUFFER to store results to.\n"
+ << "Source descriptor buffer view(s) have " << ((m_setViewOffset) ? ("non-") : ("")) << "zero offset.\n";
+
+ if (isDynamicDescriptorType(m_descriptorType))
+ {
+ if (m_setDynamicOffset)
+ {
+ msg << "Source buffer(s) are given a dynamic offset at bind time.\n"
+ << "The supplied dynamic offset is " << ((m_dynamicOffsetNonZero) ? ("non-") : ("")) << "zero.\n";
+ }
+ else
+ {
+ msg << "Dynamic offset is not supplied at bind time. Expecting bind to offset 0.\n";
+ }
+ }
+
+ msg << "Destination buffer is pre-initialized to -1.\n";
+
+ m_context.getTestContext().getLog()
+ << tcu::TestLog::Message
+ << msg.str()
+ << tcu::TestLog::EndMessage;
+}
+
+tcu::TestStatus BufferComputeInstance::testResourceAccess (void)
+{
+ enum
+ {
+ ADDRESSABLE_SIZE = 256, // allocate a lot more than required
+ };
+
+ const bool isDynamicCase = isDynamicDescriptorType(m_descriptorType);
+ const bool isUniformBuffer = isUniformDescriptorType(m_descriptorType);
+ const deUint32 bindTimeOffsets[] =
+ {
+ (m_dynamicOffsetNonZero) ? ((deUint32)DYNAMIC_OFFSET_VALUE_A) : (0u),
+ (m_dynamicOffsetNonZero) ? ((deUint32)DYNAMIC_OFFSET_VALUE_B) : (0u),
+ };
+
+ const tcu::Vec4 colorA1 = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
+ const tcu::Vec4 colorA2 = tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f);
+ const tcu::Vec4 colorB1 = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
+ const tcu::Vec4 colorB2 = tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f);
+
+ const deUint32 dataOffsetA = (isDynamicCase) ? (bindTimeOffsets[0]) : (m_setViewOffset) ? ((deUint32)STATIC_OFFSET_VALUE_A) : (0u);
+ const deUint32 dataOffsetB = (isDynamicCase) ? (bindTimeOffsets[1]) : (m_setViewOffset) ? ((deUint32)STATIC_OFFSET_VALUE_B) : (0u);
+ const deUint32 viewOffsetA = (m_setViewOffset) ? ((deUint32)STATIC_OFFSET_VALUE_A) : (0u);
+ const deUint32 viewOffsetB = (m_setViewOffset) ? ((deUint32)STATIC_OFFSET_VALUE_B) : (0u);
+ const deUint32 bufferSizeA = dataOffsetA + ADDRESSABLE_SIZE;
+ const deUint32 bufferSizeB = dataOffsetB + ADDRESSABLE_SIZE;
+
+ de::MovePtr<vk::Allocation> bufferMemA;
+ const vk::Unique<vk::VkBuffer> bufferA (createColorDataBuffer(dataOffsetA, bufferSizeA, colorA1, colorA2, &bufferMemA));
+
+ de::MovePtr<vk::Allocation> bufferMemB;
+ const vk::Unique<vk::VkBuffer> bufferB ((getInterfaceNumResources(m_shaderInterface) == 1u)
+ ? (vk::Move<vk::VkBuffer>())
+ : (createColorDataBuffer(dataOffsetB, bufferSizeB, colorB1, colorB2, &bufferMemB)));
+
+ const vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout (createDescriptorSetLayout());
+ const vk::Unique<vk::VkDescriptorPool> descriptorPool (createDescriptorPool());
+ const vk::Unique<vk::VkDescriptorSet> descriptorSet (createDescriptorSet(*descriptorPool, *descriptorSetLayout, *bufferA, viewOffsetA, *bufferB, viewOffsetB, m_result.getBuffer()));
+ const ComputePipeline pipeline (m_vki, m_device, m_context.getBinaryCollection(), 1, &descriptorSetLayout.get());
+
+ const vk::VkAccessFlags inputBit = (isUniformBuffer) ? (vk::VK_ACCESS_UNIFORM_READ_BIT) : (vk::VK_ACCESS_SHADER_READ_BIT);
+ const vk::VkBufferMemoryBarrier bufferBarrierA =
+ {
+ vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
+ DE_NULL,
+ vk::VK_ACCESS_HOST_WRITE_BIT, // outputMask
+ inputBit, // inputMask
+ vk::VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
+ vk::VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex
+ *bufferA, // buffer
+ (vk::VkDeviceSize)0u, // offset
+ (vk::VkDeviceSize)bufferSizeA, // size
+ };
+ const vk::VkBufferMemoryBarrier bufferBarrierB =
+ {
+ vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
+ DE_NULL,
+ vk::VK_ACCESS_HOST_WRITE_BIT, // outputMask
+ inputBit, // inputMask
+ vk::VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
+ vk::VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex
+ *bufferB, // buffer
+ (vk::VkDeviceSize)0u, // offset
+ (vk::VkDeviceSize)bufferSizeB, // size
+ };
+
+ const deUint32 numSrcBuffers = getInterfaceNumResources(m_shaderInterface);
+
+ const vk::VkDescriptorSet descriptorSets[] = { *descriptorSet };
+ const int numDescriptorSets = DE_LENGTH_OF_ARRAY(descriptorSets);
+ const deUint32* const dynamicOffsets = (m_setDynamicOffset) ? (bindTimeOffsets) : (DE_NULL);
+ const deUint32 numDynamicOffsets = (m_setDynamicOffset) ? (numSrcBuffers) : (0);
+ const void* const preBarriers[] = { &bufferBarrierA, &bufferBarrierB };
+ const int numPreBarriers = numSrcBuffers;
+ const void* const postBarriers[] = { m_result.getResultReadBarrier() };
+ const int numPostBarriers = DE_LENGTH_OF_ARRAY(postBarriers);
+
+ const ComputeCommand compute (m_vki,
+ m_device,
+ pipeline.getPipeline(),
+ pipeline.getPipelineLayout(),
+ tcu::UVec3(4, 1, 1),
+ numDescriptorSets, descriptorSets,
+ numDynamicOffsets, dynamicOffsets,
+ numPreBarriers, preBarriers,
+ numPostBarriers, postBarriers);
+
+ const tcu::Vec4 refQuadrantValue14 = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? (colorA2) :
+ (m_shaderInterface == SHADER_INPUT_MULTIPLE_DESCRIPTORS) ? (colorB2) :
+ (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? (colorB2) :
+ (tcu::Vec4(-2.0f));
+ const tcu::Vec4 refQuadrantValue23 = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? (colorA1) :
+ (m_shaderInterface == SHADER_INPUT_MULTIPLE_DESCRIPTORS) ? (colorA1) :
+ (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? (colorA1) :
+ (tcu::Vec4(-2.0f));
+ const tcu::Vec4 references[4] =
+ {
+ refQuadrantValue14,
+ refQuadrantValue23,
+ refQuadrantValue23,
+ refQuadrantValue14,
+ };
+ tcu::Vec4 results[4];
+
+ compute.submitAndWait(m_queueFamilyIndex, m_queue);
+ m_result.readResultContentsTo(&results);
+
+ // verify
+ if (results[0] == references[0] &&
+ results[1] == references[1] &&
+ results[2] == references[2] &&
+ results[3] == references[3])
+ {
+ return tcu::TestStatus::pass("Pass");
+ }
+ else if (results[0] == tcu::Vec4(-1.0f) &&
+ results[1] == tcu::Vec4(-1.0f) &&
+ results[2] == tcu::Vec4(-1.0f) &&
+ results[3] == tcu::Vec4(-1.0f))
+ {
+ m_context.getTestContext().getLog()
+ << tcu::TestLog::Message
+ << "Result buffer was not written to."
+ << tcu::TestLog::EndMessage;
+ return tcu::TestStatus::fail("Result buffer was not written to");
+ }
+ else
+ {
+ m_context.getTestContext().getLog()
+ << tcu::TestLog::Message
+ << "Error expected ["
+ << references[0] << ", "
+ << references[1] << ", "
+ << references[2] << ", "
+ << references[3] << "], got ["
+ << results[0] << ", "
+ << results[1] << ", "
+ << results[2] << ", "
+ << results[3] << "]"
+ << tcu::TestLog::EndMessage;
+ return tcu::TestStatus::fail("Invalid result values");
+ }
+}
+
+class QuadrantRendederCase : public vkt::TestCase
+{
+public:
+ QuadrantRendederCase (tcu::TestContext& testCtx,
+ const char* name,
+ const char* description,
+ glu::GLSLVersion glslVersion,
+ vk::VkShaderStageFlags exitingStages,
+ vk::VkShaderStageFlags activeStages);
+private:
+ virtual std::string genExtensionDeclarations (vk::VkShaderStageFlagBits stage) const = 0;
+ virtual std::string genResourceDeclarations (vk::VkShaderStageFlagBits stage, int numUsedBindings) const = 0;
+ virtual std::string genResourceAccessSource (vk::VkShaderStageFlagBits stage) const = 0;
+ virtual std::string genNoAccessSource (void) const = 0;
+
+ std::string genVertexSource (void) const;
+ std::string genTessCtrlSource (void) const;
+ std::string genTessEvalSource (void) const;
+ std::string genGeometrySource (void) const;
+ std::string genFragmentSource (void) const;
+ std::string genComputeSource (void) const;
+
+ void initPrograms (vk::SourceCollections& programCollection) const;
+
+protected:
+ const glu::GLSLVersion m_glslVersion;
+ const vk::VkShaderStageFlags m_exitingStages;
+ const vk::VkShaderStageFlags m_activeStages;
+};
+
+QuadrantRendederCase::QuadrantRendederCase (tcu::TestContext& testCtx,
+ const char* name,
+ const char* description,
+ glu::GLSLVersion glslVersion,
+ vk::VkShaderStageFlags exitingStages,
+ vk::VkShaderStageFlags activeStages)
+ : vkt::TestCase (testCtx, name, description)
+ , m_glslVersion (glslVersion)
+ , m_exitingStages (exitingStages)
+ , m_activeStages (activeStages)
+{
+ DE_ASSERT((m_exitingStages & m_activeStages) == m_activeStages);
+}
+
+std::string QuadrantRendederCase::genVertexSource (void) const
+{
+ const char* const nextStageName = ((m_exitingStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0u) ? ("tsc")
+ : ((m_exitingStages & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0u) ? ("geo")
+ : ((m_exitingStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0u) ? ("frag")
+ : (DE_NULL);
+ const char* const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
+ std::ostringstream buf;
+
+ if ((m_activeStages & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0u)
+ {
+ // active vertex shader
+ buf << versionDecl << "\n"
+ << genExtensionDeclarations(vk::VK_SHADER_STAGE_VERTEX_BIT)
+ << genResourceDeclarations(vk::VK_SHADER_STAGE_VERTEX_BIT, 0)
+ << "layout(location = 0) out highp vec4 " << nextStageName << "_color;\n"
+ << "layout(location = 1) flat out highp int " << nextStageName << "_quadrant_id;\n"
+ << "void main (void)\n"
+ << "{\n"
+ << " highp vec4 result_position;\n"
+ << " highp int quadrant_id;\n"
+ << s_quadrantGenVertexPosSource
+ << " gl_Position = result_position;\n"
+ << " " << nextStageName << "_quadrant_id = quadrant_id;\n"
+ << "\n"
+ << " highp vec4 result_color;\n"
+ << genResourceAccessSource(vk::VK_SHADER_STAGE_VERTEX_BIT)
+ << " " << nextStageName << "_color = result_color;\n"
+ << "}\n";
+ }
+ else
+ {
+ // do nothing
+ buf << versionDecl << "\n"
+ << genExtensionDeclarations(vk::VK_SHADER_STAGE_VERTEX_BIT)
+ << "layout(location = 1) flat out highp int " << nextStageName << "_quadrant_id;\n"
+ << "void main (void)\n"
+ << "{\n"
+ << " highp vec4 result_position;\n"
+ << " highp int quadrant_id;\n"
+ << s_quadrantGenVertexPosSource
+ << " gl_Position = result_position;\n"
+ << " " << nextStageName << "_quadrant_id = quadrant_id;\n"
+ << "}\n";
+ }
+
+ return buf.str();
+}
+
+std::string QuadrantRendederCase::genTessCtrlSource (void) const
+{
+ const char* const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
+ const bool extRequired = glu::glslVersionIsES(m_glslVersion) && m_glslVersion <= glu::GLSL_VERSION_310_ES;
+ const char* const tessExtDecl = extRequired ? "#extension GL_EXT_tessellation_shader : require\n" : "";
+ std::ostringstream buf;
+
+ if ((m_activeStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0u)
+ {
+ // contributing not implemented
+ DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
+
+ // active tc shader
+ buf << versionDecl << "\n"
+ << tessExtDecl
+ << genExtensionDeclarations(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
+ << "layout(vertices=3) out;\n"
+ << genResourceDeclarations(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, 0)
+ << "layout(location = 1) flat in highp int tsc_quadrant_id[];\n"
+ << "layout(location = 0) out highp vec4 tes_color[];\n"
+ << "void main (void)\n"
+ << "{\n"
+ << " highp vec4 result_color;\n"
+ << " highp int quadrant_id = tsc_quadrant_id[gl_InvocationID];\n"
+ << genResourceAccessSource(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
+ << "\n"
+ << " tes_color[gl_InvocationID] = result_color;\n"
+ << "\n"
+ << " // no dynamic input block indexing\n"
+ << " highp vec4 position;\n"
+ << " if (gl_InvocationID == 0)\n"
+ << " position = gl_in[0].gl_Position;\n"
+ << " else if (gl_InvocationID == 1)\n"
+ << " position = gl_in[1].gl_Position;\n"
+ << " else\n"
+ << " position = gl_in[2].gl_Position;\n"
+ << " gl_out[gl_InvocationID].gl_Position = position;\n"
+ << " gl_TessLevelInner[0] = 2.8;\n"
+ << " gl_TessLevelInner[1] = 2.8;\n"
+ << " gl_TessLevelOuter[0] = 2.8;\n"
+ << " gl_TessLevelOuter[1] = 2.8;\n"
+ << " gl_TessLevelOuter[2] = 2.8;\n"
+ << " gl_TessLevelOuter[3] = 2.8;\n"
+ << "}\n";
+ }
+ else if ((m_activeStages & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0u)
+ {
+ // active te shader, tc passthru
+ buf << versionDecl << "\n"
+ << tessExtDecl
+ << "layout(vertices=3) out;\n"
+ << "layout(location = 1) flat in highp int tsc_quadrant_id[];\n"
+ << "layout(location = 1) flat out highp int tes_quadrant_id[];\n"
+ << "void main (void)\n"
+ << "{\n"
+ << " tes_quadrant_id[gl_InvocationID] = tsc_quadrant_id[0];\n"
+ << "\n"
+ << " // no dynamic input block indexing\n"
+ << " highp vec4 position;\n"
+ << " if (gl_InvocationID == 0)\n"
+ << " position = gl_in[0].gl_Position;\n"
+ << " else if (gl_InvocationID == 1)\n"
+ << " position = gl_in[1].gl_Position;\n"
+ << " else\n"
+ << " position = gl_in[2].gl_Position;\n"
+ << " gl_out[gl_InvocationID].gl_Position = position;\n"
+ << " gl_TessLevelInner[0] = 2.8;\n"
+ << " gl_TessLevelInner[1] = 2.8;\n"
+ << " gl_TessLevelOuter[0] = 2.8;\n"
+ << " gl_TessLevelOuter[1] = 2.8;\n"
+ << " gl_TessLevelOuter[2] = 2.8;\n"
+ << " gl_TessLevelOuter[3] = 2.8;\n"
+ << "}\n";
+ }
+ else
+ {
+ // passthrough not implemented
+ DE_FATAL("not implemented");
+ }
+
+ return buf.str();
+}
+
+std::string QuadrantRendederCase::genTessEvalSource (void) const
+{
+ const char* const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
+ const bool extRequired = glu::glslVersionIsES(m_glslVersion) && m_glslVersion <= glu::GLSL_VERSION_310_ES;
+ const char* const tessExtDecl = extRequired ? "#extension GL_EXT_tessellation_shader : require\n" : "";
+ std::ostringstream buf;
+
+ if ((m_activeStages & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0u)
+ {
+ // contributing not implemented
+ DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT);
+
+ // active te shader
+ buf << versionDecl << "\n"
+ << tessExtDecl
+ << genExtensionDeclarations(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
+ << "layout(triangles) in;\n"
+ << genResourceDeclarations(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, 0)
+ << "layout(location = 1) flat in highp int tes_quadrant_id[];\n"
+ << "layout(location = 0) out highp vec4 frag_color;\n"
+ << "void main (void)\n"
+ << "{\n"
+ << " highp vec4 result_color;\n"
+ << " highp int quadrant_id = tes_quadrant_id[0];\n"
+ << genResourceAccessSource(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
+ << "\n"
+ << " frag_color = result_color;\n"
+ << " gl_Position = gl_TessCoord.x * gl_in[0].gl_Position + gl_TessCoord.y * gl_in[1].gl_Position + gl_TessCoord.z * gl_in[2].gl_Position;\n"
+ << "}\n";
+ }
+ else if ((m_activeStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0u)
+ {
+ // contributing not implemented
+ DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
+
+ // active tc shader, te is passthru
+ buf << versionDecl << "\n"
+ << tessExtDecl
+ << "layout(triangles) in;\n"
+ << "layout(location = 0) in highp vec4 tes_color[];\n"
+ << "layout(location = 0) out highp vec4 frag_color;\n"
+ << "void main (void)\n"
+ << "{\n"
+ << " frag_color = tes_color[0];\n"
+ << " gl_Position = gl_TessCoord.x * gl_in[0].gl_Position + gl_TessCoord.y * gl_in[1].gl_Position + gl_TessCoord.z * gl_in[2].gl_Position;\n"
+ << "}\n";
+ }
+ else
+ {
+ // passthrough not implemented
+ DE_FATAL("not implemented");
+ }
+
+ return buf.str();
+}
+
+std::string QuadrantRendederCase::genGeometrySource (void) const
+{
+ const char* const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
+ const bool extRequired = glu::glslVersionIsES(m_glslVersion) && m_glslVersion <= glu::GLSL_VERSION_310_ES;
+ const char* const geomExtDecl = extRequired ? "#extension GL_EXT_geometry_shader : require\n" : "";
+ std::ostringstream buf;
+
+ if ((m_activeStages & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0u)
+ {
+ // contributing not implemented
+ DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_GEOMETRY_BIT);
+
+ // active geometry shader
+ buf << versionDecl << "\n"
+ << geomExtDecl
+ << genExtensionDeclarations(vk::VK_SHADER_STAGE_GEOMETRY_BIT)
+ << "layout(triangles) in;\n"
+ << "layout(triangle_strip, max_vertices=4) out;\n"
+ << genResourceDeclarations(vk::VK_SHADER_STAGE_GEOMETRY_BIT, 0)
+ << "layout(location = 1) flat in highp int geo_quadrant_id[];\n"
+ << "layout(location = 0) out highp vec4 frag_color;\n"
+ << "void main (void)\n"
+ << "{\n"
+ << " highp int quadrant_id;\n"
+ << " highp vec4 result_color;\n"
+ << "\n"
+ << " quadrant_id = geo_quadrant_id[0];\n"
+ << genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY_BIT)
+ << " frag_color = result_color;\n"
+ << " gl_Position = gl_in[0].gl_Position;\n"
+ << " EmitVertex();\n"
+ << "\n"
+ << " quadrant_id = geo_quadrant_id[1];\n"
+ << genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY_BIT)
+ << " frag_color = result_color;\n"
+ << " gl_Position = gl_in[1].gl_Position;\n"
+ << " EmitVertex();\n"
+ << "\n"
+ << " quadrant_id = geo_quadrant_id[2];\n"
+ << genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY_BIT)
+ << " frag_color = result_color;\n"
+ << " gl_Position = gl_in[0].gl_Position * 0.5 + gl_in[2].gl_Position * 0.5;\n"
+ << " EmitVertex();\n"
+ << "\n"
+ << " quadrant_id = geo_quadrant_id[0];\n"
+ << genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY_BIT)
+ << " frag_color = result_color;\n"
+ << " gl_Position = gl_in[2].gl_Position;\n"
+ << " EmitVertex();\n"
+ << "}\n";
+ }
+ else
+ {
+ // passthrough not implemented
+ DE_FATAL("not implemented");
+ }
+
+ return buf.str();
+}
+
+std::string QuadrantRendederCase::genFragmentSource (void) const
+{
+ const char* const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
+ std::ostringstream buf;
+
+ if ((m_activeStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0u)
+ {
+ buf << versionDecl << "\n"
+ << genExtensionDeclarations(vk::VK_SHADER_STAGE_GEOMETRY_BIT)
+ << genResourceDeclarations(vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0);
+
+ if (m_activeStages != vk::VK_SHADER_STAGE_FRAGMENT_BIT)
+ {
+ // there are other stages, this is just a contributor
+ buf << "layout(location = 0) in mediump vec4 frag_color;\n";
+ }
+
+ buf << "layout(location = 1) flat in highp int frag_quadrant_id;\n"
+ << "layout(location = 0) out mediump vec4 o_color;\n"
+ << "void main (void)\n"
+ << "{\n"
+ << " highp int quadrant_id = frag_quadrant_id;\n"
+ << " highp vec4 result_color;\n"
+ << genResourceAccessSource(vk::VK_SHADER_STAGE_FRAGMENT_BIT);
+
+ if (m_activeStages != vk::VK_SHADER_STAGE_FRAGMENT_BIT)
+ {
+ // just contributor
+ buf << " if (frag_quadrant_id < 2)\n"
+ << " o_color = result_color;\n"
+ << " else\n"
+ << " o_color = frag_color;\n";
+ }
+ else
+ buf << " o_color = result_color;\n";
+
+ buf << "}\n";
+ }
+ else if (m_activeStages == 0u)
+ {
+ // special case, no active stages
+ buf << versionDecl << "\n"
+ << "layout(location = 1) flat in highp int frag_quadrant_id;\n"
+ << "layout(location = 0) out mediump vec4 o_color;\n"
+ << "void main (void)\n"
+ << "{\n"
+ << " highp int quadrant_id = frag_quadrant_id;\n"
+ << " highp vec4 result_color;\n"
+ << genNoAccessSource()
+ << " o_color = result_color;\n"
+ << "}\n";
+ }
+ else
+ {
+ // passthrough
+ buf << versionDecl << "\n"
+ << "layout(location = 0) in mediump vec4 frag_color;\n"
+ "layout(location = 0) out mediump vec4 o_color;\n"
+ "void main (void)\n"
+ "{\n"
+ " o_color = frag_color;\n"
+ "}\n";
+ }
+
+ return buf.str();
+}
+
+std::string QuadrantRendederCase::genComputeSource (void) const
+{
+ const char* const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
+ std::ostringstream buf;
+
+ buf << versionDecl << "\n"
+ << genExtensionDeclarations(vk::VK_SHADER_STAGE_COMPUTE_BIT)
+ << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
+ << genResourceDeclarations(vk::VK_SHADER_STAGE_COMPUTE_BIT, 1)
+ << "layout(set = 0, binding = 0, std140) writeonly buffer OutBuf\n"
+ << "{\n"
+ << " highp vec4 read_colors[4];\n"
+ << "} b_out;\n"
+ << "void main(void)\n"
+ << "{\n"
+ << " highp int quadrant_id = int(gl_WorkGroupID.x);\n"
+ << " highp vec4 result_color;\n"
+ << genResourceAccessSource(vk::VK_SHADER_STAGE_COMPUTE_BIT)
+ << " b_out.read_colors[gl_WorkGroupID.x] = result_color;\n"
+ << "}\n";
+
+ return buf.str();
+}
+
+void QuadrantRendederCase::initPrograms (vk::SourceCollections& programCollection) const
+{
+ if ((m_exitingStages & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0u)
+ programCollection.glslSources.add("vertex") << glu::VertexSource(genVertexSource());
+
+ if ((m_exitingStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0u)
+ programCollection.glslSources.add("tess_ctrl") << glu::TessellationControlSource(genTessCtrlSource());
+
+ if ((m_exitingStages & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0u)
+ programCollection.glslSources.add("tess_eval") << glu::TessellationEvaluationSource(genTessEvalSource());
+
+ if ((m_exitingStages & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0u)
+ programCollection.glslSources.add("geometry") << glu::GeometrySource(genGeometrySource());
+
+ if ((m_exitingStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0u)
+ programCollection.glslSources.add("fragment") << glu::FragmentSource(genFragmentSource());
+
+ if ((m_exitingStages & vk::VK_SHADER_STAGE_COMPUTE_BIT) != 0u)
+ programCollection.glslSources.add("compute") << glu::ComputeSource(genComputeSource());
+}
+
+class BufferDescriptorCase : public QuadrantRendederCase
+{
+public:
+ enum
+ {
+ FLAG_VIEW_OFFSET = (1u << 1u),
+ FLAG_DYNAMIC_OFFSET_ZERO = (1u << 2u),
+ FLAG_DYNAMIC_OFFSET_NONZERO = (1u << 3u),
+ };
+ // enum continues where resource flags ends
+ DE_STATIC_ASSERT((deUint32)FLAG_VIEW_OFFSET == (deUint32)RESOURCE_FLAG_LAST);
+
+ BufferDescriptorCase (tcu::TestContext& testCtx,
+ const char* name,
+ const char* description,
+ bool isPrimaryCmdBuf,
+ vk::VkDescriptorType descriptorType,
+ vk::VkShaderStageFlags exitingStages,
+ vk::VkShaderStageFlags activeStages,
+ ShaderInputInterface shaderInterface,
+ deUint32 flags);
+
+private:
+ std::string genExtensionDeclarations (vk::VkShaderStageFlagBits stage) const;
+ std::string genResourceDeclarations (vk::VkShaderStageFlagBits stage, int numUsedBindings) const;
+ std::string genResourceAccessSource (vk::VkShaderStageFlagBits stage) const;
+ std::string genNoAccessSource (void) const;
+
+ vkt::TestInstance* createInstance (vkt::Context& context) const;
+
+ const bool m_viewOffset;
+ const bool m_dynamicOffsetSet;
+ const bool m_dynamicOffsetNonZero;
+ const bool m_isPrimaryCmdBuf;
+ const vk::VkDescriptorType m_descriptorType;
+ const ShaderInputInterface m_shaderInterface;
+};
+
+BufferDescriptorCase::BufferDescriptorCase (tcu::TestContext& testCtx,
+ const char* name,
+ const char* description,
+ bool isPrimaryCmdBuf,
+ vk::VkDescriptorType descriptorType,
+ vk::VkShaderStageFlags exitingStages,
+ vk::VkShaderStageFlags activeStages,
+ ShaderInputInterface shaderInterface,
+ deUint32 flags)
+ : QuadrantRendederCase (testCtx, name, description, glu::GLSL_VERSION_310_ES, exitingStages, activeStages)
+ , m_viewOffset ((flags & FLAG_VIEW_OFFSET) != 0u)
+ , m_dynamicOffsetSet ((flags & (FLAG_DYNAMIC_OFFSET_ZERO | FLAG_DYNAMIC_OFFSET_NONZERO)) != 0u)
+ , m_dynamicOffsetNonZero ((flags & FLAG_DYNAMIC_OFFSET_NONZERO) != 0u)
+ , m_isPrimaryCmdBuf (isPrimaryCmdBuf)
+ , m_descriptorType (descriptorType)
+ , m_shaderInterface (shaderInterface)
+{
+}
+
+std::string BufferDescriptorCase::genExtensionDeclarations (vk::VkShaderStageFlagBits stage) const
+{
+ DE_UNREF(stage);
+ return "";
+}
+
+std::string BufferDescriptorCase::genResourceDeclarations (vk::VkShaderStageFlagBits stage, int numUsedBindings) const
+{
+ DE_UNREF(stage);
+
+ const bool isUniform = isUniformDescriptorType(m_descriptorType);
+ const char* const storageType = (isUniform) ? ("uniform") : ("buffer");
+ std::ostringstream buf;
+
+ switch (m_shaderInterface)
+ {
+ case SHADER_INPUT_SINGLE_DESCRIPTOR:
+ buf << "layout(set = 0, binding = " << (numUsedBindings) << ", std140) " << storageType << " BufferName\n"
+ << "{\n"
+ << " highp vec4 colorA;\n"
+ << " highp vec4 colorB;\n"
+ << "} b_instance;\n";
+ break;
+
+ case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
+ buf << "layout(set = 0, binding = " << (numUsedBindings) << ", std140) " << storageType << " BufferNameA\n"
+ << "{\n"
+ << " highp vec4 colorA;\n"
+ << " highp vec4 colorB;\n"
+ << "} b_instanceA;\n"
+ << "layout(set = 0, binding = " << (numUsedBindings+1) << ", std140) " << storageType << " BufferNameB\n"
+ << "{\n"
+ << " highp vec4 colorA;\n"
+ << " highp vec4 colorB;\n"
+ << "} b_instanceB;\n";
+ break;
+
+ case SHADER_INPUT_DESCRIPTOR_ARRAY:
+ buf << "layout(set = 0, binding = " << (numUsedBindings) << ", std140) " << storageType << " BufferName\n"
+ << "{\n"
+ << " highp vec4 colorA;\n"
+ << " highp vec4 colorB;\n"
+ << "} b_instances[2];\n";
+ break;
+
+ default:
+ DE_FATAL("Impossible");
+ }
+
+ return buf.str();
+}
+
+std::string BufferDescriptorCase::genResourceAccessSource (vk::VkShaderStageFlagBits stage) const
+{
+ DE_UNREF(stage);
+
+ std::ostringstream buf;
+
+ switch (m_shaderInterface)
+ {
+ case SHADER_INPUT_SINGLE_DESCRIPTOR:
+ buf << " if (quadrant_id == 1 || quadrant_id == 2)\n"
+ << " result_color = b_instance.colorA;\n"
+ << " else\n"
+ << " result_color = b_instance.colorB;\n";
+ break;
+
+ case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
+ buf << " if (quadrant_id == 1 || quadrant_id == 2)\n"
+ << " result_color = b_instanceA.colorA;\n"
+ << " else\n"
+ << " result_color = b_instanceB.colorB;\n";
+ break;
+
+ case SHADER_INPUT_DESCRIPTOR_ARRAY:
+ buf << " if (quadrant_id == 1 || quadrant_id == 2)\n"
+ << " result_color = b_instances[0].colorA;\n"
+ << " else\n"
+ << " result_color = b_instances[1].colorB;\n";
+ break;
+
+ default:
+ DE_FATAL("Impossible");
+ }
+
+ return buf.str();
+}
+
+std::string BufferDescriptorCase::genNoAccessSource (void) const
+{
+ return " if (quadrant_id == 1 || quadrant_id == 2)\n"
+ " result_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
+ " else\n"
+ " result_color = vec4(1.0, 1.0, 0.0, 1.0);\n";
+}
+
+vkt::TestInstance* BufferDescriptorCase::createInstance (vkt::Context& context) const
+{
+ if (m_exitingStages == vk::VK_SHADER_STAGE_COMPUTE_BIT)
+ {
+ DE_ASSERT(m_isPrimaryCmdBuf); // secondaries are only valid within renderpass
+ return new BufferComputeInstance(context, m_descriptorType, m_shaderInterface, m_viewOffset, m_dynamicOffsetSet, m_dynamicOffsetNonZero);
+ }
+ else
+ return new BufferRenderInstance(context, m_isPrimaryCmdBuf, m_descriptorType, m_activeStages, m_shaderInterface, m_viewOffset, m_dynamicOffsetSet, m_dynamicOffsetNonZero);
+}
+
+class ImageInstanceImages
+{
+public:
+ ImageInstanceImages (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ deUint32 queueFamilyIndex,
+ vk::VkQueue queue,
+ vk::Allocator& allocator,
+ vk::VkDescriptorType descriptorType,
+ vk::VkImageViewType viewType,
+ int numImages,
+ deUint32 baseMipLevel,
+ deUint32 baseArraySlice);
+
+private:
+ static vk::Move<vk::VkImage> createImage (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::Allocator& allocator,
+ vk::VkDescriptorType descriptorType,
+ vk::VkImageViewType viewType,
+ const tcu::TextureLevelPyramid& sourceImage,
+ de::MovePtr<vk::Allocation>* outAllocation);
+
+ static vk::Move<vk::VkImageView> createImageView (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::VkImageViewType viewType,
+ const tcu::TextureLevelPyramid& sourceImage,
+ vk::VkImage image,
+ deUint32 baseMipLevel,
+ deUint32 baseArraySlice);
+
+ void populateSourceImage (tcu::TextureLevelPyramid* dst,
+ bool isFirst) const;
+
+ void uploadImage (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ deUint32 queueFamilyIndex,
+ vk::VkQueue queue,
+ vk::Allocator& allocator,
+ vk::VkImage image,
+ const tcu::TextureLevelPyramid& data);
+
+protected:
+ enum
+ {
+ IMAGE_SIZE = 64,
+ NUM_MIP_LEVELS = 2,
+ ARRAY_SIZE = 2,
+ };
+
+ const vk::VkImageViewType m_viewType;
+ const deUint32 m_baseMipLevel;
+ const deUint32 m_baseArraySlice;
+
+ const tcu::TextureFormat m_imageFormat;
+ tcu::TextureLevelPyramid m_sourceImageA;
+ tcu::TextureLevelPyramid m_sourceImageB;
+
+ de::MovePtr<vk::Allocation> m_imageMemoryA;
+ de::MovePtr<vk::Allocation> m_imageMemoryB;
+ vk::Move<vk::VkImage> m_imageA;
+ vk::Move<vk::VkImage> m_imageB;
+ vk::Move<vk::VkImageView> m_imageViewA;
+ vk::Move<vk::VkImageView> m_imageViewB;
+};
+
+ImageInstanceImages::ImageInstanceImages (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ deUint32 queueFamilyIndex,
+ vk::VkQueue queue,
+ vk::Allocator& allocator,
+ vk::VkDescriptorType descriptorType,
+ vk::VkImageViewType viewType,
+ int numImages,
+ deUint32 baseMipLevel,
+ deUint32 baseArraySlice)
+ : m_viewType (viewType)
+ , m_baseMipLevel (baseMipLevel)
+ , m_baseArraySlice (baseArraySlice)
+ , m_imageFormat (tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)
+ , m_sourceImageA (m_imageFormat, NUM_MIP_LEVELS)
+ , m_sourceImageB (m_imageFormat, NUM_MIP_LEVELS)
+ , m_imageMemoryA (DE_NULL)
+ , m_imageMemoryB (DE_NULL)
+ , m_imageA (vk::Move<vk::VkImage>())
+ , m_imageB (vk::Move<vk::VkImage>())
+ , m_imageViewA (vk::Move<vk::VkImageView>())
+ , m_imageViewB (vk::Move<vk::VkImageView>())
+{
+ DE_ASSERT(numImages == 1 || numImages == 2);
+
+ populateSourceImage(&m_sourceImageA, true);
+ m_imageA = createImage(vki, device, allocator, descriptorType, viewType, m_sourceImageA, &m_imageMemoryA);
+ m_imageViewA = createImageView(vki, device, viewType, m_sourceImageA, *m_imageA, m_baseMipLevel, m_baseArraySlice);
+ uploadImage(vki, device, queueFamilyIndex, queue, allocator, *m_imageA, m_sourceImageA);
+
+ if (numImages == 2)
+ {
+ populateSourceImage(&m_sourceImageB, false);
+ m_imageB = createImage(vki, device, allocator, descriptorType, viewType, m_sourceImageB, &m_imageMemoryB);
+ m_imageViewB = createImageView(vki, device, viewType, m_sourceImageB, *m_imageB, m_baseMipLevel, m_baseArraySlice);
+ uploadImage(vki, device, queueFamilyIndex, queue, allocator, *m_imageB, m_sourceImageB);
+ }
+}
+
+vk::Move<vk::VkImage> ImageInstanceImages::createImage (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::Allocator& allocator,
+ vk::VkDescriptorType descriptorType,
+ vk::VkImageViewType viewType,
+ const tcu::TextureLevelPyramid& sourceImage,
+ de::MovePtr<vk::Allocation>* outAllocation)
+{
+ const tcu::ConstPixelBufferAccess baseLevel = sourceImage.getLevel(0);
+ const bool isCube = (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY);
+ const bool isStorage = (descriptorType == vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
+ const deUint32 readUsage = (isStorage) ? (vk::VK_IMAGE_USAGE_STORAGE_BIT) : (vk::VK_IMAGE_USAGE_SAMPLED_BIT);
+ const deUint32 arraySize = (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? (baseLevel.getHeight())
+ : (viewType == vk::VK_IMAGE_VIEW_TYPE_2D || viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY) ? (baseLevel.getDepth())
+ : (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (1)
+ : (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? (baseLevel.getDepth()) // cube: numFaces * numLayers
+ : (0);
+ const vk::VkExtent3D extent =
+ {
+ // x
+ (deInt32)baseLevel.getWidth(),
+
+ // y
+ (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? (1) : (deInt32)baseLevel.getHeight(),
+
+ // z
+ (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? ((deInt32)baseLevel.getDepth()) : (1),
+ };
+ const vk::VkImageCreateInfo createInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
+ DE_NULL,
+ isCube ? (vk::VkImageCreateFlags)vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (vk::VkImageCreateFlags)0,
+ viewTypeToImageType(viewType), // imageType
+ vk::mapTextureFormat(baseLevel.getFormat()), // format
+ extent, // extent
+ (deUint32)sourceImage.getNumLevels(), // mipLevels
+ arraySize, // arraySize
+ vk::VK_SAMPLE_COUNT_1_BIT, // samples
+ vk::VK_IMAGE_TILING_OPTIMAL, // tiling
+ readUsage | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT, // usage
+ vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
+ 0u, // queueFamilyCount
+ DE_NULL, // pQueueFamilyIndices
+ vk::VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout
+ };
+ vk::Move<vk::VkImage> image (vk::createImage(vki, device, &createInfo));
+
+ *outAllocation = allocateAndBindObjectMemory(vki, device, allocator, *image, vk::MemoryRequirement::Any);
+ return image;
+}
+
+vk::Move<vk::VkImageView> ImageInstanceImages::createImageView (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::VkImageViewType viewType,
+ const tcu::TextureLevelPyramid& sourceImage,
+ vk::VkImage image,
+ deUint32 baseMipLevel,
+ deUint32 baseArraySlice)
+{
+ const tcu::ConstPixelBufferAccess baseLevel = sourceImage.getLevel(0);
+ const deUint32 viewTypeBaseSlice = (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? (6 * baseArraySlice) : (baseArraySlice);
+ const deUint32 viewArraySize = (viewType == vk::VK_IMAGE_VIEW_TYPE_1D) ? (1)
+ : (viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? (baseLevel.getHeight() - viewTypeBaseSlice)
+ : (viewType == vk::VK_IMAGE_VIEW_TYPE_2D) ? (1)
+ : (viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY) ? (baseLevel.getDepth() - viewTypeBaseSlice)
+ : (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (1)
+ : (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE) ? (6)
+ : (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? (baseLevel.getDepth() - viewTypeBaseSlice) // cube: numFaces * numLayers
+ : (0);
+
+ DE_ASSERT(viewArraySize > 0);
+
+ const vk::VkImageSubresourceRange resourceRange =
+ {
+ vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
+ baseMipLevel, // baseMipLevel
+ sourceImage.getNumLevels() - baseMipLevel, // mipLevels
+ viewTypeBaseSlice, // baseArraySlice
+ viewArraySize, // arraySize
+ };
+ const vk::VkImageViewCreateInfo createInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
+ DE_NULL,
+ (vk::VkImageViewCreateFlags)0,
+ image, // image
+ viewType, // viewType
+ vk::mapTextureFormat(baseLevel.getFormat()), // format
+ {
+ vk::VK_COMPONENT_SWIZZLE_R,
+ vk::VK_COMPONENT_SWIZZLE_G,
+ vk::VK_COMPONENT_SWIZZLE_B,
+ vk::VK_COMPONENT_SWIZZLE_A
+ }, // channels
+ resourceRange, // subresourceRange
+ };
+ return vk::createImageView(vki, device, &createInfo);
+}
+
+void ImageInstanceImages::populateSourceImage (tcu::TextureLevelPyramid* dst, bool isFirst) const
+{
+ const int numLevels = dst->getNumLevels();
+
+ for (int level = 0; level < numLevels; ++level)
+ {
+ const int width = IMAGE_SIZE >> level;
+ const int height = (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? (ARRAY_SIZE)
+ : (IMAGE_SIZE >> level);
+ const int depth = (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? (1)
+ : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY) ? (ARRAY_SIZE)
+ : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? (6 * ARRAY_SIZE)
+ : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (IMAGE_SIZE >> level)
+ : (1);
+
+ dst->allocLevel(level, width, height, depth);
+
+ {
+ const tcu::PixelBufferAccess levelAccess = dst->getLevel(level);
+
+ for (int z = 0; z < depth; ++z)
+ for (int y = 0; y < height; ++y)
+ for (int x = 0; x < width; ++x)
+ {
+ const int gradPos = x + y + z;
+ const int gradMax = width + height + depth - 3;
+
+ const int red = 255 * gradPos / gradMax; //!< gradient from 0 -> max (detects large offset errors)
+ const int green = ((gradPos % 2 == 0) ? (127) : (0)) + ((gradPos % 4 < 3) ? (128) : (0)); //!< 3-level M pattern (detects small offset errors)
+ const int blue = (128 * level / numLevels) + (isFirst ? 127 : 0); //!< level and image index (detects incorrect lod / image)
+
+ DE_ASSERT(de::inRange(red, 0, 255));
+ DE_ASSERT(de::inRange(green, 0, 255));
+ DE_ASSERT(de::inRange(blue, 0, 255));
+
+ levelAccess.setPixel(tcu::IVec4(red, green, blue, 255), x, y, z);
+ }
+ }
+ }
+}
+
+void ImageInstanceImages::uploadImage (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ deUint32 queueFamilyIndex,
+ vk::VkQueue queue,
+ vk::Allocator& allocator,
+ vk::VkImage image,
+ const tcu::TextureLevelPyramid& data)
+{
+ const deUint32 arraySize = (m_viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (1) :
+ (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? (6 * (deUint32)ARRAY_SIZE) :
+ ((deUint32)ARRAY_SIZE);
+ const deUint32 dataBufferSize = getTextureLevelPyramidDataSize(data);
+ const vk::VkBufferCreateInfo bufferCreateInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
+ DE_NULL,
+ 0u, // flags
+ dataBufferSize, // size
+ vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT, // usage
+ vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
+ 0u, // queueFamilyCount
+ DE_NULL, // pQueueFamilyIndices
+ };
+ const vk::Unique<vk::VkBuffer> dataBuffer (vk::createBuffer(vki, device, &bufferCreateInfo));
+ const de::MovePtr<vk::Allocation> dataBufferMemory = allocateAndBindObjectMemory(vki, device, allocator, *dataBuffer, vk::MemoryRequirement::HostVisible);
+ const vk::VkFenceCreateInfo fenceCreateInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
+ DE_NULL,
+ 0u, // flags
+ };
+ const vk::VkBufferMemoryBarrier preMemoryBarrier =
+ {
+ vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
+ DE_NULL,
+ vk::VK_ACCESS_HOST_WRITE_BIT, // outputMask
+ vk::VK_ACCESS_TRANSFER_READ_BIT, // inputMask
+ vk::VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
+ vk::VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex
+ *dataBuffer, // buffer
+ 0u, // offset
+ dataBufferSize, // size
+ };
+ const vk::VkImageSubresourceRange fullSubrange =
+ {
+ vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
+ 0u, // baseMipLevel
+ (deUint32)data.getNumLevels(), // mipLevels
+ 0u, // baseArraySlice
+ arraySize, // arraySize
+ };
+ const vk::VkImageMemoryBarrier preImageBarrier =
+ {
+ vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
+ DE_NULL,
+ 0u, // outputMask
+ 0u, // inputMask
+ vk::VK_IMAGE_LAYOUT_UNDEFINED, // oldLayout
+ vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // newLayout
+ vk::VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
+ vk::VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex
+ image, // image
+ fullSubrange // subresourceRange
+ };
+ const vk::VkImageMemoryBarrier postImageBarrier =
+ {
+ vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
+ DE_NULL,
+ vk::VK_ACCESS_TRANSFER_WRITE_BIT, // outputMask
+ vk::VK_ACCESS_SHADER_READ_BIT, // inputMask
+ vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // oldLayout
+ vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // newLayout
+ vk::VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
+ vk::VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex
+ image, // image
+ fullSubrange // subresourceRange
+ };
+ const vk::VkCommandPoolCreateInfo cmdPoolCreateInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
+ DE_NULL,
+ vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // flags
+ queueFamilyIndex, // queueFamilyIndex
+ };
+ const vk::Unique<vk::VkCommandPool> cmdPool (vk::createCommandPool(vki, device, &cmdPoolCreateInfo));
+ const vk::VkCommandBufferAllocateInfo cmdBufCreateInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
+ DE_NULL,
+ *cmdPool, // cmdPool
+ vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level
+ 1u, // count
+ };
+ const vk::VkCommandBufferBeginInfo cmdBufBeginInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+ DE_NULL,
+ vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // flags
+ (vk::VkRenderPass)0u, // renderPass
+ 0u, // subpass
+ (vk::VkFramebuffer)0u, // framebuffer
+ vk::VK_FALSE, // occlusionQueryEnable
+ (vk::VkQueryControlFlags)0,
+ (vk::VkQueryPipelineStatisticFlags)0,
+ };
+
+ const vk::Unique<vk::VkCommandBuffer> cmd (vk::allocateCommandBuffer(vki, device, &cmdBufCreateInfo));
+ const void* const preBarriers[2] = { &preMemoryBarrier, &preImageBarrier };
+ const void* const postBarriers[1] = { &postImageBarrier };
+ const vk::Unique<vk::VkFence> cmdCompleteFence (vk::createFence(vki, device, &fenceCreateInfo));
+ const deUint64 infiniteTimeout = ~(deUint64)0u;
+ std::vector<vk::VkBufferImageCopy> copySlices;
+
+ // copy data to buffer
+ writeTextureLevelPyramidData(dataBufferMemory->getHostPtr(), dataBufferSize, data, m_viewType , ©Slices);
+ flushMappedMemoryRange(vki, device, dataBufferMemory->getMemory(), dataBufferMemory->getOffset(), dataBufferSize);
+
+ // record command buffer
+ VK_CHECK(vki.beginCommandBuffer(*cmd, &cmdBufBeginInfo));
+ vki.cmdPipelineBarrier(*cmd, 0u, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_FALSE, DE_LENGTH_OF_ARRAY(preBarriers), preBarriers);
+ vki.cmdCopyBufferToImage(*cmd, *dataBuffer, image, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, (deUint32)copySlices.size(), ©Slices[0]);
+ vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_FALSE, DE_LENGTH_OF_ARRAY(postBarriers), postBarriers);
+ VK_CHECK(vki.endCommandBuffer(*cmd));
+
+ // submit and wait for command buffer to complete before killing it
+ {
+ const vk::VkSubmitInfo submitInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
+ DE_NULL,
+ 0u,
+ (const vk::VkSemaphore*)0,
+ 1u,
+ &cmd.get(),
+ 0u,
+ (const vk::VkSemaphore*)0,
+ };
+ VK_CHECK(vki.queueSubmit(queue, 1, &submitInfo, *cmdCompleteFence));
+ }
+ VK_CHECK(vki.waitForFences(device, 1, &cmdCompleteFence.get(), 0u, infiniteTimeout)); // \note: timeout is failure
+}
+
+class ImageFetchInstanceImages : private ImageInstanceImages
+{
+public:
+ ImageFetchInstanceImages (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ deUint32 queueFamilyIndex,
+ vk::VkQueue queue,
+ vk::Allocator& allocator,
+ vk::VkDescriptorType descriptorType,
+ ShaderInputInterface shaderInterface,
+ vk::VkImageViewType viewType,
+ deUint32 baseMipLevel,
+ deUint32 baseArraySlice);
+
+ static tcu::IVec3 getFetchPos (vk::VkImageViewType viewType, deUint32 baseMipLevel, deUint32 baseArraySlice, int fetchPosNdx);
+ tcu::Vec4 fetchImageValue (int fetchPosNdx) const;
+
+ inline vk::VkImageView getImageViewA (void) const { return *m_imageViewA; }
+ inline vk::VkImageView getImageViewB (void) const { return *m_imageViewB; }
+
+private:
+ enum
+ {
+ // some arbitrary sample points for all four quadrants
+ SAMPLE_POINT_0_X = 6,
+ SAMPLE_POINT_0_Y = 13,
+ SAMPLE_POINT_0_Z = 49,
+
+ SAMPLE_POINT_1_X = 51,
+ SAMPLE_POINT_1_Y = 40,
+ SAMPLE_POINT_1_Z = 44,
+
+ SAMPLE_POINT_2_X = 42,
+ SAMPLE_POINT_2_Y = 26,
+ SAMPLE_POINT_2_Z = 19,
+
+ SAMPLE_POINT_3_X = 25,
+ SAMPLE_POINT_3_Y = 25,
+ SAMPLE_POINT_3_Z = 18,
+ };
+
+ const ShaderInputInterface m_shaderInterface;
+};
+
+ImageFetchInstanceImages::ImageFetchInstanceImages (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ deUint32 queueFamilyIndex,
+ vk::VkQueue queue,
+ vk::Allocator& allocator,
+ vk::VkDescriptorType descriptorType,
+ ShaderInputInterface shaderInterface,
+ vk::VkImageViewType viewType,
+ deUint32 baseMipLevel,
+ deUint32 baseArraySlice)
+ : ImageInstanceImages (vki,
+ device,
+ queueFamilyIndex,
+ queue,
+ allocator,
+ descriptorType,
+ viewType,
+ getInterfaceNumResources(shaderInterface), // numImages
+ baseMipLevel,
+ baseArraySlice)
+ , m_shaderInterface (shaderInterface)
+{
+}
+
+bool isImageViewTypeArray (vk::VkImageViewType type)
+{
+ return type == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY || type == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY || type == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
+}
+
+tcu::IVec3 ImageFetchInstanceImages::getFetchPos (vk::VkImageViewType viewType, deUint32 baseMipLevel, deUint32 baseArraySlice, int fetchPosNdx)
+{
+ const tcu::IVec3 fetchPositions[4] =
+ {
+ tcu::IVec3(SAMPLE_POINT_0_X, SAMPLE_POINT_0_Y, SAMPLE_POINT_0_Z),
+ tcu::IVec3(SAMPLE_POINT_1_X, SAMPLE_POINT_1_Y, SAMPLE_POINT_1_Z),
+ tcu::IVec3(SAMPLE_POINT_2_X, SAMPLE_POINT_2_Y, SAMPLE_POINT_2_Z),
+ tcu::IVec3(SAMPLE_POINT_3_X, SAMPLE_POINT_3_Y, SAMPLE_POINT_3_Z),
+ };
+ const tcu::IVec3 coord = de::getSizedArrayElement<4>(fetchPositions, fetchPosNdx);
+ const deUint32 imageSize = (deUint32)IMAGE_SIZE >> baseMipLevel;
+ const deUint32 arraySize = isImageViewTypeArray(viewType) ? ARRAY_SIZE - baseArraySlice : 1;
+
+ switch (viewType)
+ {
+ case vk::VK_IMAGE_VIEW_TYPE_1D:
+ case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY: return tcu::IVec3(coord.x() % imageSize, coord.y() % arraySize, 0);
+ case vk::VK_IMAGE_VIEW_TYPE_2D:
+ case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY: return tcu::IVec3(coord.x() % imageSize, coord.y() % imageSize, coord.z() % arraySize);
+ case vk::VK_IMAGE_VIEW_TYPE_CUBE:
+ case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: return tcu::IVec3(coord.x() % imageSize, coord.y() % imageSize, coord.z() % (arraySize * 6));
+ case vk::VK_IMAGE_VIEW_TYPE_3D: return tcu::IVec3(coord.x() % imageSize, coord.y() % imageSize, coord.z() % imageSize);
+ default:
+ DE_FATAL("Impossible");
+ return tcu::IVec3();
+ }
+}
+
+tcu::Vec4 ImageFetchInstanceImages::fetchImageValue (int fetchPosNdx) const
+{
+ DE_ASSERT(de::inBounds(fetchPosNdx, 0, 4));
+
+ const tcu::TextureLevelPyramid& fetchSrcA = m_sourceImageA;
+ const tcu::TextureLevelPyramid& fetchSrcB = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? (m_sourceImageA) : (m_sourceImageB);
+ const tcu::TextureLevelPyramid& fetchSrc = ((fetchPosNdx % 2) == 0) ? (fetchSrcA) : (fetchSrcB); // sampling order is ABAB
+ const tcu::IVec3 fetchPos = getFetchPos(m_viewType, m_baseMipLevel, m_baseArraySlice, fetchPosNdx);
+
+ return fetchSrc.getLevel(m_baseMipLevel).getPixel(fetchPos.x(), fetchPos.y(), fetchPos.z());
+}
+
+class ImageFetchRenderInstance : public SingleCmdRenderInstance
+{
+public:
+ ImageFetchRenderInstance (vkt::Context& context,
+ bool isPrimaryCmdBuf,
+ vk::VkDescriptorType descriptorType,
+ vk::VkShaderStageFlags stageFlags,
+ ShaderInputInterface shaderInterface,
+ vk::VkImageViewType viewType,
+ deUint32 baseMipLevel,
+ deUint32 baseArraySlice);
+
+private:
+ static vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::VkDescriptorType descriptorType,
+ ShaderInputInterface shaderInterface,
+ vk::VkShaderStageFlags stageFlags);
+
+ static vk::Move<vk::VkPipelineLayout> createPipelineLayout (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::VkDescriptorSetLayout descriptorSetLayout);
+
+ static vk::Move<vk::VkDescriptorPool> createDescriptorPool (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::VkDescriptorType descriptorType,
+ ShaderInputInterface shaderInterface);
+
+ static vk::Move<vk::VkDescriptorSet> createDescriptorSet (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::VkDescriptorType descriptorType,
+ ShaderInputInterface shaderInterface,
+ vk::VkDescriptorSetLayout layout,
+ vk::VkDescriptorPool pool,
+ vk::VkImageView viewA,
+ vk::VkImageView viewB);
+
+ void logTestPlan (void) const;
+ vk::VkPipelineLayout getPipelineLayout (void) const;
+ void writeDrawCmdBuffer (vk::VkCommandBuffer cmd) const;
+ tcu::TestStatus verifyResultImage (const tcu::ConstPixelBufferAccess& result) const;
+
+ enum
+ {
+ RENDER_SIZE = 128,
+ };
+
+ const vk::VkDescriptorType m_descriptorType;
+ const vk::VkShaderStageFlags m_stageFlags;
+ const ShaderInputInterface m_shaderInterface;
+ const vk::VkImageViewType m_viewType;
+ const deUint32 m_baseMipLevel;
+ const deUint32 m_baseArraySlice;
+
+ const vk::Unique<vk::VkDescriptorSetLayout> m_descriptorSetLayout;
+ const vk::Unique<vk::VkPipelineLayout> m_pipelineLayout;
+ const ImageFetchInstanceImages m_images;
+ const vk::Unique<vk::VkDescriptorPool> m_descriptorPool;
+ const vk::Unique<vk::VkDescriptorSet> m_descriptorSet;
+};
+
+ImageFetchRenderInstance::ImageFetchRenderInstance (vkt::Context& context,
+ bool isPrimaryCmdBuf,
+ vk::VkDescriptorType descriptorType,
+ vk::VkShaderStageFlags stageFlags,
+ ShaderInputInterface shaderInterface,
+ vk::VkImageViewType viewType,
+ deUint32 baseMipLevel,
+ deUint32 baseArraySlice)
+ : SingleCmdRenderInstance (context, isPrimaryCmdBuf, tcu::UVec2(RENDER_SIZE, RENDER_SIZE))
+ , m_descriptorType (descriptorType)
+ , m_stageFlags (stageFlags)
+ , m_shaderInterface (shaderInterface)
+ , m_viewType (viewType)
+ , m_baseMipLevel (baseMipLevel)
+ , m_baseArraySlice (baseArraySlice)
+ , m_descriptorSetLayout (createDescriptorSetLayout(m_vki, m_device, m_descriptorType, m_shaderInterface, m_stageFlags))
+ , m_pipelineLayout (createPipelineLayout(m_vki, m_device, *m_descriptorSetLayout))
+ , m_images (m_vki, m_device, m_queueFamilyIndex, m_queue, m_allocator, m_descriptorType, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice)
+ , m_descriptorPool (createDescriptorPool(m_vki, m_device, m_descriptorType, m_shaderInterface))
+ , m_descriptorSet (createDescriptorSet(m_vki, m_device, m_descriptorType, m_shaderInterface, *m_descriptorSetLayout, *m_descriptorPool, m_images.getImageViewA(), m_images.getImageViewB()))
+{
+}
+
+vk::Move<vk::VkDescriptorSetLayout> ImageFetchRenderInstance::createDescriptorSetLayout (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::VkDescriptorType descriptorType,
+ ShaderInputInterface shaderInterface,
+ vk::VkShaderStageFlags stageFlags)
+{
+ vk::DescriptorSetLayoutBuilder builder;
+
+ switch (shaderInterface)
+ {
+ case SHADER_INPUT_SINGLE_DESCRIPTOR:
+ builder.addSingleBinding(descriptorType, stageFlags);
+ break;
+
+ case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
+ builder.addSingleBinding(descriptorType, stageFlags);
+ builder.addSingleBinding(descriptorType, stageFlags);
+ break;
+
+ case SHADER_INPUT_DESCRIPTOR_ARRAY:
+ builder.addArrayBinding(descriptorType, 2u, stageFlags);
+ break;
+
+ default:
+ DE_FATAL("Impossible");
+ }
+
+ return builder.build(vki, device);
+}
+
+vk::Move<vk::VkPipelineLayout> ImageFetchRenderInstance::createPipelineLayout (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::VkDescriptorSetLayout descriptorSetLayout)
+{
+ const vk::VkPipelineLayoutCreateInfo createInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
+ DE_NULL,
+ (vk::VkPipelineLayoutCreateFlags)0,
+ 1, // descriptorSetCount
+ &descriptorSetLayout, // pSetLayouts
+ 0u, // pushConstantRangeCount
+ DE_NULL, // pPushConstantRanges
+ };
+ return vk::createPipelineLayout(vki, device, &createInfo);
+}
+
+vk::Move<vk::VkDescriptorPool> ImageFetchRenderInstance::createDescriptorPool (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::VkDescriptorType descriptorType,
+ ShaderInputInterface shaderInterface)
+{
+ return vk::DescriptorPoolBuilder()
+ .addType(descriptorType, getInterfaceNumResources(shaderInterface))
+ .build(vki, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
+}
+
+vk::Move<vk::VkDescriptorSet> ImageFetchRenderInstance::createDescriptorSet (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::VkDescriptorType descriptorType,
+ ShaderInputInterface shaderInterface,
+ vk::VkDescriptorSetLayout layout,
+ vk::VkDescriptorPool pool,
+ vk::VkImageView viewA,
+ vk::VkImageView viewB)
+{
+ const vk::VkDescriptorImageInfo imageInfos[2] =
+ {
+ makeDescriptorImageInfo(viewA, vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
+ makeDescriptorImageInfo(viewB, vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
+ };
+ const vk::VkDescriptorSetAllocateInfo allocInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+ DE_NULL,
+ pool,
+ 1u,
+ &layout
+ };
+
+ vk::Move<vk::VkDescriptorSet> descriptorSet = allocateDescriptorSet(vki, device, &allocInfo);
+ vk::DescriptorSetUpdateBuilder builder;
+
+ switch (shaderInterface)
+ {
+ case SHADER_INPUT_SINGLE_DESCRIPTOR:
+ builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &imageInfos[0]);
+ break;
+
+ case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
+ builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &imageInfos[0]);
+ builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), descriptorType, &imageInfos[1]);
+ break;
+
+ case SHADER_INPUT_DESCRIPTOR_ARRAY:
+ builder.writeArray(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, 2u, imageInfos);
+ break;
+
+ default:
+ DE_FATAL("Impossible");
+ }
+
+ builder.update(vki, device);
+ return descriptorSet;
+}
+
+void ImageFetchRenderInstance::logTestPlan (void) const
+{
+ std::ostringstream msg;
+
+ msg << "Rendering 2x2 grid.\n"
+ << "Single descriptor set. Descriptor set contains "
+ << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
+ (m_shaderInterface == SHADER_INPUT_MULTIPLE_DESCRIPTORS) ? "two" :
+ (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
+ (const char*)DE_NULL)
+ << " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
+ << "Image view type is " << vk::getImageViewTypeName(m_viewType) << "\n";
+
+ if (m_baseMipLevel)
+ msg << "Image view base mip level = " << m_baseMipLevel << "\n";
+ if (m_baseArraySlice)
+ msg << "Image view base array slice = " << m_baseArraySlice << "\n";
+
+ if (m_stageFlags == 0u)
+ {
+ msg << "Descriptors are not accessed in any shader stage.\n";
+ }
+ else
+ {
+ msg << "Color in each cell is fetched using the descriptor(s):\n";
+
+ for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
+ {
+ msg << "Test sample " << resultNdx << ": fetching at position " << m_images.getFetchPos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx);
+
+ if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
+ {
+ const int srcResourceNdx = (resultNdx % 2); // ABAB source
+ msg << " from descriptor " << srcResourceNdx;
+ }
+
+ msg << "\n";
+ }
+
+ msg << "Descriptors are accessed in {"
+ << (((m_stageFlags & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0) ? (" vertex") : (""))
+ << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0) ? (" tess_control") : (""))
+ << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0) ? (" tess_evaluation") : (""))
+ << (((m_stageFlags & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0) ? (" geometry") : (""))
+ << (((m_stageFlags & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0) ? (" fragment") : (""))
+ << " } stages.";
+ }
+
+ m_context.getTestContext().getLog()
+ << tcu::TestLog::Message
+ << msg.str()
+ << tcu::TestLog::EndMessage;
+}
+
+vk::VkPipelineLayout ImageFetchRenderInstance::getPipelineLayout (void) const
+{
+ return *m_pipelineLayout;
+}
+
+void ImageFetchRenderInstance::writeDrawCmdBuffer (vk::VkCommandBuffer cmd) const
+{
+ m_vki.cmdBindDescriptorSets(cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, getPipelineLayout(), 0, 1, &m_descriptorSet.get(), 0, DE_NULL);
+ m_vki.cmdDraw(cmd, 6 * 4, 1, 0, 0); // render four quads (two separate triangles)
+}
+
+tcu::TestStatus ImageFetchRenderInstance::verifyResultImage (const tcu::ConstPixelBufferAccess& result) const
+{
+ const tcu::Vec4 green (0.0f, 1.0f, 0.0f, 1.0f);
+ const tcu::Vec4 yellow (1.0f, 1.0f, 0.0f, 1.0f);
+ const bool doFetch = (m_stageFlags != 0u); // no active stages? Then don't fetch
+ const tcu::Vec4 sample0 = (!doFetch) ? (yellow) : (m_images.fetchImageValue(0));
+ const tcu::Vec4 sample1 = (!doFetch) ? (green) : (m_images.fetchImageValue(1));
+ const tcu::Vec4 sample2 = (!doFetch) ? (green) : (m_images.fetchImageValue(2));
+ const tcu::Vec4 sample3 = (!doFetch) ? (yellow) : (m_images.fetchImageValue(3));
+ tcu::Surface reference (m_targetSize.x(), m_targetSize.y());
+
+ drawQuadrantReferenceResult(reference.getAccess(), sample0, sample1, sample2, sample3);
+
+ if (!bilinearCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference.getAccess(), result, tcu::RGBA(1, 1, 1, 1), tcu::COMPARE_LOG_RESULT))
+ return tcu::TestStatus::fail("Image verification failed");
+ else
+ return tcu::TestStatus::pass("Pass");
+}
+
+class ImageFetchComputeInstance : public vkt::TestInstance
+{
+public:
+ ImageFetchComputeInstance (vkt::Context& context,
+ vk::VkDescriptorType descriptorType,
+ ShaderInputInterface shaderInterface,
+ vk::VkImageViewType viewType,
+ deUint32 baseMipLevel,
+ deUint32 baseArraySlice);
+
+private:
+ vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout (void) const;
+ vk::Move<vk::VkDescriptorPool> createDescriptorPool (void) const;
+ vk::Move<vk::VkDescriptorSet> createDescriptorSet (vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout) const;
+
+ tcu::TestStatus iterate (void);
+ void logTestPlan (void) const;
+ tcu::TestStatus testResourceAccess (void);
+
+ const vk::VkDescriptorType m_descriptorType;
+ const ShaderInputInterface m_shaderInterface;
+ const vk::VkImageViewType m_viewType;
+ const deUint32 m_baseMipLevel;
+ const deUint32 m_baseArraySlice;
+
+ const vk::DeviceInterface& m_vki;
+ const vk::VkDevice m_device;
+ const vk::VkQueue m_queue;
+ const deUint32 m_queueFamilyIndex;
+ vk::Allocator& m_allocator;
+
+ const ComputeInstanceResultBuffer m_result;
+ const ImageFetchInstanceImages m_images;
+};
+
+ImageFetchComputeInstance::ImageFetchComputeInstance (Context& context,
+ vk::VkDescriptorType descriptorType,
+ ShaderInputInterface shaderInterface,
+ vk::VkImageViewType viewType,
+ deUint32 baseMipLevel,
+ deUint32 baseArraySlice)
+ : vkt::TestInstance (context)
+ , m_descriptorType (descriptorType)
+ , m_shaderInterface (shaderInterface)
+ , m_viewType (viewType)
+ , m_baseMipLevel (baseMipLevel)
+ , m_baseArraySlice (baseArraySlice)
+ , m_vki (context.getDeviceInterface())
+ , m_device (context.getDevice())
+ , m_queue (context.getUniversalQueue())
+ , m_queueFamilyIndex (context.getUniversalQueueFamilyIndex())
+ , m_allocator (context.getDefaultAllocator())
+ , m_result (m_vki, m_device, m_allocator)
+ , m_images (m_vki, m_device, m_queueFamilyIndex, m_queue, m_allocator, m_descriptorType, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice)
+{
+}
+
+vk::Move<vk::VkDescriptorSetLayout> ImageFetchComputeInstance::createDescriptorSetLayout (void) const
+{
+ vk::DescriptorSetLayoutBuilder builder;
+
+ builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT);
+
+ switch (m_shaderInterface)
+ {
+ case SHADER_INPUT_SINGLE_DESCRIPTOR:
+ builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
+ break;
+
+ case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
+ builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
+ builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
+ break;
+
+ case SHADER_INPUT_DESCRIPTOR_ARRAY:
+ builder.addArrayBinding(m_descriptorType, 2u, vk::VK_SHADER_STAGE_COMPUTE_BIT);
+ break;
+
+ default:
+ DE_FATAL("Impossible");
+ };
+
+ return builder.build(m_vki, m_device);
+}
+
+vk::Move<vk::VkDescriptorPool> ImageFetchComputeInstance::createDescriptorPool (void) const
+{
+ return vk::DescriptorPoolBuilder()
+ .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
+ .addType(m_descriptorType, getInterfaceNumResources(m_shaderInterface))
+ .build(m_vki, m_device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
+}
+
+vk::Move<vk::VkDescriptorSet> ImageFetchComputeInstance::createDescriptorSet (vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout) const
+{
+ const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
+ const vk::VkDescriptorImageInfo imageInfos[2] =
+ {
+ makeDescriptorImageInfo(m_images.getImageViewA(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
+ makeDescriptorImageInfo(m_images.getImageViewB(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
+ };
+ const vk::VkDescriptorSetAllocateInfo allocInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+ DE_NULL,
+ pool,
+ 1u,
+ &layout
+ };
+
+ vk::Move<vk::VkDescriptorSet> descriptorSet = allocateDescriptorSet(m_vki, m_device, &allocInfo);
+ vk::DescriptorSetUpdateBuilder builder;
+
+ // result
+ builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
+
+ // images
+ switch (m_shaderInterface)
+ {
+ case SHADER_INPUT_SINGLE_DESCRIPTOR:
+ builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, &imageInfos[0]);
+ break;
+
+ case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
+ builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, &imageInfos[0]);
+ builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), m_descriptorType, &imageInfos[1]);
+ break;
+
+ case SHADER_INPUT_DESCRIPTOR_ARRAY:
+ builder.writeArray(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, 2u, imageInfos);
+ break;
+
+ default:
+ DE_FATAL("Impossible");
+ }
+
+ builder.update(m_vki, m_device);
+ return descriptorSet;
+}
+
+tcu::TestStatus ImageFetchComputeInstance::iterate (void)
+{
+ logTestPlan();
+ return testResourceAccess();
+}
+
+void ImageFetchComputeInstance::logTestPlan (void) const
+{
+ std::ostringstream msg;
+
+ msg << "Fetching 4 values from image in compute shader.\n"
+ << "Single descriptor set. Descriptor set contains "
+ << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
+ (m_shaderInterface == SHADER_INPUT_MULTIPLE_DESCRIPTORS) ? "two" :
+ (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
+ (const char*)DE_NULL)
+ << " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
+ << "Image view type is " << vk::getImageViewTypeName(m_viewType) << "\n";
+
+ if (m_baseMipLevel)
+ msg << "Image view base mip level = " << m_baseMipLevel << "\n";
+ if (m_baseArraySlice)
+ msg << "Image view base array slice = " << m_baseArraySlice << "\n";
+
+ for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
+ {
+ msg << "Test sample " << resultNdx << ": fetch at position " << m_images.getFetchPos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx);
+
+ if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
+ {
+ const int srcResourceNdx = (resultNdx % 2); // ABAB source
+ msg << " from descriptor " << srcResourceNdx;
+ }
+
+ msg << "\n";
+ }
+
+ m_context.getTestContext().getLog()
+ << tcu::TestLog::Message
+ << msg.str()
+ << tcu::TestLog::EndMessage;
+}
+
+tcu::TestStatus ImageFetchComputeInstance::testResourceAccess (void)
+{
+ const vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout (createDescriptorSetLayout());
+ const vk::Unique<vk::VkDescriptorPool> descriptorPool (createDescriptorPool());
+ const vk::Unique<vk::VkDescriptorSet> descriptorSet (createDescriptorSet(*descriptorPool, *descriptorSetLayout));
+ const ComputePipeline pipeline (m_vki, m_device, m_context.getBinaryCollection(), 1, &descriptorSetLayout.get());
+
+ const vk::VkDescriptorSet descriptorSets[] = { *descriptorSet };
+ const int numDescriptorSets = DE_LENGTH_OF_ARRAY(descriptorSets);
+ const deUint32* const dynamicOffsets = DE_NULL;
+ const int numDynamicOffsets = 0;
+ const void* const* preBarriers = DE_NULL;
+ const int numPreBarriers = 0;
+ const void* const postBarriers[] = { m_result.getResultReadBarrier() };
+ const int numPostBarriers = DE_LENGTH_OF_ARRAY(postBarriers);
+
+ const ComputeCommand compute (m_vki,
+ m_device,
+ pipeline.getPipeline(),
+ pipeline.getPipelineLayout(),
+ tcu::UVec3(4, 1, 1),
+ numDescriptorSets, descriptorSets,
+ numDynamicOffsets, dynamicOffsets,
+ numPreBarriers, preBarriers,
+ numPostBarriers, postBarriers);
+
+ tcu::Vec4 results[4];
+ bool anyResultSet = false;
+ bool allResultsOk = true;
+
+ compute.submitAndWait(m_queueFamilyIndex, m_queue);
+ m_result.readResultContentsTo(&results);
+
+ // verify
+ for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
+ {
+ const tcu::Vec4 result = results[resultNdx];
+ const tcu::Vec4 reference = m_images.fetchImageValue(resultNdx);
+ const tcu::Vec4 conversionThreshold = tcu::Vec4(1.0f / 255.0f);
+
+ if (result != tcu::Vec4(-1.0f))
+ anyResultSet = true;
+
+ if (tcu::boolAny(tcu::greaterThan(tcu::abs(result - reference), conversionThreshold)))
+ {
+ allResultsOk = false;
+
+ m_context.getTestContext().getLog()
+ << tcu::TestLog::Message
+ << "Test sample " << resultNdx << ": Expected " << reference << ", got " << result
+ << tcu::TestLog::EndMessage;
+ }
+ }
+
+ // read back and verify
+ if (allResultsOk)
+ return tcu::TestStatus::pass("Pass");
+ else if (anyResultSet)
+ return tcu::TestStatus::fail("Invalid result values");
+ else
+ {
+ m_context.getTestContext().getLog()
+ << tcu::TestLog::Message
+ << "Result buffer was not written to."
+ << tcu::TestLog::EndMessage;
+ return tcu::TestStatus::fail("Result buffer was not written to");
+ }
+}
+
+class ImageSampleInstanceImages : private ImageInstanceImages
+{
+public:
+ ImageSampleInstanceImages (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ deUint32 queueFamilyIndex,
+ vk::VkQueue queue,
+ vk::Allocator& allocator,
+ vk::VkDescriptorType descriptorType,
+ ShaderInputInterface shaderInterface,
+ vk::VkImageViewType viewType,
+ deUint32 baseMipLevel,
+ deUint32 baseArraySlice,
+ bool immutable);
+
+ static tcu::Vec4 getSamplePos (vk::VkImageViewType viewType, deUint32 baseMipLevel, deUint32 baseArraySlice, int samplePosNdx);
+ tcu::Vec4 fetchSampleValue (int samplePosNdx) const;
+
+ inline vk::VkImageView getImageViewA (void) const { return *m_imageViewA; }
+ inline vk::VkImageView getImageViewB (void) const { return *m_imageViewB; }
+ inline vk::VkSampler getSamplerA (void) const { return *m_samplerA; }
+ inline vk::VkSampler getSamplerB (void) const { return *m_samplerB; }
+ inline bool isImmutable (void) const { return m_isImmutable; }
+
+private:
+ static int getNumImages (vk::VkDescriptorType descriptorType, ShaderInputInterface shaderInterface);
+ static tcu::Sampler createRefSampler (bool isFirst);
+ static vk::Move<vk::VkSampler> createSampler (const vk::DeviceInterface& vki, vk::VkDevice device, const tcu::Sampler& sampler, const tcu::TextureFormat& format);
+
+ static tcu::Texture1DArrayView getRef1DView (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage);
+ static tcu::Texture2DArrayView getRef2DView (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage);
+ static tcu::Texture3DView getRef3DView (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage);
+ static tcu::TextureCubeArrayView getRefCubeView (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage);
+
+ const vk::VkDescriptorType m_descriptorType;
+ const ShaderInputInterface m_shaderInterface;
+ const bool m_isImmutable;
+
+ const tcu::Sampler m_refSamplerA;
+ const tcu::Sampler m_refSamplerB;
+ const vk::Unique<vk::VkSampler> m_samplerA;
+ const vk::Unique<vk::VkSampler> m_samplerB;
+};
+
+ImageSampleInstanceImages::ImageSampleInstanceImages (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ deUint32 queueFamilyIndex,
+ vk::VkQueue queue,
+ vk::Allocator& allocator,
+ vk::VkDescriptorType descriptorType,
+ ShaderInputInterface shaderInterface,
+ vk::VkImageViewType viewType,
+ deUint32 baseMipLevel,
+ deUint32 baseArraySlice,
+ bool immutable)
+ : ImageInstanceImages (vki,
+ device,
+ queueFamilyIndex,
+ queue,
+ allocator,
+ descriptorType,
+ viewType,
+ getNumImages(descriptorType, shaderInterface),
+ baseMipLevel,
+ baseArraySlice)
+ , m_descriptorType (descriptorType)
+ , m_shaderInterface (shaderInterface)
+ , m_isImmutable (immutable)
+ , m_refSamplerA (createRefSampler(true))
+ , m_refSamplerB (createRefSampler(false))
+ , m_samplerA (createSampler(vki, device, m_refSamplerA, m_imageFormat))
+ , m_samplerB ((getInterfaceNumResources(m_shaderInterface) == 1u)
+ ? vk::Move<vk::VkSampler>()
+ : createSampler(vki, device, m_refSamplerB, m_imageFormat))
+{
+}
+
+tcu::Vec4 ImageSampleInstanceImages::getSamplePos (vk::VkImageViewType viewType, deUint32 baseMipLevel, deUint32 baseArraySlice, int samplePosNdx)
+{
+ DE_ASSERT(de::inBounds(samplePosNdx, 0, 4));
+
+ const deUint32 imageSize = (deUint32)IMAGE_SIZE >> baseMipLevel;
+ const deUint32 arraySize = isImageViewTypeArray(viewType) ? ARRAY_SIZE - baseArraySlice : 1;
+
+ // choose arbitrary values that are not ambiguous with NEAREST filtering
+
+ switch (viewType)
+ {
+ case vk::VK_IMAGE_VIEW_TYPE_1D:
+ case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY:
+ case vk::VK_IMAGE_VIEW_TYPE_2D:
+ case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY:
+ case vk::VK_IMAGE_VIEW_TYPE_3D:
+ {
+ const tcu::Vec3 coords[4] =
+ {
+ tcu::Vec3(0.75f,
+ 0.5f,
+ (float)(12u % imageSize) + 0.25f),
+
+ tcu::Vec3((float)(23u % imageSize) + 0.25f,
+ (float)(73u % imageSize) + 0.5f,
+ (float)(16u % imageSize) + 0.5f + (float)imageSize),
+
+ tcu::Vec3(-(float)(43u % imageSize) + 0.25f,
+ (float)(84u % imageSize) + 0.5f + (float)imageSize,
+ (float)(117u % imageSize) + 0.75f),
+
+ tcu::Vec3((float)imageSize + 0.5f,
+ (float)(75u % imageSize) + 0.25f,
+ (float)(83u % imageSize) + 0.25f + (float)imageSize),
+ };
+ const deUint32 slices[4] =
+ {
+ 0u % arraySize,
+ 4u % arraySize,
+ 9u % arraySize,
+ 2u % arraySize,
+ };
+
+ if (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)
+ return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize,
+ (float)slices[samplePosNdx],
+ 0.0f,
+ 0.0f);
+ else if (viewType == vk::VK_IMAGE_VIEW_TYPE_2D || viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY)
+ return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize,
+ coords[samplePosNdx].y() / (float)imageSize,
+ (float)slices[samplePosNdx],
+ 0.0f);
+ else if (viewType == vk::VK_IMAGE_VIEW_TYPE_3D)
+ return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize,
+ coords[samplePosNdx].y() / (float)imageSize,
+ coords[samplePosNdx].z() / (float)imageSize,
+ 0.0f);
+ else
+ {
+ DE_FATAL("Impossible");
+ return tcu::Vec4();
+ }
+ }
+
+ case vk::VK_IMAGE_VIEW_TYPE_CUBE:
+ case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
+ {
+ // \note these values are in [0, texSize]*3 space for convenience
+ const tcu::Vec3 coords[4] =
+ {
+ tcu::Vec3(0.75f,
+ 0.5f,
+ (float)imageSize),
+
+ tcu::Vec3((float)(13u % imageSize) + 0.25f,
+ 0.0f,
+ (float)(16u % imageSize) + 0.5f),
+
+ tcu::Vec3(0.0f,
+ (float)(84u % imageSize) + 0.5f,
+ (float)(10u % imageSize) + 0.75f),
+
+ tcu::Vec3((float)imageSize,
+ (float)(75u % imageSize) + 0.25f,
+ (float)(83u % imageSize) + 0.75f),
+ };
+ const deUint32 slices[4] =
+ {
+ 1u % arraySize,
+ 2u % arraySize,
+ 9u % arraySize,
+ 5u % arraySize,
+ };
+
+ DE_ASSERT(de::inRange(coords[samplePosNdx].x(), 0.0f, (float)imageSize));
+ DE_ASSERT(de::inRange(coords[samplePosNdx].y(), 0.0f, (float)imageSize));
+ DE_ASSERT(de::inRange(coords[samplePosNdx].z(), 0.0f, (float)imageSize));
+
+ // map to [-1, 1]*3 space
+ return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize * 2.0f - 1.0f,
+ coords[samplePosNdx].y() / (float)imageSize * 2.0f - 1.0f,
+ coords[samplePosNdx].z() / (float)imageSize * 2.0f - 1.0f,
+ (float)slices[samplePosNdx]);
+ }
+
+ default:
+ DE_FATAL("Impossible");
+ return tcu::Vec4();
+ }
+}
+
+tcu::Vec4 ImageSampleInstanceImages::fetchSampleValue (int samplePosNdx) const
+{
+ DE_ASSERT(de::inBounds(samplePosNdx, 0, 4));
+
+ // texture order is ABAB
+ const bool isSamplerCase = (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER);
+ const tcu::TextureLevelPyramid& sampleSrcA = m_sourceImageA;
+ const tcu::TextureLevelPyramid& sampleSrcB = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? (m_sourceImageA) : (m_sourceImageB);
+ const tcu::TextureLevelPyramid& sampleSrc = (isSamplerCase) ? (sampleSrcA) : ((samplePosNdx % 2) == 0) ? (sampleSrcA) : (sampleSrcB);
+
+ // sampler order is ABAB
+ const tcu::Sampler& samplerA = m_refSamplerA;
+ const tcu::Sampler& samplerB = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? (m_refSamplerA) : (m_refSamplerB);
+ const tcu::Sampler& sampler = ((samplePosNdx % 2) == 0) ? (samplerA) : (samplerB);
+
+ const tcu::Vec4 samplePos = getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, samplePosNdx);
+ const float lod = 0.0f;
+ std::vector<tcu::ConstPixelBufferAccess> levelStorage;
+
+ switch (m_viewType)
+ {
+ case vk::VK_IMAGE_VIEW_TYPE_1D:
+ case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY: return getRef1DView(sampleSrc, m_baseMipLevel, m_baseArraySlice, &levelStorage).sample(sampler, samplePos.x(), samplePos.y(), lod);
+ case vk::VK_IMAGE_VIEW_TYPE_2D:
+ case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY: return getRef2DView(sampleSrc, m_baseMipLevel, m_baseArraySlice, &levelStorage).sample(sampler, samplePos.x(), samplePos.y(), samplePos.z(), lod);
+ case vk::VK_IMAGE_VIEW_TYPE_3D: return getRef3DView(sampleSrc, m_baseMipLevel, m_baseArraySlice, &levelStorage).sample(sampler, samplePos.x(), samplePos.y(), samplePos.z(), lod);
+ case vk::VK_IMAGE_VIEW_TYPE_CUBE:
+ case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: return getRefCubeView(sampleSrc, m_baseMipLevel, m_baseArraySlice, &levelStorage).sample(sampler, samplePos.x(), samplePos.y(), samplePos.z(), samplePos.w(), lod);
+
+ default:
+ {
+ DE_FATAL("Impossible");
+ return tcu::Vec4();
+ }
+ }
+}
+
+int ImageSampleInstanceImages::getNumImages (vk::VkDescriptorType descriptorType, ShaderInputInterface shaderInterface)
+{
+ // If we are testing separate samplers, just one image is enough
+ if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
+ return 1;
+ else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
+ {
+ // combined: numImages == numSamplers
+ return getInterfaceNumResources(shaderInterface);
+ }
+ else
+ {
+ DE_FATAL("Impossible");
+ return 0;
+ }
+}
+
+tcu::Sampler ImageSampleInstanceImages::createRefSampler (bool isFirst)
+{
+ if (isFirst)
+ {
+ // linear, wrapping
+ return tcu::Sampler(tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::LINEAR, tcu::Sampler::LINEAR);
+ }
+ else
+ {
+ // nearest, clamping
+ return tcu::Sampler(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::NEAREST, tcu::Sampler::NEAREST);
+ }
+}
+
+vk::Move<vk::VkSampler> ImageSampleInstanceImages::createSampler (const vk::DeviceInterface& vki, vk::VkDevice device, const tcu::Sampler& sampler, const tcu::TextureFormat& format)
+{
+ const bool compareEnabled = (sampler.compare != tcu::Sampler::COMPAREMODE_NONE);
+ const vk::VkCompareOp compareOp = (compareEnabled) ? (vk::mapCompareMode(sampler.compare)) : (vk::VK_COMPARE_OP_ALWAYS);
+ const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(format.type);
+ const bool isIntTexture = channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER || channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER;
+ const vk::VkBorderColor borderColor = (isIntTexture) ? (vk::VK_BORDER_COLOR_INT_OPAQUE_WHITE) : (vk::VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE);
+ const vk::VkSamplerCreateInfo createInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
+ DE_NULL,
+ (vk::VkSamplerCreateFlags)0,
+ vk::mapFilterMode(sampler.magFilter), // magFilter
+ vk::mapFilterMode(sampler.minFilter), // minFilter
+ vk::mapMipmapMode(sampler.minFilter), // mipMode
+ vk::mapWrapMode(sampler.wrapS), // addressU
+ vk::mapWrapMode(sampler.wrapT), // addressV
+ vk::mapWrapMode(sampler.wrapR), // addressW
+ 0.0f, // mipLodBias
+ 1, // maxAnisotropy
+ (compareEnabled ? vk::VK_TRUE : vk::VK_FALSE), // compareEnable
+ compareOp, // compareOp
+ 0.0f, // minLod
+ 0.0f, // maxLod
+ borderColor, // borderColor
+ vk::VK_FALSE, // unnormalizedCoords
+ };
+ return vk::createSampler(vki, device, &createInfo);
+}
+
+tcu::Texture1DArrayView ImageSampleInstanceImages::getRef1DView (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage)
+{
+ DE_ASSERT(levelStorage->empty());
+
+ const deUint32 numSlices = (deUint32)source.getLevel(0).getHeight();
+ const deUint32 numLevels = (deUint32)source.getNumLevels();
+
+ // cut pyramid from baseMipLevel
+ for (deUint32 level = baseMipLevel; level < numLevels; ++level)
+ {
+ // cut levels from baseArraySlice
+ const tcu::ConstPixelBufferAccess wholeLevel = source.getLevel(level);
+ const tcu::ConstPixelBufferAccess cutLevel = tcu::getSubregion(wholeLevel, 0, baseArraySlice, wholeLevel.getWidth(), numSlices - baseArraySlice);
+ levelStorage->push_back(cutLevel);
+ }
+
+ return tcu::Texture1DArrayView((int)levelStorage->size(), &levelStorage->front());
+}
+
+tcu::Texture2DArrayView ImageSampleInstanceImages::getRef2DView (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage)
+{
+ DE_ASSERT(levelStorage->empty());
+
+ const deUint32 numSlices = (deUint32)source.getLevel(0).getDepth();
+ const deUint32 numLevels = (deUint32)source.getNumLevels();
+
+ // cut pyramid from baseMipLevel
+ for (deUint32 level = baseMipLevel; level < numLevels; ++level)
+ {
+ // cut levels from baseArraySlice
+ const tcu::ConstPixelBufferAccess wholeLevel = source.getLevel(level);
+ const tcu::ConstPixelBufferAccess cutLevel = tcu::getSubregion(wholeLevel, 0, 0, baseArraySlice, wholeLevel.getWidth(), wholeLevel.getHeight(), numSlices - baseArraySlice);
+ levelStorage->push_back(cutLevel);
+ }
+
+ return tcu::Texture2DArrayView((int)levelStorage->size(), &levelStorage->front());
+}
+
+tcu::Texture3DView ImageSampleInstanceImages::getRef3DView (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage)
+{
+ DE_ASSERT(levelStorage->empty());
+ DE_ASSERT(baseArraySlice == 0);
+ DE_UNREF(baseArraySlice);
+
+ const deUint32 numLevels = (deUint32)source.getNumLevels();
+
+ // cut pyramid from baseMipLevel
+ for (deUint32 level = baseMipLevel; level < numLevels; ++level)
+ levelStorage->push_back(source.getLevel(level));
+
+ return tcu::Texture3DView((int)levelStorage->size(), &levelStorage->front());
+}
+
+tcu::TextureCubeArrayView ImageSampleInstanceImages::getRefCubeView (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage)
+{
+ DE_ASSERT(levelStorage->empty());
+
+ const deUint32 numSlices = (deUint32)source.getLevel(0).getDepth() / 6;
+ const deUint32 numLevels = (deUint32)source.getNumLevels();
+
+ // cut pyramid from baseMipLevel
+ for (deUint32 level = baseMipLevel; level < numLevels; ++level)
+ {
+ // cut levels from baseArraySlice
+ const tcu::ConstPixelBufferAccess wholeLevel = source.getLevel(level);
+ const tcu::ConstPixelBufferAccess cutLevel = tcu::getSubregion(wholeLevel, 0, 0, baseArraySlice * 6, wholeLevel.getWidth(), wholeLevel.getHeight(), (numSlices - baseArraySlice) * 6);
+ levelStorage->push_back(cutLevel);
+ }
+
+ return tcu::TextureCubeArrayView((int)levelStorage->size(), &levelStorage->front());
+}
+
+class ImageSampleRenderInstance : public SingleCmdRenderInstance
+{
+public:
+ ImageSampleRenderInstance (vkt::Context& context,
+ bool isPrimaryCmdBuf,
+ vk::VkDescriptorType descriptorType,
+ vk::VkShaderStageFlags stageFlags,
+ ShaderInputInterface shaderInterface,
+ vk::VkImageViewType viewType,
+ deUint32 baseMipLevel,
+ deUint32 baseArraySlice,
+ bool isImmutable);
+
+private:
+ static vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::VkDescriptorType descriptorType,
+ ShaderInputInterface shaderInterface,
+ vk::VkShaderStageFlags stageFlags,
+ const ImageSampleInstanceImages& images);
+
+ static vk::Move<vk::VkPipelineLayout> createPipelineLayout (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::VkDescriptorSetLayout descriptorSetLayout);
+
+ static vk::Move<vk::VkDescriptorPool> createDescriptorPool (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::VkDescriptorType descriptorType,
+ ShaderInputInterface shaderInterface,
+ bool isImmutable);
+
+ static vk::Move<vk::VkDescriptorSet> createDescriptorSet (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::VkDescriptorType descriptorType,
+ ShaderInputInterface shaderInterface,
+ vk::VkDescriptorSetLayout layout,
+ vk::VkDescriptorPool pool,
+ bool isImmutable,
+ const ImageSampleInstanceImages& images);
+
+ static void writeSamplerDescriptorSet (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ ShaderInputInterface shaderInterface,
+ bool isImmutable,
+ const ImageSampleInstanceImages& images,
+ vk::VkDescriptorSet descriptorSet);
+
+ static void writeImageSamplerDescriptorSet (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ ShaderInputInterface shaderInterface,
+ bool isImmutable,
+ const ImageSampleInstanceImages& images,
+ vk::VkDescriptorSet descriptorSet);
+
+ void logTestPlan (void) const;
+ vk::VkPipelineLayout getPipelineLayout (void) const;
+ void writeDrawCmdBuffer (vk::VkCommandBuffer cmd) const;
+ tcu::TestStatus verifyResultImage (const tcu::ConstPixelBufferAccess& result) const;
+
+ enum
+ {
+ RENDER_SIZE = 128,
+ };
+
+ const vk::VkDescriptorType m_descriptorType;
+ const vk::VkShaderStageFlags m_stageFlags;
+ const ShaderInputInterface m_shaderInterface;
+ const vk::VkImageViewType m_viewType;
+ const deUint32 m_baseMipLevel;
+ const deUint32 m_baseArraySlice;
+
+ const ImageSampleInstanceImages m_images;
+ const vk::Unique<vk::VkDescriptorSetLayout> m_descriptorSetLayout;
+ const vk::Unique<vk::VkPipelineLayout> m_pipelineLayout;
+ const vk::Unique<vk::VkDescriptorPool> m_descriptorPool;
+ const vk::Unique<vk::VkDescriptorSet> m_descriptorSet;
+};
+
+ImageSampleRenderInstance::ImageSampleRenderInstance (vkt::Context& context,
+ bool isPrimaryCmdBuf,
+ vk::VkDescriptorType descriptorType,
+ vk::VkShaderStageFlags stageFlags,
+ ShaderInputInterface shaderInterface,
+ vk::VkImageViewType viewType,
+ deUint32 baseMipLevel,
+ deUint32 baseArraySlice,
+ bool isImmutable)
+ : SingleCmdRenderInstance (context, isPrimaryCmdBuf, tcu::UVec2(RENDER_SIZE, RENDER_SIZE))
+ , m_descriptorType (descriptorType)
+ , m_stageFlags (stageFlags)
+ , m_shaderInterface (shaderInterface)
+ , m_viewType (viewType)
+ , m_baseMipLevel (baseMipLevel)
+ , m_baseArraySlice (baseArraySlice)
+ , m_images (m_vki, m_device, m_queueFamilyIndex, m_queue, m_allocator, m_descriptorType, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice, isImmutable)
+ , m_descriptorSetLayout (createDescriptorSetLayout(m_vki, m_device, m_descriptorType, m_shaderInterface, m_stageFlags, m_images))
+ , m_pipelineLayout (createPipelineLayout(m_vki, m_device, *m_descriptorSetLayout))
+ , m_descriptorPool (createDescriptorPool(m_vki, m_device, m_descriptorType, m_shaderInterface, isImmutable))
+ , m_descriptorSet (createDescriptorSet(m_vki, m_device, m_descriptorType, m_shaderInterface, *m_descriptorSetLayout, *m_descriptorPool, isImmutable, m_images))
+{
+}
+
+vk::Move<vk::VkDescriptorSetLayout> ImageSampleRenderInstance::createDescriptorSetLayout (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::VkDescriptorType descriptorType,
+ ShaderInputInterface shaderInterface,
+ vk::VkShaderStageFlags stageFlags,
+ const ImageSampleInstanceImages& images)
+{
+ const vk::VkSampler samplers[2] =
+ {
+ images.getSamplerA(),
+ images.getSamplerB(),
+ };
+
+ vk::DescriptorSetLayoutBuilder builder;
+
+ // with samplers, separate texture at binding 0
+ if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
+ builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags);
+
+ // (combined)samplers follow
+ switch (shaderInterface)
+ {
+ case SHADER_INPUT_SINGLE_DESCRIPTOR:
+ builder.addSingleSamplerBinding(descriptorType, stageFlags, (images.isImmutable()) ? (&samplers[0]) : (DE_NULL));
+ break;
+
+ case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
+ builder.addSingleSamplerBinding(descriptorType, stageFlags, (images.isImmutable()) ? (&samplers[0]) : (DE_NULL));
+ builder.addSingleSamplerBinding(descriptorType, stageFlags, (images.isImmutable()) ? (&samplers[1]) : (DE_NULL));
+ break;
+
+ case SHADER_INPUT_DESCRIPTOR_ARRAY:
+ builder.addArraySamplerBinding(descriptorType, 2u, stageFlags, (images.isImmutable()) ? (samplers) : (DE_NULL));
+ break;
+
+ default:
+ DE_FATAL("Impossible");
+ }
+
+ return builder.build(vki, device);
+}
+
+vk::Move<vk::VkPipelineLayout> ImageSampleRenderInstance::createPipelineLayout (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::VkDescriptorSetLayout descriptorSetLayout)
+{
+ const vk::VkPipelineLayoutCreateInfo createInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
+ DE_NULL,
+ (vk::VkPipelineLayoutCreateFlags)0,
+ 1, // descriptorSetCount
+ &descriptorSetLayout, // pSetLayouts
+ 0u, // pushConstantRangeCount
+ DE_NULL, // pPushConstantRanges
+ };
+ return vk::createPipelineLayout(vki, device, &createInfo);
+}
+
+vk::Move<vk::VkDescriptorPool> ImageSampleRenderInstance::createDescriptorPool (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::VkDescriptorType descriptorType,
+ ShaderInputInterface shaderInterface,
+ bool isImmutable)
+{
+ vk::DescriptorPoolBuilder builder;
+
+ if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
+ {
+ // separate samplers need image to sample
+ builder.addType(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
+
+ // samplers needed only if they are specified in the descriptor set
+ if (!isImmutable)
+ builder.addType(vk::VK_DESCRIPTOR_TYPE_SAMPLER, getInterfaceNumResources(shaderInterface));
+ }
+ else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
+ {
+ // combined image samplers
+ builder.addType(vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, getInterfaceNumResources(shaderInterface));
+ }
+ else
+ DE_FATAL("Impossible");
+
+ return builder.build(vki, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
+}
+
+vk::Move<vk::VkDescriptorSet> ImageSampleRenderInstance::createDescriptorSet (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::VkDescriptorType descriptorType,
+ ShaderInputInterface shaderInterface,
+ vk::VkDescriptorSetLayout layout,
+ vk::VkDescriptorPool pool,
+ bool isImmutable,
+ const ImageSampleInstanceImages& images)
+{
+ const vk::VkDescriptorSetAllocateInfo allocInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+ DE_NULL,
+ pool,
+ 1u,
+ &layout
+ };
+
+ vk::Move<vk::VkDescriptorSet> descriptorSet = allocateDescriptorSet(vki, device, &allocInfo);
+
+ if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
+ writeSamplerDescriptorSet(vki, device, shaderInterface, isImmutable, images, *descriptorSet);
+ else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
+ writeImageSamplerDescriptorSet(vki, device, shaderInterface, isImmutable, images, *descriptorSet);
+ else
+ DE_FATAL("Impossible");
+
+ return descriptorSet;
+}
+
+void ImageSampleRenderInstance::writeSamplerDescriptorSet (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ ShaderInputInterface shaderInterface,
+ bool isImmutable,
+ const ImageSampleInstanceImages& images,
+ vk::VkDescriptorSet descriptorSet)
+{
+ const vk::VkDescriptorImageInfo imageInfo = makeDescriptorImageInfo(images.getImageViewA(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
+ const vk::VkDescriptorImageInfo samplersInfos[2] =
+ {
+ makeDescriptorImageInfo(images.getSamplerA()),
+ makeDescriptorImageInfo(images.getSamplerB()),
+ };
+
+ vk::DescriptorSetUpdateBuilder builder;
+
+ // stand alone texture
+ builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &imageInfo);
+
+ // samplers
+ if (!isImmutable)
+ {
+ switch (shaderInterface)
+ {
+ case SHADER_INPUT_SINGLE_DESCRIPTOR:
+ builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
+ break;
+
+ case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
+ builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
+ builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[1]);
+ break;
+
+ case SHADER_INPUT_DESCRIPTOR_ARRAY:
+ builder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, 2u, samplersInfos);
+ break;
+
+ default:
+ DE_FATAL("Impossible");
+ }
+ }
+
+ builder.update(vki, device);
+}
+
+void ImageSampleRenderInstance::writeImageSamplerDescriptorSet (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ ShaderInputInterface shaderInterface,
+ bool isImmutable,
+ const ImageSampleInstanceImages& images,
+ vk::VkDescriptorSet descriptorSet)
+{
+ const vk::VkSampler samplers[2] =
+ {
+ (isImmutable) ? (0) : (images.getSamplerA()),
+ (isImmutable) ? (0) : (images.getSamplerB()),
+ };
+ const vk::VkDescriptorImageInfo imageSamplers[2] =
+ {
+ vk::makeDescriptorImageInfo(samplers[0], images.getImageViewA(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
+ vk::makeDescriptorImageInfo(samplers[1], images.getImageViewB(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
+ };
+
+ vk::DescriptorSetUpdateBuilder builder;
+
+ // combined image samplers
+ switch (shaderInterface)
+ {
+ case SHADER_INPUT_SINGLE_DESCRIPTOR:
+ builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
+ break;
+
+ case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
+ builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
+ builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[1]);
+ break;
+
+ case SHADER_INPUT_DESCRIPTOR_ARRAY:
+ builder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2u, imageSamplers);
+ break;
+
+ default:
+ DE_FATAL("Impossible");
+ }
+
+ builder.update(vki, device);
+}
+
+void ImageSampleRenderInstance::logTestPlan (void) const
+{
+ std::ostringstream msg;
+
+ msg << "Rendering 2x2 grid.\n";
+
+ if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
+ {
+ msg << "Single descriptor set. Descriptor set contains "
+ << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
+ (m_shaderInterface == SHADER_INPUT_MULTIPLE_DESCRIPTORS) ? "two" :
+ (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
+ (const char*)DE_NULL)
+ << " VK_DESCRIPTOR_TYPE_SAMPLER descriptor(s) and a single texture.\n";
+ }
+ else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
+ {
+ msg << "Single descriptor set. Descriptor set contains "
+ << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
+ (m_shaderInterface == SHADER_INPUT_MULTIPLE_DESCRIPTORS) ? "two" :
+ (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
+ (const char*)DE_NULL)
+ << " VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER descriptor(s).\n";
+ }
+ else
+ DE_FATAL("Impossible");
+
+ msg << "Image view type is " << vk::getImageViewTypeName(m_viewType) << "\n";
+
+ if (m_baseMipLevel)
+ msg << "Image view base mip level = " << m_baseMipLevel << "\n";
+ if (m_baseArraySlice)
+ msg << "Image view base array slice = " << m_baseArraySlice << "\n";
+
+ if (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)
+ msg << "Sampler mode is LINEAR, with WRAP\n";
+ else
+ msg << "Sampler 0 mode is LINEAR, with WRAP\nSampler 1 mode is NEAREST with CLAMP\n";
+
+ if (m_stageFlags == 0u)
+ {
+ msg << "Descriptors are not accessed in any shader stage.\n";
+ }
+ else
+ {
+ msg << "Color in each cell is fetched using the descriptor(s):\n";
+
+ for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
+ {
+ msg << "Test sample " << resultNdx << ": sample at position " << m_images.getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx);
+
+ if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
+ {
+ const int srcResourceNdx = (resultNdx % 2); // ABAB source
+
+ if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
+ msg << " using sampler " << srcResourceNdx;
+ else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
+ msg << " from combined image sampler " << srcResourceNdx;
+ else
+ DE_FATAL("Impossible");
+ }
+ msg << "\n";
+ }
+
+ msg << "Descriptors are accessed in {"
+ << (((m_stageFlags & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0) ? (" vertex") : (""))
+ << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0) ? (" tess_control") : (""))
+ << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0) ? (" tess_evaluation") : (""))
+ << (((m_stageFlags & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0) ? (" geometry") : (""))
+ << (((m_stageFlags & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0) ? (" fragment") : (""))
+ << " } stages.";
+ }
+
+ m_context.getTestContext().getLog()
+ << tcu::TestLog::Message
+ << msg.str()
+ << tcu::TestLog::EndMessage;
+}
+
+vk::VkPipelineLayout ImageSampleRenderInstance::getPipelineLayout (void) const
+{
+ return *m_pipelineLayout;
+}
+
+void ImageSampleRenderInstance::writeDrawCmdBuffer (vk::VkCommandBuffer cmd) const
+{
+ m_vki.cmdBindDescriptorSets(cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, getPipelineLayout(), 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
+ m_vki.cmdDraw(cmd, 6u * 4u, 1u, 0u, 0u); // render four quads (two separate triangles)
+}
+
+tcu::TestStatus ImageSampleRenderInstance::verifyResultImage (const tcu::ConstPixelBufferAccess& result) const
+{
+ const tcu::Vec4 green (0.0f, 1.0f, 0.0f, 1.0f);
+ const tcu::Vec4 yellow (1.0f, 1.0f, 0.0f, 1.0f);
+ const bool doFetch = (m_stageFlags != 0u); // no active stages? Then don't fetch
+ const tcu::Vec4 sample0 = (!doFetch) ? (yellow) : (m_images.fetchSampleValue(0));
+ const tcu::Vec4 sample1 = (!doFetch) ? (green) : (m_images.fetchSampleValue(1));
+ const tcu::Vec4 sample2 = (!doFetch) ? (green) : (m_images.fetchSampleValue(2));
+ const tcu::Vec4 sample3 = (!doFetch) ? (yellow) : (m_images.fetchSampleValue(3));
+ const tcu::RGBA threshold = tcu::RGBA(8, 8, 8, 8); // source image is high-frequency so the threshold is quite large to tolerate sampling errors
+ tcu::Surface reference (m_targetSize.x(), m_targetSize.y());
+
+ drawQuadrantReferenceResult(reference.getAccess(), sample0, sample1, sample2, sample3);
+
+ if (!bilinearCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference.getAccess(), result, threshold, tcu::COMPARE_LOG_RESULT))
+ return tcu::TestStatus::fail("Image verification failed");
+ else
+ return tcu::TestStatus::pass("Pass");
+}
+
+class ImageSampleComputeInstance : public vkt::TestInstance
+{
+public:
+ ImageSampleComputeInstance (vkt::Context& context,
+ vk::VkDescriptorType descriptorType,
+ ShaderInputInterface shaderInterface,
+ vk::VkImageViewType viewType,
+ deUint32 baseMipLevel,
+ deUint32 baseArraySlice,
+ bool isImmutableSampler);
+
+private:
+ vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout (void) const;
+ vk::Move<vk::VkDescriptorPool> createDescriptorPool (void) const;
+ vk::Move<vk::VkDescriptorSet> createDescriptorSet (vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout) const;
+ void writeImageSamplerDescriptorSet (vk::VkDescriptorSet descriptorSet) const;
+ void writeSamplerDescriptorSet (vk::VkDescriptorSet descriptorSet) const;
+
+ tcu::TestStatus iterate (void);
+ void logTestPlan (void) const;
+ tcu::TestStatus testResourceAccess (void);
+
+ const vk::VkDescriptorType m_descriptorType;
+ const ShaderInputInterface m_shaderInterface;
+ const vk::VkImageViewType m_viewType;
+ const deUint32 m_baseMipLevel;
+ const deUint32 m_baseArraySlice;
+ const bool m_isImmutableSampler;
+
+ const vk::DeviceInterface& m_vki;
+ const vk::VkDevice m_device;
+ const vk::VkQueue m_queue;
+ const deUint32 m_queueFamilyIndex;
+ vk::Allocator& m_allocator;
+
+ const ComputeInstanceResultBuffer m_result;
+ const ImageSampleInstanceImages m_images;
+};
+
+ImageSampleComputeInstance::ImageSampleComputeInstance (Context& context,
+ vk::VkDescriptorType descriptorType,
+ ShaderInputInterface shaderInterface,
+ vk::VkImageViewType viewType,
+ deUint32 baseMipLevel,
+ deUint32 baseArraySlice,
+ bool isImmutableSampler)
+ : vkt::TestInstance (context)
+ , m_descriptorType (descriptorType)
+ , m_shaderInterface (shaderInterface)
+ , m_viewType (viewType)
+ , m_baseMipLevel (baseMipLevel)
+ , m_baseArraySlice (baseArraySlice)
+ , m_isImmutableSampler (isImmutableSampler)
+ , m_vki (context.getDeviceInterface())
+ , m_device (context.getDevice())
+ , m_queue (context.getUniversalQueue())
+ , m_queueFamilyIndex (context.getUniversalQueueFamilyIndex())
+ , m_allocator (context.getDefaultAllocator())
+ , m_result (m_vki, m_device, m_allocator)
+ , m_images (m_vki, m_device, m_queueFamilyIndex, m_queue, m_allocator, m_descriptorType, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice, isImmutableSampler)
+{
+}
+
+vk::Move<vk::VkDescriptorSetLayout> ImageSampleComputeInstance::createDescriptorSetLayout (void) const
+{
+ const vk::VkSampler samplers[2] =
+ {
+ m_images.getSamplerA(),
+ m_images.getSamplerB(),
+ };
+
+ vk::DescriptorSetLayoutBuilder builder;
+
+ // result buffer
+ builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT);
+
+ // with samplers, separate texture at binding 0
+ if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
+ builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, vk::VK_SHADER_STAGE_COMPUTE_BIT);
+
+ // (combined)samplers follow
+ switch (m_shaderInterface)
+ {
+ case SHADER_INPUT_SINGLE_DESCRIPTOR:
+ builder.addSingleSamplerBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, (m_images.isImmutable()) ? (&samplers[0]) : (DE_NULL));
+ break;
+
+ case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
+ builder.addSingleSamplerBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, (m_images.isImmutable()) ? (&samplers[0]) : (DE_NULL));
+ builder.addSingleSamplerBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, (m_images.isImmutable()) ? (&samplers[1]) : (DE_NULL));
+ break;
+
+ case SHADER_INPUT_DESCRIPTOR_ARRAY:
+ builder.addArraySamplerBinding(m_descriptorType, 2u, vk::VK_SHADER_STAGE_COMPUTE_BIT, (m_images.isImmutable()) ? (samplers) : (DE_NULL));
+ break;
+
+ default:
+ DE_FATAL("Impossible");
+ };
+
+ return builder.build(m_vki, m_device);
+}
+
+vk::Move<vk::VkDescriptorPool> ImageSampleComputeInstance::createDescriptorPool (void) const
+{
+ vk::DescriptorPoolBuilder builder;
+
+ builder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
+ builder.addType(m_descriptorType, getInterfaceNumResources(m_shaderInterface));
+
+ if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
+ builder.addType(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
+
+ return builder.build(m_vki, m_device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
+}
+
+vk::Move<vk::VkDescriptorSet> ImageSampleComputeInstance::createDescriptorSet (vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout) const
+{
+ const vk::VkDescriptorSetAllocateInfo allocInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+ DE_NULL,
+ pool,
+ 1u,
+ &layout
+ };
+
+ vk::Move<vk::VkDescriptorSet> descriptorSet = allocateDescriptorSet(m_vki, m_device, &allocInfo);
+
+ if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
+ writeSamplerDescriptorSet(*descriptorSet);
+ else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
+ writeImageSamplerDescriptorSet(*descriptorSet);
+ else
+ DE_FATAL("Impossible");
+
+ return descriptorSet;
+}
+
+void ImageSampleComputeInstance::writeSamplerDescriptorSet (vk::VkDescriptorSet descriptorSet) const
+{
+ const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
+ const vk::VkDescriptorImageInfo imageInfo = makeDescriptorImageInfo(m_images.getImageViewA(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
+ const vk::VkDescriptorImageInfo samplersInfos[2] =
+ {
+ makeDescriptorImageInfo(m_images.getSamplerA()),
+ makeDescriptorImageInfo(m_images.getSamplerB()),
+ };
+
+ vk::DescriptorSetUpdateBuilder builder;
+
+ // result
+ builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
+
+ // stand alone texture
+ builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &imageInfo);
+
+ // samplers
+ if (!m_isImmutableSampler)
+ {
+ switch (m_shaderInterface)
+ {
+ case SHADER_INPUT_SINGLE_DESCRIPTOR:
+ builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
+ break;
+
+ case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
+ builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
+ builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(3u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[1]);
+ break;
+
+ case SHADER_INPUT_DESCRIPTOR_ARRAY:
+ builder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, 2u, samplersInfos);
+ break;
+
+ default:
+ DE_FATAL("Impossible");
+ }
+ }
+
+ builder.update(m_vki, m_device);
+}
+
+void ImageSampleComputeInstance::writeImageSamplerDescriptorSet (vk::VkDescriptorSet descriptorSet) const
+{
+ const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
+ const vk::VkSampler samplers[2] =
+ {
+ (m_isImmutableSampler) ? (0) : (m_images.getSamplerA()),
+ (m_isImmutableSampler) ? (0) : (m_images.getSamplerB()),
+ };
+ const vk::VkDescriptorImageInfo imageSamplers[2] =
+ {
+ makeDescriptorImageInfo(samplers[0], m_images.getImageViewA(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
+ makeDescriptorImageInfo(samplers[1], m_images.getImageViewB(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
+ };
+
+ vk::DescriptorSetUpdateBuilder builder;
+
+ // result
+ builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
+
+ // combined image samplers
+ switch (m_shaderInterface)
+ {
+ case SHADER_INPUT_SINGLE_DESCRIPTOR:
+ builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
+ break;
+
+ case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
+ builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
+ builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[1]);
+ break;
+
+ case SHADER_INPUT_DESCRIPTOR_ARRAY:
+ builder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2u, imageSamplers);
+ break;
+
+ default:
+ DE_FATAL("Impossible");
+ }
+
+ builder.update(m_vki, m_device);
+}
+
+tcu::TestStatus ImageSampleComputeInstance::iterate (void)
+{
+ logTestPlan();
+ return testResourceAccess();
+}
+
+void ImageSampleComputeInstance::logTestPlan (void) const
+{
+ std::ostringstream msg;
+
+ msg << "Accessing resource in a compute program.\n";
+
+ if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
+ {
+ msg << "Single descriptor set. Descriptor set contains "
+ << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
+ (m_shaderInterface == SHADER_INPUT_MULTIPLE_DESCRIPTORS) ? "two" :
+ (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
+ (const char*)DE_NULL)
+ << " VK_DESCRIPTOR_TYPE_SAMPLER descriptor(s) and a single texture.\n";
+ }
+ else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
+ {
+ msg << "Single descriptor set. Descriptor set contains "
+ << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
+ (m_shaderInterface == SHADER_INPUT_MULTIPLE_DESCRIPTORS) ? "two" :
+ (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
+ (const char*)DE_NULL)
+ << " VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER descriptor(s).\n";
+ }
+ else
+ DE_FATAL("Impossible");
+
+ msg << "Image view type is " << vk::getImageViewTypeName(m_viewType) << "\n";
+
+ if (m_baseMipLevel)
+ msg << "Image view base mip level = " << m_baseMipLevel << "\n";
+ if (m_baseArraySlice)
+ msg << "Image view base array slice = " << m_baseArraySlice << "\n";
+
+ if (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)
+ msg << "Sampler mode is LINEAR, with WRAP\n";
+ else
+ msg << "Sampler 0 mode is LINEAR, with WRAP\nSampler 1 mode is NEAREST with CLAMP\n";
+
+ for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
+ {
+ msg << "Test sample " << resultNdx << ": sample at position " << m_images.getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx);
+
+ if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
+ {
+ const int srcResourceNdx = (resultNdx % 2); // ABAB source
+
+ if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
+ msg << " using sampler " << srcResourceNdx;
+ else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
+ msg << " from combined image sampler " << srcResourceNdx;
+ else
+ DE_FATAL("Impossible");
+ }
+ msg << "\n";
+ }
+
+ m_context.getTestContext().getLog()
+ << tcu::TestLog::Message
+ << msg.str()
+ << tcu::TestLog::EndMessage;
+}
+
+tcu::TestStatus ImageSampleComputeInstance::testResourceAccess (void)
+{
+ const vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout (createDescriptorSetLayout());
+ const vk::Unique<vk::VkDescriptorPool> descriptorPool (createDescriptorPool());
+ const vk::Unique<vk::VkDescriptorSet> descriptorSet (createDescriptorSet(*descriptorPool, *descriptorSetLayout));
+ const ComputePipeline pipeline (m_vki, m_device, m_context.getBinaryCollection(), 1, &descriptorSetLayout.get());
+
+ const vk::VkDescriptorSet descriptorSets[] = { *descriptorSet };
+ const int numDescriptorSets = DE_LENGTH_OF_ARRAY(descriptorSets);
+ const deUint32* const dynamicOffsets = DE_NULL;
+ const int numDynamicOffsets = 0;
+ const void* const* preBarriers = DE_NULL;
+ const int numPreBarriers = 0;
+ const void* const postBarriers[] = { m_result.getResultReadBarrier() };
+ const int numPostBarriers = DE_LENGTH_OF_ARRAY(postBarriers);
+
+ const ComputeCommand compute (m_vki,
+ m_device,
+ pipeline.getPipeline(),
+ pipeline.getPipelineLayout(),
+ tcu::UVec3(4, 1, 1),
+ numDescriptorSets, descriptorSets,
+ numDynamicOffsets, dynamicOffsets,
+ numPreBarriers, preBarriers,
+ numPostBarriers, postBarriers);
+
+ tcu::Vec4 results[4];
+ bool anyResultSet = false;
+ bool allResultsOk = true;
+
+ compute.submitAndWait(m_queueFamilyIndex, m_queue);
+ m_result.readResultContentsTo(&results);
+
+ // verify
+ for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
+ {
+ const tcu::Vec4 result = results[resultNdx];
+ const tcu::Vec4 reference = m_images.fetchSampleValue(resultNdx);
+
+ // source image is high-frequency so the threshold is quite large to tolerate sampling errors
+ const tcu::Vec4 samplingThreshold = tcu::Vec4(8.0f / 255.0f);
+
+ if (result != tcu::Vec4(-1.0f))
+ anyResultSet = true;
+
+ if (tcu::boolAny(tcu::greaterThan(tcu::abs(result - reference), samplingThreshold)))
+ {
+ allResultsOk = false;
+
+ m_context.getTestContext().getLog()
+ << tcu::TestLog::Message
+ << "Test sample " << resultNdx << ":\n"
+ << "\tSampling at " << m_images.getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx) << "\n"
+ << "\tError expected " << reference << ", got " << result
+ << tcu::TestLog::EndMessage;
+ }
+ }
+
+ // read back and verify
+ if (allResultsOk)
+ return tcu::TestStatus::pass("Pass");
+ else if (anyResultSet)
+ return tcu::TestStatus::fail("Invalid result values");
+ else
+ {
+ m_context.getTestContext().getLog()
+ << tcu::TestLog::Message
+ << "Result buffer was not written to."
+ << tcu::TestLog::EndMessage;
+ return tcu::TestStatus::fail("Result buffer was not written to");
+ }
+}
+
+class ImageDescriptorCase : public QuadrantRendederCase
+{
+public:
+ enum
+ {
+ FLAG_BASE_MIP = (1u << 1u),
+ FLAG_BASE_SLICE = (1u << 2u),
+ };
+ // enum continues where resource flags ends
+ DE_STATIC_ASSERT((deUint32)FLAG_BASE_MIP == (deUint32)RESOURCE_FLAG_LAST);
+
+ ImageDescriptorCase (tcu::TestContext& testCtx,
+ const char* name,
+ const char* description,
+ bool isPrimaryCmdBuf,
+ vk::VkDescriptorType descriptorType,
+ vk::VkShaderStageFlags exitingStages,
+ vk::VkShaderStageFlags activeStages,
+ ShaderInputInterface shaderInterface,
+ vk::VkImageViewType viewType,
+ deUint32 flags);
+
+private:
+ std::string genExtensionDeclarations (vk::VkShaderStageFlagBits stage) const;
+ std::string genResourceDeclarations (vk::VkShaderStageFlagBits stage, int numUsedBindings) const;
+ std::string genFetchCoordStr (int fetchPosNdx) const;
+ std::string genSampleCoordStr (int samplePosNdx) const;
+ std::string genResourceAccessSource (vk::VkShaderStageFlagBits stage) const;
+ std::string genNoAccessSource (void) const;
+
+ vkt::TestInstance* createInstance (vkt::Context& context) const;
+
+private:
+ const bool m_isPrimaryCmdBuf;
+ const vk::VkDescriptorType m_descriptorType;
+ const ShaderInputInterface m_shaderInterface;
+ const vk::VkImageViewType m_viewType;
+ const deUint32 m_baseMipLevel;
+ const deUint32 m_baseArraySlice;
+ const bool m_isImmutableSampler;
+};
+
+ImageDescriptorCase::ImageDescriptorCase (tcu::TestContext& testCtx,
+ const char* name,
+ const char* description,
+ bool isPrimaryCmdBuf,
+ vk::VkDescriptorType descriptorType,
+ vk::VkShaderStageFlags exitingStages,
+ vk::VkShaderStageFlags activeStages,
+ ShaderInputInterface shaderInterface,
+ vk::VkImageViewType viewType,
+ deUint32 flags)
+ : QuadrantRendederCase (testCtx, name, description,
+ // \note 1D textures are not supported in ES
+ (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? glu::GLSL_VERSION_440 : glu::GLSL_VERSION_310_ES,
+ exitingStages, activeStages)
+ , m_isPrimaryCmdBuf (isPrimaryCmdBuf)
+ , m_descriptorType (descriptorType)
+ , m_shaderInterface (shaderInterface)
+ , m_viewType (viewType)
+ , m_baseMipLevel (((flags & FLAG_BASE_MIP) != 0) ? (1u) : (0u))
+ , m_baseArraySlice (((flags & FLAG_BASE_SLICE) != 0) ? (1u) : (0u))
+ , m_isImmutableSampler ((flags & RESOURCE_FLAG_IMMUTABLE_SAMPLER) != 0)
+{
+}
+
+std::string ImageDescriptorCase::genExtensionDeclarations (vk::VkShaderStageFlagBits stage) const
+{
+ DE_UNREF(stage);
+
+ if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
+ return "#extension GL_OES_texture_cube_map_array : require\n";
+ else
+ return "";
+}
+
+std::string ImageDescriptorCase::genResourceDeclarations (vk::VkShaderStageFlagBits stage, int numUsedBindings) const
+{
+ DE_UNREF(stage);
+
+ // Vulkan-style resources are arrays implicitly, OpenGL-style are not
+ const std::string dimensionBase = (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? ("1D")
+ : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY) ? ("2D")
+ : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? ("3D")
+ : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? ("Cube")
+ : (DE_NULL);
+ const std::string dimensionArray = (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? ("1DArray")
+ : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY) ? ("2DArray")
+ : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? ("3D")
+ : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? ("CubeArray")
+ : (DE_NULL);
+ const std::string dimension = isImageViewTypeArray(m_viewType) ? dimensionArray : dimensionBase;
+
+ switch (m_shaderInterface)
+ {
+ case SHADER_INPUT_SINGLE_DESCRIPTOR:
+ {
+ switch (m_descriptorType)
+ {
+ case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
+ return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp texture" + dimension + " u_separateTexture;\n"
+ "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ") uniform highp sampler u_separateSampler;\n";
+ case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+ return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp sampler" + dimension + " u_combinedTextureSampler;\n";
+ case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
+ return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp texture" + dimensionBase + " u_separateTexture;\n";
+ case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
+ return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ", rgba8) readonly uniform highp image" + dimension + " u_image;\n";
+ default:
+ DE_FATAL("invalid descriptor");
+ return "";
+ }
+ }
+
+ case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
+ switch (m_descriptorType)
+ {
+ case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
+ return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp texture" + dimension + " u_separateTexture;\n"
+ "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ") uniform highp sampler u_separateSamplerA;\n"
+ "layout(set = 0, binding = " + de::toString(numUsedBindings+2) + ") uniform highp sampler u_separateSamplerB;\n";
+ case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+ return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp sampler" + dimension + " u_combinedTextureSamplerA;\n"
+ "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ") uniform highp sampler" + dimension + " u_combinedTextureSamplerB;\n";
+ case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
+ return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp texture" + dimensionBase + " u_separateTextureA;\n"
+ "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ") uniform highp texture" + dimensionBase + " u_separateTextureB;\n";
+ case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
+ return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ", rgba8) readonly uniform highp image" + dimension + " u_imageA;\n"
+ "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ", rgba8) readonly uniform highp image" + dimension + " u_imageB;\n";
+ default:
+ DE_FATAL("invalid descriptor");
+ return "";
+ }
+
+ case SHADER_INPUT_DESCRIPTOR_ARRAY:
+ switch (m_descriptorType)
+ {
+ case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
+ return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp texture" + dimension + " u_separateTexture;\n"
+ "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ") uniform highp sampler u_separateSampler[2];\n";
+ case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+ return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp sampler" + dimension + " u_combinedTextureSampler[2];\n";
+ case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
+ return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp texture" + dimensionBase + " u_separateTexture[2];\n";
+ case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
+ return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ", rgba8) readonly uniform highp image" + dimension + " u_image[2];\n";
+ default:
+ DE_FATAL("invalid descriptor");
+ return "";
+ }
+
+ default:
+ DE_FATAL("Impossible");
+ return "";
+ }
+}
+
+std::string ImageDescriptorCase::genFetchCoordStr (int fetchPosNdx) const
+{
+ DE_ASSERT(m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE || m_descriptorType == vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
+ const tcu::IVec3 fetchPos = ImageFetchInstanceImages::getFetchPos(m_viewType, m_baseMipLevel, m_baseArraySlice, fetchPosNdx);
+
+ if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D)
+ {
+ return de::toString(fetchPos.x());
+ }
+ else if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY || m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D)
+ {
+ std::ostringstream buf;
+ buf << "ivec2(" << fetchPos.x() << ", " << fetchPos.y() << ")";
+ return buf.str();
+ }
+ else
+ {
+ std::ostringstream buf;
+ buf << "ivec3(" << fetchPos.x() << ", " << fetchPos.y() << ", " << fetchPos.z() << ")";
+ return buf.str();
+ }
+}
+
+std::string ImageDescriptorCase::genSampleCoordStr (int samplePosNdx) const
+{
+ DE_ASSERT(m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER || m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
+ const tcu::Vec4 fetchPos = ImageSampleInstanceImages::getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, samplePosNdx);
+
+ if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D)
+ {
+ std::ostringstream buf;
+ buf << "float(" << fetchPos.x() << ")";
+ return buf.str();
+ }
+ else if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY || m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D)
+ {
+ std::ostringstream buf;
+ buf << "vec2(float(" << fetchPos.x() << "), float(" << fetchPos.y() << "))";
+ return buf.str();
+ }
+ else if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
+ {
+ std::ostringstream buf;
+ buf << "vec4(float(" << fetchPos.x() << "), float(" << fetchPos.y() << "), float(" << fetchPos.z() << "), float(" << fetchPos.w() << "))";
+ return buf.str();
+ }
+ else
+ {
+ std::ostringstream buf;
+ buf << "vec3(float(" << fetchPos.x() << "), float(" << fetchPos.y() << "), float(" << fetchPos.z() << "))";
+ return buf.str();
+ }
+}
+
+std::string ImageDescriptorCase::genResourceAccessSource (vk::VkShaderStageFlagBits stage) const
+{
+ DE_UNREF(stage);
+
+ const char* const dimension = (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D) ? ("1D")
+ : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? ("1DArray")
+ : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D) ? ("2D")
+ : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY) ? ("2DArray")
+ : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? ("3D")
+ : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE) ? ("Cube")
+ : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? ("CubeArray")
+ : (DE_NULL);
+ const char* const accessPostfixA = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? ("")
+ : (m_shaderInterface == SHADER_INPUT_MULTIPLE_DESCRIPTORS) ? ("A")
+ : (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? ("[0]")
+ : (DE_NULL);
+ const char* const accessPostfixB = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? ("")
+ : (m_shaderInterface == SHADER_INPUT_MULTIPLE_DESCRIPTORS) ? ("B")
+ : (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? ("[1]")
+ : (DE_NULL);
+
+ switch (m_descriptorType)
+ {
+ case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
+ case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+ {
+ const std::string coodStr[4] =
+ {
+ genSampleCoordStr(0),
+ genSampleCoordStr(1),
+ genSampleCoordStr(2),
+ genSampleCoordStr(3),
+ };
+ std::ostringstream buf;
+
+ if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
+ {
+ buf << " if (quadrant_id == 0)\n"
+ << " result_color = textureLod(sampler" << dimension << "(u_separateTexture, u_separateSampler" << accessPostfixA << "), " << coodStr[0] << ", 0.0);\n"
+ << " else if (quadrant_id == 1)\n"
+ << " result_color = textureLod(sampler" << dimension << "(u_separateTexture, u_separateSampler" << accessPostfixB << "), " << coodStr[1] << ", 0.0);\n"
+ << " else if (quadrant_id == 2)\n"
+ << " result_color = textureLod(sampler" << dimension << "(u_separateTexture, u_separateSampler" << accessPostfixA << "), " << coodStr[2] << ", 0.0);\n"
+ << " else\n"
+ << " result_color = textureLod(sampler" << dimension << "(u_separateTexture, u_separateSampler" << accessPostfixB << "), " << coodStr[3] << ", 0.0);\n";
+ }
+ else
+ {
+ buf << " if (quadrant_id == 0)\n"
+ << " result_color = textureLod(u_combinedTextureSampler" << accessPostfixA << ", " << coodStr[0] << ", 0.0);\n"
+ << " else if (quadrant_id == 1)\n"
+ << " result_color = textureLod(u_combinedTextureSampler" << accessPostfixB << ", " << coodStr[1] << ", 0.0);\n"
+ << " else if (quadrant_id == 2)\n"
+ << " result_color = textureLod(u_combinedTextureSampler" << accessPostfixA << ", " << coodStr[2] << ", 0.0);\n"
+ << " else\n"
+ << " result_color = textureLod(u_combinedTextureSampler" << accessPostfixB << ", " << coodStr[3] << ", 0.0);\n";
+ }
+
+ return buf.str();
+ }
+
+ case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
+ {
+ const std::string coodStr[4] =
+ {
+ genFetchCoordStr(0),
+ genFetchCoordStr(1),
+ genFetchCoordStr(2),
+ genFetchCoordStr(3),
+ };
+ std::ostringstream buf;
+
+ buf << " if (quadrant_id == 0)\n"
+ << " result_color = imageLoad(u_image" << accessPostfixA << ", " << coodStr[0] << ");\n"
+ << " else if (quadrant_id == 1)\n"
+ << " result_color = imageLoad(u_image" << accessPostfixB << ", " << coodStr[1] << ");\n"
+ << " else if (quadrant_id == 2)\n"
+ << " result_color = imageLoad(u_image" << accessPostfixA << ", " << coodStr[2] << ");\n"
+ << " else\n"
+ << " result_color = imageLoad(u_image" << accessPostfixB << ", " << coodStr[3] << ");\n";
+
+ return buf.str();
+ }
+
+ default:
+ DE_FATAL("invalid descriptor");
+ return "";
+ }
+}
+
+std::string ImageDescriptorCase::genNoAccessSource (void) const
+{
+ return " if (quadrant_id == 1 || quadrant_id == 2)\n"
+ " result_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
+ " else\n"
+ " result_color = vec4(1.0, 1.0, 0.0, 1.0);\n";
+}
+
+vkt::TestInstance* ImageDescriptorCase::createInstance (vkt::Context& context) const
+{
+ switch (m_descriptorType)
+ {
+ case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
+ case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+ if (m_exitingStages == vk::VK_SHADER_STAGE_COMPUTE_BIT)
+ {
+ DE_ASSERT(m_isPrimaryCmdBuf);
+ return new ImageSampleComputeInstance(context, m_descriptorType, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice, m_isImmutableSampler);
+ }
+ else
+ return new ImageSampleRenderInstance(context, m_isPrimaryCmdBuf, m_descriptorType, m_activeStages, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice, m_isImmutableSampler);
+
+ case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
+ case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
+ if (m_exitingStages == vk::VK_SHADER_STAGE_COMPUTE_BIT)
+ {
+ DE_ASSERT(m_isPrimaryCmdBuf);
+ return new ImageFetchComputeInstance(context, m_descriptorType, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice);
+ }
+ else
+ return new ImageFetchRenderInstance(context, m_isPrimaryCmdBuf, m_descriptorType, m_activeStages, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice);
+
+ default:
+ DE_FATAL("Impossible");
+ return DE_NULL;
+ }
+}
+
+class TexelBufferInstanceBuffers
+{
+public:
+ TexelBufferInstanceBuffers (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::Allocator& allocator,
+ vk::VkDescriptorType descriptorType,
+ int numTexelBuffers,
+ bool hasViewOffset);
+
+private:
+ static vk::Move<vk::VkBuffer> createBuffer (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::Allocator& allocator,
+ vk::VkDescriptorType descriptorType,
+ de::MovePtr<vk::Allocation> *outAllocation);
+
+ static vk::Move<vk::VkBufferView> createBufferView (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ const tcu::TextureFormat& textureFormat,
+ deUint32 offset,
+ vk::VkBuffer buffer);
+
+ static vk::VkBufferMemoryBarrier createBarrier (vk::VkDescriptorType descriptorType, vk::VkBuffer buffer);
+
+ void populateSourceBuffer (const tcu::PixelBufferAccess& access);
+ void uploadData (const vk::DeviceInterface& vki, vk::VkDevice device, const vk::Allocation& memory, const de::ArrayBuffer<deUint8>& data);
+
+public:
+ static int getFetchPos (int fetchPosNdx);
+ tcu::Vec4 fetchTexelValue (int fetchPosNdx) const;
+
+ inline int getNumTexelBuffers (void) const { return m_numTexelBuffers; }
+ const tcu::TextureFormat& getTextureFormat (void) const { return m_imageFormat; }
+ inline vk::VkBufferView getBufferViewA (void) const { return *m_bufferViewA; }
+ inline vk::VkBufferView getBufferViewB (void) const { return *m_bufferViewB; }
+ inline const void* getBufferInitBarrierA (void) const { return &m_bufferBarrierA; }
+ inline const void* getBufferInitBarrierB (void) const { return &m_bufferBarrierB; }
+
+private:
+ enum
+ {
+ BUFFER_SIZE = 512,
+ VIEW_OFFSET_VALUE = 256,
+ VIEW_DATA_SIZE = 256, //!< size in bytes
+ VIEW_WIDTH = 64, //!< size in pixels
+ };
+ enum
+ {
+ // some arbitrary points
+ SAMPLE_POINT_0 = 6,
+ SAMPLE_POINT_1 = 51,
+ SAMPLE_POINT_2 = 42,
+ SAMPLE_POINT_3 = 25,
+ };
+
+ const deUint32 m_numTexelBuffers;
+ const tcu::TextureFormat m_imageFormat;
+ const deUint32 m_viewOffset;
+
+ de::ArrayBuffer<deUint8> m_sourceBufferA;
+ de::ArrayBuffer<deUint8> m_sourceBufferB;
+ const tcu::ConstPixelBufferAccess m_sourceViewA;
+ const tcu::ConstPixelBufferAccess m_sourceViewB;
+
+ de::MovePtr<vk::Allocation> m_bufferMemoryA;
+ de::MovePtr<vk::Allocation> m_bufferMemoryB;
+ const vk::Unique<vk::VkBuffer> m_bufferA;
+ const vk::Unique<vk::VkBuffer> m_bufferB;
+ const vk::Unique<vk::VkBufferView> m_bufferViewA;
+ const vk::Unique<vk::VkBufferView> m_bufferViewB;
+ const vk::VkBufferMemoryBarrier m_bufferBarrierA;
+ const vk::VkBufferMemoryBarrier m_bufferBarrierB;
+};
+
+TexelBufferInstanceBuffers::TexelBufferInstanceBuffers (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::Allocator& allocator,
+ vk::VkDescriptorType descriptorType,
+ int numTexelBuffers,
+ bool hasViewOffset)
+ : m_numTexelBuffers (numTexelBuffers)
+ , m_imageFormat (tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)
+ , m_viewOffset ((hasViewOffset) ? ((deUint32)VIEW_OFFSET_VALUE) : (0u))
+ , m_sourceBufferA (BUFFER_SIZE)
+ , m_sourceBufferB ((numTexelBuffers == 1)
+ ? (0u)
+ : ((size_t)BUFFER_SIZE))
+ , m_sourceViewA (m_imageFormat, tcu::IVec3(VIEW_WIDTH, 1, 1), m_sourceBufferA.getElementPtr(m_viewOffset))
+ , m_sourceViewB (m_imageFormat, tcu::IVec3(VIEW_WIDTH, 1, 1), m_sourceBufferB.getElementPtr(m_viewOffset))
+ , m_bufferMemoryA (DE_NULL)
+ , m_bufferMemoryB (DE_NULL)
+ , m_bufferA (createBuffer(vki, device, allocator, descriptorType, &m_bufferMemoryA))
+ , m_bufferB ((numTexelBuffers == 1)
+ ? vk::Move<vk::VkBuffer>()
+ : createBuffer(vki, device, allocator, descriptorType, &m_bufferMemoryB))
+ , m_bufferViewA (createBufferView(vki, device, m_imageFormat, m_viewOffset, *m_bufferA))
+ , m_bufferViewB ((numTexelBuffers == 1)
+ ? vk::Move<vk::VkBufferView>()
+ : createBufferView(vki, device, m_imageFormat, m_viewOffset, *m_bufferB))
+ , m_bufferBarrierA (createBarrier(descriptorType, *m_bufferA))
+ , m_bufferBarrierB (createBarrier(descriptorType, *m_bufferB))
+{
+ DE_ASSERT(numTexelBuffers == 1 || numTexelBuffers == 2);
+ DE_ASSERT(VIEW_WIDTH * m_imageFormat.getPixelSize() == VIEW_DATA_SIZE);
+ DE_ASSERT(BUFFER_SIZE % m_imageFormat.getPixelSize() == 0);
+
+ // specify and upload
+
+ populateSourceBuffer(tcu::PixelBufferAccess(m_imageFormat, tcu::IVec3(BUFFER_SIZE / m_imageFormat.getPixelSize(), 1, 1), m_sourceBufferA.getPtr()));
+ uploadData(vki, device, *m_bufferMemoryA, m_sourceBufferA);
+
+ if (numTexelBuffers == 2)
+ {
+ populateSourceBuffer(tcu::PixelBufferAccess(m_imageFormat, tcu::IVec3(BUFFER_SIZE / m_imageFormat.getPixelSize(), 1, 1), m_sourceBufferB.getPtr()));
+ uploadData(vki, device, *m_bufferMemoryB, m_sourceBufferB);
+ }
+}
+
+vk::Move<vk::VkBuffer> TexelBufferInstanceBuffers::createBuffer (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::Allocator& allocator,
+ vk::VkDescriptorType descriptorType,
+ de::MovePtr<vk::Allocation> *outAllocation)
+{
+ const vk::VkBufferUsageFlags usage = (isUniformDescriptorType(descriptorType)) ? (vk::VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT) : (vk::VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT);
+ const vk::VkBufferCreateInfo createInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
+ DE_NULL,
+ 0u, // flags
+ (vk::VkDeviceSize)BUFFER_SIZE, // size
+ usage, // usage
+ vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
+ 0u, // queueFamilyCount
+ DE_NULL, // pQueueFamilyIndices
+ };
+ vk::Move<vk::VkBuffer> buffer (vk::createBuffer(vki, device, &createInfo));
+ de::MovePtr<vk::Allocation> allocation (allocateAndBindObjectMemory(vki, device, allocator, *buffer, vk::MemoryRequirement::HostVisible));
+
+ *outAllocation = allocation;
+ return buffer;
+}
+
+vk::Move<vk::VkBufferView> TexelBufferInstanceBuffers::createBufferView (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ const tcu::TextureFormat& textureFormat,
+ deUint32 offset,
+ vk::VkBuffer buffer)
+{
+ const vk::VkBufferViewCreateInfo createInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,
+ DE_NULL,
+ (vk::VkBufferViewCreateFlags)0,
+ buffer, // buffer
+ vk::mapTextureFormat(textureFormat), // format
+ (vk::VkDeviceSize)offset, // offset
+ (vk::VkDeviceSize)VIEW_DATA_SIZE // range
+ };
+ return vk::createBufferView(vki, device, &createInfo);
+}
+
+vk::VkBufferMemoryBarrier TexelBufferInstanceBuffers::createBarrier (vk::VkDescriptorType descriptorType, vk::VkBuffer buffer)
+{
+ const vk::VkAccessFlags inputBit = (isUniformDescriptorType(descriptorType)) ? (vk::VK_ACCESS_UNIFORM_READ_BIT) : (vk::VK_ACCESS_SHADER_READ_BIT);
+ const vk::VkBufferMemoryBarrier barrier =
+ {
+ vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
+ DE_NULL,
+ vk::VK_ACCESS_HOST_WRITE_BIT, // outputMask
+ inputBit, // inputMask
+ vk::VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
+ vk::VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex
+ buffer , // buffer
+ 0u, // offset
+ (vk::VkDeviceSize)BUFFER_SIZE // size
+ };
+ return barrier;
+}
+
+void TexelBufferInstanceBuffers::populateSourceBuffer (const tcu::PixelBufferAccess& access)
+{
+ DE_ASSERT(access.getHeight() == 1);
+ DE_ASSERT(access.getDepth() == 1);
+
+ const deInt32 width = access.getWidth();
+
+ for (int x = 0; x < width; ++x)
+ {
+ const int red = 255 * x / width; //!< gradient from 0 -> max (detects large offset errors)
+ const int green = ((x % 2 == 0) ? (127) : (0)) + ((x % 4 < 3) ? (128) : (0)); //!< 3-level M pattern (detects small offset errors)
+ const int blue = 16 * (x % 16); //!< 16-long triangle wave
+
+ DE_ASSERT(de::inRange(red, 0, 255));
+ DE_ASSERT(de::inRange(green, 0, 255));
+ DE_ASSERT(de::inRange(blue, 0, 255));
+
+ access.setPixel(tcu::IVec4(red, green, blue, 255), x, 0, 0);
+ }
+}
+
+void TexelBufferInstanceBuffers::uploadData (const vk::DeviceInterface& vki, vk::VkDevice device, const vk::Allocation& memory, const de::ArrayBuffer<deUint8>& data)
+{
+ deMemcpy(memory.getHostPtr(), data.getPtr(), data.size());
+ flushMappedMemoryRange(vki, device, memory.getMemory(), memory.getOffset(), data.size());
+}
+
+int TexelBufferInstanceBuffers::getFetchPos (int fetchPosNdx)
+{
+ static const int fetchPositions[4] =
+ {
+ SAMPLE_POINT_0,
+ SAMPLE_POINT_1,
+ SAMPLE_POINT_2,
+ SAMPLE_POINT_3,
+ };
+ return de::getSizedArrayElement<4>(fetchPositions, fetchPosNdx);
+}
+
+tcu::Vec4 TexelBufferInstanceBuffers::fetchTexelValue (int fetchPosNdx) const
+{
+ // source order is ABAB
+ const tcu::ConstPixelBufferAccess& texelSrcA = m_sourceViewA;
+ const tcu::ConstPixelBufferAccess& texelSrcB = (m_numTexelBuffers == 1) ? (m_sourceViewA) : (m_sourceViewB);
+ const tcu::ConstPixelBufferAccess& texelSrc = ((fetchPosNdx % 2) == 0) ? (texelSrcA) : (texelSrcB);
+
+ return texelSrc.getPixel(getFetchPos(fetchPosNdx), 0, 0);
+}
+
+class TexelBufferRenderInstance : public SingleCmdRenderInstance
+{
+public:
+ TexelBufferRenderInstance (vkt::Context& context,
+ bool isPrimaryCmdBuf,
+ vk::VkDescriptorType descriptorType,
+ vk::VkShaderStageFlags stageFlags,
+ ShaderInputInterface shaderInterface,
+ bool nonzeroViewOffset);
+
+private:
+ static vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::VkDescriptorType descriptorType,
+ ShaderInputInterface shaderInterface,
+ vk::VkShaderStageFlags stageFlags);
+
+ static vk::Move<vk::VkPipelineLayout> createPipelineLayout (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::VkDescriptorSetLayout descriptorSetLayout);
+
+ static vk::Move<vk::VkDescriptorPool> createDescriptorPool (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::VkDescriptorType descriptorType,
+ ShaderInputInterface shaderInterface);
+
+ static vk::Move<vk::VkDescriptorSet> createDescriptorSet (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::VkDescriptorType descriptorType,
+ ShaderInputInterface shaderInterface,
+ vk::VkDescriptorSetLayout layout,
+ vk::VkDescriptorPool pool,
+ vk::VkBufferView viewA,
+ vk::VkBufferView viewB);
+
+ void logTestPlan (void) const;
+ vk::VkPipelineLayout getPipelineLayout (void) const;
+ void writeDrawCmdBuffer (vk::VkCommandBuffer cmd) const;
+ tcu::TestStatus verifyResultImage (const tcu::ConstPixelBufferAccess& result) const;
+
+ enum
+ {
+ RENDER_SIZE = 128,
+ };
+
+ const vk::VkDescriptorType m_descriptorType;
+ const vk::VkShaderStageFlags m_stageFlags;
+ const ShaderInputInterface m_shaderInterface;
+ const bool m_nonzeroViewOffset;
+
+ const vk::Unique<vk::VkDescriptorSetLayout> m_descriptorSetLayout;
+ const vk::Unique<vk::VkPipelineLayout> m_pipelineLayout;
+ const TexelBufferInstanceBuffers m_texelBuffers;
+ const vk::Unique<vk::VkDescriptorPool> m_descriptorPool;
+ const vk::Unique<vk::VkDescriptorSet> m_descriptorSet;
+};
+
+TexelBufferRenderInstance::TexelBufferRenderInstance (vkt::Context& context,
+ bool isPrimaryCmdBuf,
+ vk::VkDescriptorType descriptorType,
+ vk::VkShaderStageFlags stageFlags,
+ ShaderInputInterface shaderInterface,
+ bool nonzeroViewOffset)
+ : SingleCmdRenderInstance (context, isPrimaryCmdBuf, tcu::UVec2(RENDER_SIZE, RENDER_SIZE))
+ , m_descriptorType (descriptorType)
+ , m_stageFlags (stageFlags)
+ , m_shaderInterface (shaderInterface)
+ , m_nonzeroViewOffset (nonzeroViewOffset)
+ , m_descriptorSetLayout (createDescriptorSetLayout(m_vki, m_device, m_descriptorType, m_shaderInterface, m_stageFlags))
+ , m_pipelineLayout (createPipelineLayout(m_vki, m_device, *m_descriptorSetLayout))
+ , m_texelBuffers (m_vki, m_device, m_allocator, m_descriptorType, getInterfaceNumResources(m_shaderInterface), m_nonzeroViewOffset)
+ , m_descriptorPool (createDescriptorPool(m_vki, m_device, m_descriptorType, m_shaderInterface))
+ , m_descriptorSet (createDescriptorSet(m_vki, m_device, m_descriptorType, m_shaderInterface, *m_descriptorSetLayout, *m_descriptorPool, m_texelBuffers.getBufferViewA(), m_texelBuffers.getBufferViewB()))
+{
+}
+
+vk::Move<vk::VkDescriptorSetLayout> TexelBufferRenderInstance::createDescriptorSetLayout (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::VkDescriptorType descriptorType,
+ ShaderInputInterface shaderInterface,
+ vk::VkShaderStageFlags stageFlags)
+{
+ vk::DescriptorSetLayoutBuilder builder;
+
+ switch (shaderInterface)
+ {
+ case SHADER_INPUT_SINGLE_DESCRIPTOR:
+ builder.addSingleBinding(descriptorType, stageFlags);
+ break;
+
+ case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
+ builder.addSingleBinding(descriptorType, stageFlags);
+ builder.addSingleBinding(descriptorType, stageFlags);
+ break;
+
+ case SHADER_INPUT_DESCRIPTOR_ARRAY:
+ builder.addArrayBinding(descriptorType, 2u, stageFlags);
+ break;
+
+ default:
+ DE_FATAL("Impossible");
+ }
+
+ return builder.build(vki, device);
+}
+
+vk::Move<vk::VkPipelineLayout> TexelBufferRenderInstance::createPipelineLayout (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::VkDescriptorSetLayout descriptorSetLayout)
+{
+ const vk::VkPipelineLayoutCreateInfo createInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
+ DE_NULL,
+ (vk::VkPipelineLayoutCreateFlags)0,
+ 1, // descriptorSetCount
+ &descriptorSetLayout, // pSetLayouts
+ 0u, // pushConstantRangeCount
+ DE_NULL, // pPushConstantRanges
+ };
+ return vk::createPipelineLayout(vki, device, &createInfo);
+}
+
+vk::Move<vk::VkDescriptorPool> TexelBufferRenderInstance::createDescriptorPool (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::VkDescriptorType descriptorType,
+ ShaderInputInterface shaderInterface)
+{
+ return vk::DescriptorPoolBuilder()
+ .addType(descriptorType, getInterfaceNumResources(shaderInterface))
+ .build(vki, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
+}
+
+vk::Move<vk::VkDescriptorSet> TexelBufferRenderInstance::createDescriptorSet (const vk::DeviceInterface& vki,
+ vk::VkDevice device,
+ vk::VkDescriptorType descriptorType,
+ ShaderInputInterface shaderInterface,
+ vk::VkDescriptorSetLayout layout,
+ vk::VkDescriptorPool pool,
+ vk::VkBufferView viewA,
+ vk::VkBufferView viewB)
+{
+ const vk::VkBufferView texelBufferInfos[2] =
+ {
+ viewA,
+ viewB,
+ };
+ const vk::VkDescriptorSetAllocateInfo allocInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+ DE_NULL,
+ pool,
+ 1u,
+ &layout
+ };
+
+ vk::Move<vk::VkDescriptorSet> descriptorSet = allocateDescriptorSet(vki, device, &allocInfo);
+ vk::DescriptorSetUpdateBuilder builder;
+
+ switch (shaderInterface)
+ {
+ case SHADER_INPUT_SINGLE_DESCRIPTOR:
+ builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &texelBufferInfos[0]);
+ break;
+
+ case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
+ builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &texelBufferInfos[0]);
+ builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), descriptorType, &texelBufferInfos[1]);
+ break;
+
+ case SHADER_INPUT_DESCRIPTOR_ARRAY:
+ builder.writeArray(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, 2u, texelBufferInfos);
+ break;
+
+ default:
+ DE_FATAL("Impossible");
+ }
+
+ builder.update(vki, device);
+ return descriptorSet;
+}
+
+void TexelBufferRenderInstance::logTestPlan (void) const
+{
+ std::ostringstream msg;
+
+ msg << "Rendering 2x2 grid.\n"
+ << "Single descriptor set. Descriptor set contains "
+ << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
+ (m_shaderInterface == SHADER_INPUT_MULTIPLE_DESCRIPTORS) ? "two" :
+ (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
+ (const char*)DE_NULL)
+ << " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
+ << "Buffer view is created with a " << ((m_nonzeroViewOffset) ? ("non-zero") : ("zero")) << " offset.\n"
+ << "Buffer format is " << vk::getFormatName(vk::mapTextureFormat(m_texelBuffers.getTextureFormat())) << ".\n";
+
+ if (m_stageFlags == 0u)
+ {
+ msg << "Descriptors are not accessed in any shader stage.\n";
+ }
+ else
+ {
+ msg << "Color in each cell is fetched using the descriptor(s):\n";
+
+ for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
+ {
+ msg << "Test sample " << resultNdx << ": fetch at position " << m_texelBuffers.getFetchPos(resultNdx);
+
+ if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
+ {
+ const int srcResourceNdx = (resultNdx % 2); // ABAB source
+ msg << " from texelBuffer " << srcResourceNdx;
+ }
+
+ msg << "\n";
+ }
+
+ msg << "Descriptors are accessed in {"
+ << (((m_stageFlags & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0) ? (" vertex") : (""))
+ << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0) ? (" tess_control") : (""))
+ << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0) ? (" tess_evaluation") : (""))
+ << (((m_stageFlags & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0) ? (" geometry") : (""))
+ << (((m_stageFlags & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0) ? (" fragment") : (""))
+ << " } stages.";
+ }
+
+ m_context.getTestContext().getLog()
+ << tcu::TestLog::Message
+ << msg.str()
+ << tcu::TestLog::EndMessage;
+}
+
+vk::VkPipelineLayout TexelBufferRenderInstance::getPipelineLayout (void) const
+{
+ return *m_pipelineLayout;
+}
+
+void TexelBufferRenderInstance::writeDrawCmdBuffer (vk::VkCommandBuffer cmd) const
+{
+ m_vki.cmdBindDescriptorSets(cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, getPipelineLayout(), 0, 1, &m_descriptorSet.get(), 0, DE_NULL);
+ m_vki.cmdDraw(cmd, 6 * 4, 1, 0, 0); // render four quads (two separate triangles)
+}
+
+tcu::TestStatus TexelBufferRenderInstance::verifyResultImage (const tcu::ConstPixelBufferAccess& result) const
+{
+ const tcu::Vec4 green (0.0f, 1.0f, 0.0f, 1.0f);
+ const tcu::Vec4 yellow (1.0f, 1.0f, 0.0f, 1.0f);
+ const bool doFetch = (m_stageFlags != 0u); // no active stages? Then don't fetch
+ const tcu::Vec4 sample0 = (!doFetch) ? (yellow) : (m_texelBuffers.fetchTexelValue(0));
+ const tcu::Vec4 sample1 = (!doFetch) ? (green) : (m_texelBuffers.fetchTexelValue(1));
+ const tcu::Vec4 sample2 = (!doFetch) ? (green) : (m_texelBuffers.fetchTexelValue(2));
+ const tcu::Vec4 sample3 = (!doFetch) ? (yellow) : (m_texelBuffers.fetchTexelValue(3));
+ tcu::Surface reference (m_targetSize.x(), m_targetSize.y());
+
+ drawQuadrantReferenceResult(reference.getAccess(), sample0, sample1, sample2, sample3);
+
+ if (!bilinearCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference.getAccess(), result, tcu::RGBA(1, 1, 1, 1), tcu::COMPARE_LOG_RESULT))
+ return tcu::TestStatus::fail("Image verification failed");
+ else
+ return tcu::TestStatus::pass("Pass");
+}
+
+class TexelBufferComputeInstance : public vkt::TestInstance
+{
+public:
+ TexelBufferComputeInstance (vkt::Context& context,
+ vk::VkDescriptorType descriptorType,
+ ShaderInputInterface shaderInterface,
+ bool nonzeroViewOffset);
+
+private:
+ vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout (void) const;
+ vk::Move<vk::VkDescriptorPool> createDescriptorPool (void) const;
+ vk::Move<vk::VkDescriptorSet> createDescriptorSet (vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout) const;
+
+ tcu::TestStatus iterate (void);
+ void logTestPlan (void) const;
+ tcu::TestStatus testResourceAccess (void);
+
+ const vk::VkDescriptorType m_descriptorType;
+ const ShaderInputInterface m_shaderInterface;
+ const bool m_nonzeroViewOffset;
+
+ const vk::DeviceInterface& m_vki;
+ const vk::VkDevice m_device;
+ const vk::VkQueue m_queue;
+ const deUint32 m_queueFamilyIndex;
+ vk::Allocator& m_allocator;
+
+ const ComputeInstanceResultBuffer m_result;
+ const TexelBufferInstanceBuffers m_texelBuffers;
+};
+
+TexelBufferComputeInstance::TexelBufferComputeInstance (Context& context,
+ vk::VkDescriptorType descriptorType,
+ ShaderInputInterface shaderInterface,
+ bool nonzeroViewOffset)
+ : vkt::TestInstance (context)
+ , m_descriptorType (descriptorType)
+ , m_shaderInterface (shaderInterface)
+ , m_nonzeroViewOffset (nonzeroViewOffset)
+ , m_vki (context.getDeviceInterface())
+ , m_device (context.getDevice())
+ , m_queue (context.getUniversalQueue())
+ , m_queueFamilyIndex (context.getUniversalQueueFamilyIndex())
+ , m_allocator (context.getDefaultAllocator())
+ , m_result (m_vki, m_device, m_allocator)
+ , m_texelBuffers (m_vki, m_device, m_allocator, m_descriptorType, getInterfaceNumResources(m_shaderInterface), m_nonzeroViewOffset)
+{
+}
+
+vk::Move<vk::VkDescriptorSetLayout> TexelBufferComputeInstance::createDescriptorSetLayout (void) const
+{
+ vk::DescriptorSetLayoutBuilder builder;
+
+ builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT);
+
+ switch (m_shaderInterface)
+ {
+ case SHADER_INPUT_SINGLE_DESCRIPTOR:
+ builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
+ break;
+
+ case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
+ builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
+ builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
+ break;
+
+ case SHADER_INPUT_DESCRIPTOR_ARRAY:
+ builder.addArrayBinding(m_descriptorType, 2u, vk::VK_SHADER_STAGE_COMPUTE_BIT);
+ break;
+
+ default:
+ DE_FATAL("Impossible");
+ };
+
+ return builder.build(m_vki, m_device);
+}
+
+vk::Move<vk::VkDescriptorPool> TexelBufferComputeInstance::createDescriptorPool (void) const
+{
+ return vk::DescriptorPoolBuilder()
+ .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
+ .addType(m_descriptorType, getInterfaceNumResources(m_shaderInterface))
+ .build(m_vki, m_device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
+}
+
+vk::Move<vk::VkDescriptorSet> TexelBufferComputeInstance::createDescriptorSet (vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout) const
+{
+ const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
+ const vk::VkBufferView texelBufferInfos[2] =
+ {
+ m_texelBuffers.getBufferViewA(),
+ m_texelBuffers.getBufferViewB(),
+ };
+ const vk::VkDescriptorSetAllocateInfo allocInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+ DE_NULL,
+ pool,
+ 1u,
+ &layout
+ };
+
+ vk::Move<vk::VkDescriptorSet> descriptorSet = allocateDescriptorSet(m_vki, m_device, &allocInfo);
+ vk::DescriptorSetUpdateBuilder builder;
+
+ // result
+ builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
+
+ // texel buffers
+ switch (m_shaderInterface)
+ {
+ case SHADER_INPUT_SINGLE_DESCRIPTOR:
+ builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, &texelBufferInfos[0]);
+ break;
+
+ case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
+ builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, &texelBufferInfos[0]);
+ builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), m_descriptorType, &texelBufferInfos[1]);
+ break;
+
+ case SHADER_INPUT_DESCRIPTOR_ARRAY:
+ builder.writeArray(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, 2u, texelBufferInfos);
+ break;
+
+ default:
+ DE_FATAL("Impossible");
+ }
+
+ builder.update(m_vki, m_device);
+ return descriptorSet;
+}
+
+tcu::TestStatus TexelBufferComputeInstance::iterate (void)
+{
+ logTestPlan();
+ return testResourceAccess();
+}
+
+void TexelBufferComputeInstance::logTestPlan (void) const
+{
+ std::ostringstream msg;
+
+ msg << "Fetching 4 values from image in compute shader.\n"
+ << "Single descriptor set. Descriptor set contains "
+ << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
+ (m_shaderInterface == SHADER_INPUT_MULTIPLE_DESCRIPTORS) ? "two" :
+ (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
+ (const char*)DE_NULL)
+ << " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
+ << "Buffer view is created with a " << ((m_nonzeroViewOffset) ? ("non-zero") : ("zero")) << " offset.\n"
+ << "Buffer format is " << vk::getFormatName(vk::mapTextureFormat(m_texelBuffers.getTextureFormat())) << ".\n";
+
+ for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
+ {
+ msg << "Test sample " << resultNdx << ": fetch at position " << m_texelBuffers.getFetchPos(resultNdx);
+
+ if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
+ {
+ const int srcResourceNdx = (resultNdx % 2); // ABAB source
+ msg << " from texelBuffer " << srcResourceNdx;
+ }
+
+ msg << "\n";
+ }
+
+ m_context.getTestContext().getLog()
+ << tcu::TestLog::Message
+ << msg.str()
+ << tcu::TestLog::EndMessage;
+}
+
+tcu::TestStatus TexelBufferComputeInstance::testResourceAccess (void)
+{
+ const vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout (createDescriptorSetLayout());
+ const vk::Unique<vk::VkDescriptorPool> descriptorPool (createDescriptorPool());
+ const vk::Unique<vk::VkDescriptorSet> descriptorSet (createDescriptorSet(*descriptorPool, *descriptorSetLayout));
+ const ComputePipeline pipeline (m_vki, m_device, m_context.getBinaryCollection(), 1, &descriptorSetLayout.get());
+
+ const vk::VkDescriptorSet descriptorSets[] = { *descriptorSet };
+ const int numDescriptorSets = DE_LENGTH_OF_ARRAY(descriptorSets);
+ const deUint32* const dynamicOffsets = DE_NULL;
+ const int numDynamicOffsets = 0;
+ const void* const preBarriers[] = { m_texelBuffers.getBufferInitBarrierA(), m_texelBuffers.getBufferInitBarrierB() };
+ const int numPreBarriers = m_texelBuffers.getNumTexelBuffers();
+ const void* const postBarriers[] = { m_result.getResultReadBarrier() };
+ const int numPostBarriers = DE_LENGTH_OF_ARRAY(postBarriers);
+
+ const ComputeCommand compute (m_vki,
+ m_device,
+ pipeline.getPipeline(),
+ pipeline.getPipelineLayout(),
+ tcu::UVec3(4, 1, 1),
+ numDescriptorSets, descriptorSets,
+ numDynamicOffsets, dynamicOffsets,
+ numPreBarriers, preBarriers,
+ numPostBarriers, postBarriers);
+
+ tcu::Vec4 results[4];
+ bool anyResultSet = false;
+ bool allResultsOk = true;
+
+ compute.submitAndWait(m_queueFamilyIndex, m_queue);
+ m_result.readResultContentsTo(&results);
+
+ // verify
+ for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
+ {
+ const tcu::Vec4 result = results[resultNdx];
+ const tcu::Vec4 reference = m_texelBuffers.fetchTexelValue(resultNdx);
+ const tcu::Vec4 conversionThreshold = tcu::Vec4(1.0f / 255.0f);
+
+ if (result != tcu::Vec4(-1.0f))
+ anyResultSet = true;
+
+ if (tcu::boolAny(tcu::greaterThan(tcu::abs(result - reference), conversionThreshold)))
+ {
+ allResultsOk = false;
+
+ m_context.getTestContext().getLog()
+ << tcu::TestLog::Message
+ << "Test sample " << resultNdx << ": Expected " << reference << ", got " << result
+ << tcu::TestLog::EndMessage;
+ }
+ }
+
+ // read back and verify
+ if (allResultsOk)
+ return tcu::TestStatus::pass("Pass");
+ else if (anyResultSet)
+ return tcu::TestStatus::fail("Invalid result values");
+ else
+ {
+ m_context.getTestContext().getLog()
+ << tcu::TestLog::Message
+ << "Result buffer was not written to."
+ << tcu::TestLog::EndMessage;
+ return tcu::TestStatus::fail("Result buffer was not written to");
+ }
+}
+
+class TexelBufferDescriptorCase : public QuadrantRendederCase
+{
+public:
+ enum
+ {
+ FLAG_VIEW_OFFSET = (1u << 1u),
+ };
+ // enum continues where resource flags ends
+ DE_STATIC_ASSERT((deUint32)FLAG_VIEW_OFFSET == (deUint32)RESOURCE_FLAG_LAST);
+
+ TexelBufferDescriptorCase (tcu::TestContext& testCtx,
+ const char* name,
+ const char* description,
+ bool isPrimaryCmdBuf,
+ vk::VkDescriptorType descriptorType,
+ vk::VkShaderStageFlags exitingStages,
+ vk::VkShaderStageFlags activeStages,
+ ShaderInputInterface shaderInterface,
+ deUint32 flags);
+
+private:
+ std::string genExtensionDeclarations (vk::VkShaderStageFlagBits stage) const;
+ std::string genResourceDeclarations (vk::VkShaderStageFlagBits stage, int numUsedBindings) const;
+ std::string genResourceAccessSource (vk::VkShaderStageFlagBits stage) const;
+ std::string genNoAccessSource (void) const;
+
+ vkt::TestInstance* createInstance (vkt::Context& context) const;
+
+ const bool m_isPrimaryCmdBuf;
+ const vk::VkDescriptorType m_descriptorType;
+ const ShaderInputInterface m_shaderInterface;
+ const bool m_nonzeroViewOffset;
+};
+
+TexelBufferDescriptorCase::TexelBufferDescriptorCase (tcu::TestContext& testCtx,
+ const char* name,
+ const char* description,
+ bool isPrimaryCmdBuf,
+ vk::VkDescriptorType descriptorType,
+ vk::VkShaderStageFlags exitingStages,
+ vk::VkShaderStageFlags activeStages,
+ ShaderInputInterface shaderInterface,
+ deUint32 flags)
+ : QuadrantRendederCase (testCtx, name, description, glu::GLSL_VERSION_310_ES, exitingStages, activeStages)
+ , m_isPrimaryCmdBuf (isPrimaryCmdBuf)
+ , m_descriptorType (descriptorType)
+ , m_shaderInterface (shaderInterface)
+ , m_nonzeroViewOffset (((flags & FLAG_VIEW_OFFSET) != 0) ? (1u) : (0u))
+{
+}
+
+std::string TexelBufferDescriptorCase::genExtensionDeclarations (vk::VkShaderStageFlagBits stage) const
+{
+ DE_UNREF(stage);
+ return "#extension GL_EXT_texture_buffer : require\n";
+}
+
+std::string TexelBufferDescriptorCase::genResourceDeclarations (vk::VkShaderStageFlagBits stage, int numUsedBindings) const
+{
+ DE_UNREF(stage);
+
+ const bool isUniform = isUniformDescriptorType(m_descriptorType);
+ const char* const storageType = (isUniform) ? ("samplerBuffer ") : ("readonly imageBuffer ");
+ const char* const formatQualifier = (isUniform) ? ("") : (", rgba8");
+
+ switch (m_shaderInterface)
+ {
+ case SHADER_INPUT_SINGLE_DESCRIPTOR:
+ return "layout(set = 0, binding = " + de::toString(numUsedBindings) + formatQualifier + ") uniform highp " + storageType + " u_texelBuffer;\n";
+
+ case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
+ return "layout(set = 0, binding = " + de::toString(numUsedBindings) + formatQualifier + ") uniform highp " + storageType + " u_texelBufferA;\n"
+ "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + formatQualifier + ") uniform highp " + storageType + " u_texelBufferB;\n";
+
+ case SHADER_INPUT_DESCRIPTOR_ARRAY:
+ return "layout(set = 0, binding = " + de::toString(numUsedBindings) + formatQualifier + ") uniform highp " + storageType + " u_texelBuffer[2];\n";
+
+ default:
+ DE_FATAL("Impossible");
+ return "";
+ }
+}
+
+std::string TexelBufferDescriptorCase::genResourceAccessSource (vk::VkShaderStageFlagBits stage) const
+{
+ DE_UNREF(stage);
+
+ const char* const accessPostfixA = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? ("")
+ : (m_shaderInterface == SHADER_INPUT_MULTIPLE_DESCRIPTORS) ? ("A")
+ : (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? ("[0]")
+ : (DE_NULL);
+ const char* const accessPostfixB = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? ("")
+ : (m_shaderInterface == SHADER_INPUT_MULTIPLE_DESCRIPTORS) ? ("B")
+ : (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? ("[1]")
+ : (DE_NULL);
+ const char* const fetchFunc = (isUniformDescriptorType(m_descriptorType)) ? ("texelFetch") : ("imageLoad");
+ std::ostringstream buf;
+
+ buf << " if (quadrant_id == 0)\n"
+ << " result_color = " << fetchFunc << "(u_texelBuffer" << accessPostfixA << ", " << TexelBufferInstanceBuffers::getFetchPos(0) << ");\n"
+ << " else if (quadrant_id == 1)\n"
+ << " result_color = " << fetchFunc << "(u_texelBuffer" << accessPostfixB << ", " << TexelBufferInstanceBuffers::getFetchPos(1) << ");\n"
+ << " else if (quadrant_id == 2)\n"
+ << " result_color = " << fetchFunc << "(u_texelBuffer" << accessPostfixA << ", " << TexelBufferInstanceBuffers::getFetchPos(2) << ");\n"
+ << " else\n"
+ << " result_color = " << fetchFunc << "(u_texelBuffer" << accessPostfixB << ", " << TexelBufferInstanceBuffers::getFetchPos(3) << ");\n";
+
+ return buf.str();
+}
+
+std::string TexelBufferDescriptorCase::genNoAccessSource (void) const
+{
+ return " if (quadrant_id == 1 || quadrant_id == 2)\n"
+ " result_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
+ " else\n"
+ " result_color = vec4(1.0, 1.0, 0.0, 1.0);\n";
+}
+
+vkt::TestInstance* TexelBufferDescriptorCase::createInstance (vkt::Context& context) const
+{
+ if (m_exitingStages == vk::VK_SHADER_STAGE_COMPUTE_BIT)
+ {
+ DE_ASSERT(m_isPrimaryCmdBuf); // secondaries are only valid within renderpass
+ return new TexelBufferComputeInstance(context, m_descriptorType, m_shaderInterface, m_nonzeroViewOffset);
+ }
+ else
+ return new TexelBufferRenderInstance(context, m_isPrimaryCmdBuf, m_descriptorType, m_activeStages, m_shaderInterface, m_nonzeroViewOffset);
+}
+
+void createShaderAccessImageTests (tcu::TestCaseGroup* group,
+ bool isPrimaryCmdBuf,
+ vk::VkDescriptorType descriptorType,
+ vk::VkShaderStageFlags exitingStages,
+ vk::VkShaderStageFlags activeStages,
+ ShaderInputInterface dimension,
+ deUint32 resourceFlags)
+{
+ static const struct
+ {
+ vk::VkImageViewType viewType;
+ const char* name;
+ const char* description;
+ deUint32 flags;
+ } s_imageTypes[] =
+ {
+ { vk::VK_IMAGE_VIEW_TYPE_1D, "1d", "1D image view", 0u },
+ { vk::VK_IMAGE_VIEW_TYPE_1D, "1d_base_mip", "1D image subview with base mip level", ImageDescriptorCase::FLAG_BASE_MIP },
+ { vk::VK_IMAGE_VIEW_TYPE_1D, "1d_base_slice", "1D image subview with base array slice", ImageDescriptorCase::FLAG_BASE_SLICE },
+
+ { vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY, "1d_array", "1D array image view", 0u },
+ { vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY, "1d_array_base_mip", "1D array image subview with base mip level", ImageDescriptorCase::FLAG_BASE_MIP },
+ { vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY, "1d_array_base_slice", "1D array image subview with base array slice", ImageDescriptorCase::FLAG_BASE_SLICE },
+
+ { vk::VK_IMAGE_VIEW_TYPE_2D, "2d", "2D image view", 0u },
+ { vk::VK_IMAGE_VIEW_TYPE_2D, "2d_base_mip", "2D image subview with base mip level", ImageDescriptorCase::FLAG_BASE_MIP },
+ { vk::VK_IMAGE_VIEW_TYPE_2D, "2d_base_slice", "2D image subview with base array slice", ImageDescriptorCase::FLAG_BASE_SLICE },
+
+ { vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY, "2d_array", "2D array image view", 0u },
+ { vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY, "2d_array_base_mip", "2D array image subview with base mip level", ImageDescriptorCase::FLAG_BASE_MIP },
+ { vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY, "2d_array_base_slice", "2D array image subview with base array slice", ImageDescriptorCase::FLAG_BASE_SLICE },
+
+ { vk::VK_IMAGE_VIEW_TYPE_3D, "3d", "3D image view", 0u },
+ { vk::VK_IMAGE_VIEW_TYPE_3D, "3d_base_mip", "3D image subview with base mip level", ImageDescriptorCase::FLAG_BASE_MIP },
+ // no 3d array textures
+
+ { vk::VK_IMAGE_VIEW_TYPE_CUBE, "cube", "Cube image view", 0u },
+ { vk::VK_IMAGE_VIEW_TYPE_CUBE, "cube_base_mip", "Cube image subview with base mip level", ImageDescriptorCase::FLAG_BASE_MIP },
+ { vk::VK_IMAGE_VIEW_TYPE_CUBE, "cube_base_slice", "Cube image subview with base array slice", ImageDescriptorCase::FLAG_BASE_SLICE },
+
+ { vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, "cube_array", "Cube image view", 0u },
+ { vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, "cube_array_base_mip", "Cube image subview with base mip level", ImageDescriptorCase::FLAG_BASE_MIP },
+ { vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, "cube_array_base_slice", "Cube image subview with base array slice", ImageDescriptorCase::FLAG_BASE_SLICE },
+ };
+
+ for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_imageTypes); ++ndx)
+ {
+ // never overlap
+ DE_ASSERT((s_imageTypes[ndx].flags & resourceFlags) == 0u);
+
+ group->addChild(new ImageDescriptorCase(group->getTestContext(),
+ s_imageTypes[ndx].name,
+ s_imageTypes[ndx].description,
+ isPrimaryCmdBuf,
+ descriptorType,
+ exitingStages,
+ activeStages,
+ dimension,
+ s_imageTypes[ndx].viewType,
+ s_imageTypes[ndx].flags | resourceFlags));
+ }
+}
+
+void createShaderAccessTexelBufferTests (tcu::TestCaseGroup* group,
+ bool isPrimaryCmdBuf,
+ vk::VkDescriptorType descriptorType,
+ vk::VkShaderStageFlags exitingStages,
+ vk::VkShaderStageFlags activeStages,
+ ShaderInputInterface dimension,
+ deUint32 resourceFlags)
+{
+ DE_ASSERT(resourceFlags == 0);
+ DE_UNREF(resourceFlags);
+
+ static const struct
+ {
+ const char* name;
+ const char* description;
+ deUint32 flags;
+ } s_texelBufferTypes[] =
+ {
+ { "offset_zero", "View offset is zero", 0u },
+ { "offset_nonzero", "View offset is non-zero", TexelBufferDescriptorCase::FLAG_VIEW_OFFSET },
+ };
+
+ for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_texelBufferTypes); ++ndx)
+ {
+ group->addChild(new TexelBufferDescriptorCase(group->getTestContext(),
+ s_texelBufferTypes[ndx].name,
+ s_texelBufferTypes[ndx].description,
+ isPrimaryCmdBuf,
+ descriptorType,
+ exitingStages,
+ activeStages,
+ dimension,
+ s_texelBufferTypes[ndx].flags));
+ }
+}
+
+void createShaderAccessBufferTests (tcu::TestCaseGroup* group,
+ bool isPrimaryCmdBuf,
+ vk::VkDescriptorType descriptorType,
+ vk::VkShaderStageFlags exitingStages,
+ vk::VkShaderStageFlags activeStages,
+ ShaderInputInterface dimension,
+ deUint32 resourceFlags)
+{
+ DE_ASSERT(resourceFlags == 0u);
+ DE_UNREF(resourceFlags);
+
+ static const struct
+ {
+ const char* name;
+ const char* description;
+ bool isForDynamicCases;
+ deUint32 flags;
+ } s_bufferTypes[] =
+ {
+ { "offset_view_zero", "View offset is zero", false, 0u },
+ { "offset_view_nonzero", "View offset is non-zero", false, BufferDescriptorCase::FLAG_VIEW_OFFSET },
+
+ { "offset_view_zero_dynamic_zero", "View offset is zero, dynamic offset is zero", true, BufferDescriptorCase::FLAG_DYNAMIC_OFFSET_ZERO },
+ { "offset_view_zero_dynamic_nonzero", "View offset is zero, dynamic offset is non-zero", true, BufferDescriptorCase::FLAG_DYNAMIC_OFFSET_NONZERO },
+ { "offset_view_nonzero_dynamic_zero", "View offset is non-zero, dynamic offset is zero", true, BufferDescriptorCase::FLAG_VIEW_OFFSET | BufferDescriptorCase::FLAG_DYNAMIC_OFFSET_ZERO },
+ { "offset_view_nonzero_dynamic_nonzero", "View offset is non-zero, dynamic offset is non-zero", true, BufferDescriptorCase::FLAG_VIEW_OFFSET | BufferDescriptorCase::FLAG_DYNAMIC_OFFSET_NONZERO },
+ };
+
+ const bool isDynamicCase = isDynamicDescriptorType(descriptorType);
+
+ for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_bufferTypes); ++ndx)
+ {
+ if (isDynamicCase == s_bufferTypes[ndx].isForDynamicCases)
+ group->addChild(new BufferDescriptorCase(group->getTestContext(),
+ s_bufferTypes[ndx].name,
+ s_bufferTypes[ndx].description,
+ isPrimaryCmdBuf,
+ descriptorType,
+ exitingStages,
+ activeStages,
+ dimension,
+ s_bufferTypes[ndx].flags));
+ }
+}
+
+} // anonymous
+
+tcu::TestCaseGroup* createShaderAccessTests (tcu::TestContext& testCtx)
+{
+ static const struct
+ {
+ const bool isPrimary;
+ const char* name;
+ const char* description;
+ } s_bindTypes[] =
+ {
+ { true, "primary_cmd_buf", "Bind in primary command buffer" },
+ { false, "seconday_cmd_buf", "Bind in secondary command buffer" },
+ };
+ static const struct
+ {
+ const vk::VkDescriptorType descriptorType;
+ const char* name;
+ const char* description;
+ deUint32 flags;
+ } s_descriptorTypes[] =
+ {
+ { vk::VK_DESCRIPTOR_TYPE_SAMPLER, "sampler_mutable", "VK_DESCRIPTOR_TYPE_SAMPLER with mutable sampler", 0u },
+ { vk::VK_DESCRIPTOR_TYPE_SAMPLER, "sampler_immutable", "VK_DESCRIPTOR_TYPE_SAMPLER with immutable sampler", RESOURCE_FLAG_IMMUTABLE_SAMPLER },
+ { vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, "combined_image_sampler_mutable", "VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER with mutable sampler", 0u },
+ { vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, "combined_image_sampler_immutable", "VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER with immutable sampler", RESOURCE_FLAG_IMMUTABLE_SAMPLER },
+ // \note No way to access SAMPLED_IMAGE without a sampler
+// { vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, "sampled_image", "VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE", 0u },
+ { vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, "storage_image", "VK_DESCRIPTOR_TYPE_STORAGE_IMAGE", 0u },
+ { vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, "uniform_texel_buffer", "VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER", 0u },
+ { vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, "storage_texel_buffer", "VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER", 0u },
+ { vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, "uniform_buffer", "VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER", 0u },
+ { vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, "storage_buffer", "VK_DESCRIPTOR_TYPE_STORAGE_BUFFER", 0u },
+ { vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, "uniform_buffer_dynamic", "VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC", 0u },
+ { vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, "storage_buffer_dynamic", "VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC", 0u },
+ };
+ static const struct
+ {
+ const char* name;
+ const char* description;
+ vk::VkShaderStageFlags existingStages; //!< stages that exists
+ vk::VkShaderStageFlags activeStages; //!< stages that access resource
+ bool supportsSecondaryCmdBufs;
+ } s_shaderStages[] =
+ {
+ {
+ "no_access",
+ "No accessing stages",
+ vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
+ 0u,
+ true,
+ },
+ {
+ "vertex",
+ "Vertex stage",
+ vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
+ vk::VK_SHADER_STAGE_VERTEX_BIT,
+ true,
+ },
+ {
+ "tess_ctrl",
+ "Tessellation control stage",
+ vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
+ vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
+ true,
+ },
+ {
+ "tess_eval",
+ "Tessellation evaluation stage",
+ vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
+ vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
+ true,
+ },
+ {
+ "geometry",
+ "Geometry stage",
+ vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_GEOMETRY_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
+ vk::VK_SHADER_STAGE_GEOMETRY_BIT,
+ true,
+ },
+ {
+ "fragment",
+ "Fragment stage",
+ vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
+ vk::VK_SHADER_STAGE_FRAGMENT_BIT,
+ true,
+ },
+ {
+ "compute",
+ "Compute stage",
+ vk::VK_SHADER_STAGE_COMPUTE_BIT,
+ vk::VK_SHADER_STAGE_COMPUTE_BIT,
+ false,
+ },
+ {
+ "vertex_fragment",
+ "Vertex and fragment stages",
+ vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
+ vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
+ true,
+ },
+ };
+ static const struct
+ {
+ ShaderInputInterface dimension;
+ const char* name;
+ const char* description;
+ } s_variableDimensions[] =
+ {
+ { SHADER_INPUT_SINGLE_DESCRIPTOR, "single_descriptor", "Single descriptor" },
+ { SHADER_INPUT_MULTIPLE_DESCRIPTORS, "multiple_descriptors", "Multiple descriptors" },
+ { SHADER_INPUT_DESCRIPTOR_ARRAY, "descriptor_array", "Descriptor array" },
+ };
+
+ de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "shader_access", "Access resource via descriptor in a single descriptor set"));
+
+ // .primary_cmd_buf...
+ for (int bindTypeNdx = 0; bindTypeNdx < DE_LENGTH_OF_ARRAY(s_bindTypes); ++bindTypeNdx)
+ {
+ de::MovePtr<tcu::TestCaseGroup> bindGroup(new tcu::TestCaseGroup(testCtx, s_bindTypes[bindTypeNdx].name, s_bindTypes[bindTypeNdx].description));
+
+ // .sampler, .combined_image_sampler, other resource types ...
+ for (int descriptorNdx = 0; descriptorNdx < DE_LENGTH_OF_ARRAY(s_descriptorTypes); ++descriptorNdx)
+ {
+ de::MovePtr<tcu::TestCaseGroup> typeGroup(new tcu::TestCaseGroup(testCtx, s_descriptorTypes[descriptorNdx].name, s_descriptorTypes[descriptorNdx].description));
+
+ for (int stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(s_shaderStages); ++stageNdx)
+ {
+ if (s_bindTypes[bindTypeNdx].isPrimary || s_shaderStages[stageNdx].supportsSecondaryCmdBufs)
+ {
+ de::MovePtr<tcu::TestCaseGroup> stageGroup(new tcu::TestCaseGroup(testCtx, s_shaderStages[stageNdx].name, s_shaderStages[stageNdx].description));
+
+ for (int dimensionNdx = 0; dimensionNdx < DE_LENGTH_OF_ARRAY(s_variableDimensions); ++dimensionNdx)
+ {
+ de::MovePtr<tcu::TestCaseGroup> dimensionGroup(new tcu::TestCaseGroup(testCtx, s_variableDimensions[dimensionNdx].name, s_variableDimensions[dimensionNdx].description));
+ void (*createTestsFunc)(tcu::TestCaseGroup* group,
+ bool isPrimaryCmdBuf,
+ vk::VkDescriptorType descriptorType,
+ vk::VkShaderStageFlags existingStages,
+ vk::VkShaderStageFlags activeStages,
+ ShaderInputInterface dimension,
+ deUint32 resourceFlags);
+
+ switch (s_descriptorTypes[descriptorNdx].descriptorType)
+ {
+ case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
+ case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+ case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
+ createTestsFunc = createShaderAccessImageTests;
+ break;
+
+ case vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
+ case vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
+ createTestsFunc = createShaderAccessTexelBufferTests;
+ break;
+
+ case vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
+ case vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
+ case vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
+ case vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
+ createTestsFunc = createShaderAccessBufferTests;
+ break;
+
+ default:
+ createTestsFunc = DE_NULL;
+ DE_FATAL("Impossible");
+ }
+
+ if (createTestsFunc)
+ {
+ createTestsFunc(dimensionGroup.get(),
+ s_bindTypes[bindTypeNdx].isPrimary,
+ s_descriptorTypes[descriptorNdx].descriptorType,
+ s_shaderStages[stageNdx].existingStages,
+ s_shaderStages[stageNdx].activeStages,
+ s_variableDimensions[dimensionNdx].dimension,
+ s_descriptorTypes[descriptorNdx].flags);
+ }
+ else
+ DE_FATAL("Impossible");
+
+ stageGroup->addChild(dimensionGroup.release());
+ }
+
+ typeGroup->addChild(stageGroup.release());
+ }
+ }
+
+ bindGroup->addChild(typeGroup.release());
+ }
+
+ group->addChild(bindGroup.release());
+ }
+
+ return group.release();
+}
+
+} // BindingModel
+} // vkt
--- /dev/null
+#ifndef _VKTBINDINGSHADERACCESSTESTS_HPP
+#define _VKTBINDINGSHADERACCESSTESTS_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Binding shader access tests
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+namespace BindingModel
+{
+
+tcu::TestCaseGroup* createShaderAccessTests (tcu::TestContext& testCtx);
+
+} // BindingModel
+} // vkt
+
+#endif // _VKTBINDINGSHADERACCESSTESTS_HPP
--- /dev/null
+# Memory tests
+
+include_directories(..)
+
+set(DEQP_VK_MEMORY_SRCS
+ vktMemoryTests.cpp
+ vktMemoryTests.hpp
+ vktMemoryAllocationTests.cpp
+ vktMemoryAllocationTests.hpp
+ vktMemoryMappingTests.cpp
+ vktMemoryMappingTests.hpp
+ )
+
+set(DEQP_VK_MEMORY_LIBS
+ tcutil
+ vkutil
+ )
+
+add_library(deqp-vk-memory STATIC ${DEQP_VK_MEMORY_SRCS})
+target_link_libraries(deqp-vk-memory ${DEQP_VK_MEMORY_LIBS})
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Simple memory allocation tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "vktMemoryAllocationTests.hpp"
+
+#include "vktTestCaseUtil.hpp"
+
+#include "tcuMaybe.hpp"
+#include "tcuResultCollector.hpp"
+#include "tcuTestLog.hpp"
+
+#include "vkPlatform.hpp"
+#include "vkStrUtil.hpp"
+#include "vkRef.hpp"
+#include "vkDeviceUtil.hpp"
+#include "vkQueryUtil.hpp"
+
+#include "deUniquePtr.hpp"
+#include "deStringUtil.hpp"
+#include "deRandom.hpp"
+
+using tcu::Maybe;
+using tcu::TestLog;
+
+using std::string;
+using std::vector;
+
+using namespace vk;
+
+namespace vkt
+{
+namespace memory
+{
+namespace
+{
+
+struct TestConfig
+{
+ enum Order
+ {
+ ALLOC_FREE,
+ ALLOC_REVERSE_FREE,
+ MIXED_ALLOC_FREE,
+ ORDER_LAST
+ };
+
+ Maybe<VkDeviceSize> memorySize;
+ Maybe<float> memoryPercentage;
+ deUint32 memoryAllocationCount;
+ Order order;
+
+ TestConfig (void)
+ : memoryAllocationCount ((deUint32)-1)
+ , order (ORDER_LAST)
+ {
+ }
+};
+
+class AllocateFreeTestInstance : public TestInstance
+{
+public:
+ AllocateFreeTestInstance (Context& context, const TestConfig config)
+ : TestInstance (context)
+ , m_config (config)
+ , m_result (m_context.getTestContext().getLog())
+ , m_memoryTypeIndex (0)
+ , m_memoryProperties (getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()))
+ {
+ DE_ASSERT(!!m_config.memorySize != !!m_config.memoryPercentage);
+ }
+
+ tcu::TestStatus iterate (void);
+
+private:
+ const TestConfig m_config;
+ tcu::ResultCollector m_result;
+ deUint32 m_memoryTypeIndex;
+ const VkPhysicalDeviceMemoryProperties m_memoryProperties;
+};
+
+tcu::TestStatus AllocateFreeTestInstance::iterate (void)
+{
+ TestLog& log = m_context.getTestContext().getLog();
+ const VkDevice device = m_context.getDevice();
+ const DeviceInterface& vkd = m_context.getDeviceInterface();
+
+ if (m_memoryTypeIndex == 0)
+ {
+ log << TestLog::Message << "Memory allocation count: " << m_config.memoryAllocationCount << TestLog::EndMessage;
+ log << TestLog::Message << "Single allocation size: " << (m_config.memorySize ? de::toString(*m_config.memorySize) : de::toString(100.0f * (*m_config.memoryPercentage)) + " of heap size.D") << TestLog::EndMessage;
+
+ if (m_config.order == TestConfig::ALLOC_REVERSE_FREE)
+ log << TestLog::Message << "Memory is freed in reversed order. " << TestLog::EndMessage;
+ else if (m_config.order == TestConfig::ALLOC_FREE)
+ log << TestLog::Message << "Memory is freed in same order as allocated. " << TestLog::EndMessage;
+ else if (m_config.order == TestConfig::MIXED_ALLOC_FREE)
+ log << TestLog::Message << "Memory is freed right after allocation. " << TestLog::EndMessage;
+ else
+ DE_FATAL("Unknown allocation order");
+ }
+
+ try
+ {
+ const VkMemoryType memoryType = m_memoryProperties.memoryTypes[m_memoryTypeIndex];
+ const VkMemoryHeap memoryHeap = m_memoryProperties.memoryHeaps[memoryType.heapIndex];
+
+ const VkDeviceSize allocationSize = (m_config.memorySize ? *m_config.memorySize : (VkDeviceSize)(*m_config.memoryPercentage * (float)memoryHeap.size));
+ vector<VkDeviceMemory> memoryObjects (m_config.memoryAllocationCount, (VkDeviceMemory)0);
+
+ log << TestLog::Message << "Memory type index: " << m_memoryTypeIndex << TestLog::EndMessage;
+
+ if (memoryType.heapIndex >= m_memoryProperties.memoryHeapCount)
+ m_result.fail("Invalid heap index defined for memory type.");
+
+ {
+ log << TestLog::Message << "Memory type: " << memoryType << TestLog::EndMessage;
+ log << TestLog::Message << "Memory heap: " << memoryHeap << TestLog::EndMessage;
+
+ if (allocationSize * m_config.memoryAllocationCount * 4 > memoryHeap.size)
+ TCU_THROW(NotSupportedError, "Memory heap doesn't have enough memory.");
+
+ try
+ {
+ if (m_config.order == TestConfig::ALLOC_FREE || m_config.order == TestConfig::ALLOC_REVERSE_FREE)
+ {
+ for (size_t ndx = 0; ndx < m_config.memoryAllocationCount; ndx++)
+ {
+ const VkMemoryAllocateInfo alloc =
+ {
+ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType
+ DE_NULL, // pNext
+ allocationSize, // allocationSize
+ m_memoryTypeIndex // memoryTypeIndex;
+ };
+
+ VK_CHECK(vkd.allocateMemory(device, &alloc, (const VkAllocationCallbacks*)DE_NULL, &memoryObjects[ndx]));
+
+ TCU_CHECK(!!memoryObjects[ndx]);
+ }
+
+ if (m_config.order == TestConfig::ALLOC_FREE)
+ {
+ for (size_t ndx = 0; ndx < m_config.memoryAllocationCount; ndx++)
+ {
+ const VkDeviceMemory mem = memoryObjects[memoryObjects.size() - 1 - ndx];
+
+ vkd.freeMemory(device, mem, (const VkAllocationCallbacks*)DE_NULL);
+ memoryObjects[memoryObjects.size() - 1 - ndx] = (VkDeviceMemory)0;
+ }
+ }
+ else
+ {
+ for (size_t ndx = 0; ndx < m_config.memoryAllocationCount; ndx++)
+ {
+ const VkDeviceMemory mem = memoryObjects[ndx];
+
+ vkd.freeMemory(device, mem, (const VkAllocationCallbacks*)DE_NULL);
+ memoryObjects[ndx] = (VkDeviceMemory)0;
+ }
+ }
+ }
+ else
+ {
+ for (size_t ndx = 0; ndx < m_config.memoryAllocationCount; ndx++)
+ {
+ const VkMemoryAllocateInfo alloc =
+ {
+ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType
+ DE_NULL, // pNext
+ allocationSize, // allocationSize
+ m_memoryTypeIndex // memoryTypeIndex;
+ };
+
+ VK_CHECK(vkd.allocateMemory(device, &alloc, (const VkAllocationCallbacks*)DE_NULL, &memoryObjects[ndx]));
+ TCU_CHECK(!!memoryObjects[ndx]);
+
+ vkd.freeMemory(device, memoryObjects[ndx], (const VkAllocationCallbacks*)DE_NULL);
+ memoryObjects[ndx] = (VkDeviceMemory)0;
+ }
+ }
+ }
+ catch (...)
+ {
+ for (size_t ndx = 0; ndx < m_config.memoryAllocationCount; ndx++)
+ {
+ const VkDeviceMemory mem = memoryObjects[ndx];
+
+ if (!!mem)
+ {
+ vkd.freeMemory(device, mem, (const VkAllocationCallbacks*)DE_NULL);
+ memoryObjects[ndx] = (VkDeviceMemory)0;
+ }
+ }
+
+ throw;
+ }
+ }
+ }
+ catch (const tcu::TestError& error)
+ {
+ m_result.fail(error.getMessage());
+ }
+
+ m_memoryTypeIndex++;
+
+ if (m_memoryTypeIndex < m_memoryProperties.memoryTypeCount)
+ return tcu::TestStatus::incomplete();
+ else
+ return tcu::TestStatus(m_result.getResult(), m_result.getMessage());
+}
+
+struct MemoryType
+{
+ deUint32 index;
+ VkMemoryType type;
+};
+
+struct MemoryObject
+{
+ VkDeviceMemory memory;
+ VkDeviceSize size;
+};
+
+struct Heap
+{
+ VkMemoryHeap heap;
+ VkDeviceSize memoryUsage;
+ VkDeviceSize maxMemoryUsage;
+ vector<MemoryType> types;
+ vector<MemoryObject> objects;
+};
+
+class RandomAllocFreeTestInstance : public TestInstance
+{
+public:
+ RandomAllocFreeTestInstance (Context& context, deUint32 seed);
+ ~RandomAllocFreeTestInstance (void);
+
+ tcu::TestStatus iterate (void);
+
+private:
+ const size_t m_opCount;
+ size_t m_opNdx;
+ de::Random m_rng;
+ vector<Heap> m_heaps;
+ vector<size_t> m_nonFullHeaps;
+ vector<size_t> m_nonEmptyHeaps;
+};
+
+RandomAllocFreeTestInstance::RandomAllocFreeTestInstance (Context& context, deUint32 seed)
+ : TestInstance (context)
+ , m_opCount (128)
+ , m_opNdx (0)
+ , m_rng (seed)
+{
+ const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
+ const InstanceInterface& vki = context.getInstanceInterface();
+ const VkPhysicalDeviceMemoryProperties memoryProperties = getPhysicalDeviceMemoryProperties(vki, physicalDevice);
+
+ TCU_CHECK(memoryProperties.memoryHeapCount <= 32);
+ TCU_CHECK(memoryProperties.memoryTypeCount <= 32);
+
+ m_heaps.resize(memoryProperties.memoryHeapCount);
+
+ m_nonFullHeaps.reserve(m_heaps.size());
+ m_nonEmptyHeaps.reserve(m_heaps.size());
+
+ for (deUint32 heapNdx = 0; heapNdx < memoryProperties.memoryHeapCount; heapNdx++)
+ {
+ m_heaps[heapNdx].heap = memoryProperties.memoryHeaps[heapNdx];
+ m_heaps[heapNdx].memoryUsage = 0;
+ m_heaps[heapNdx].maxMemoryUsage = m_heaps[heapNdx].heap.size / 4;
+
+ m_heaps[heapNdx].objects.reserve(100);
+
+ m_nonFullHeaps.push_back((size_t)heapNdx);
+ }
+
+ for (deUint32 memoryTypeNdx = 0; memoryTypeNdx < memoryProperties.memoryTypeCount; memoryTypeNdx++)
+ {
+ const MemoryType type =
+ {
+ memoryTypeNdx,
+ memoryProperties.memoryTypes[memoryTypeNdx]
+ };
+
+ TCU_CHECK(type.type.heapIndex < memoryProperties.memoryHeapCount);
+
+ m_heaps[type.type.heapIndex].types.push_back(type);
+ }
+}
+
+RandomAllocFreeTestInstance::~RandomAllocFreeTestInstance (void)
+{
+ const VkDevice device = m_context.getDevice();
+ const DeviceInterface& vkd = m_context.getDeviceInterface();
+
+ for (deUint32 heapNdx = 0; heapNdx < (deUint32)m_heaps.size(); heapNdx++)
+ {
+ const Heap& heap = m_heaps[heapNdx];
+
+ for (size_t objectNdx = 0; objectNdx < heap.objects.size(); objectNdx++)
+ {
+ if (!!heap.objects[objectNdx].memory)
+ vkd.freeMemory(device, heap.objects[objectNdx].memory, (const VkAllocationCallbacks*)DE_NULL);
+ }
+ }
+}
+
+tcu::TestStatus RandomAllocFreeTestInstance::iterate (void)
+{
+ const VkDevice device = m_context.getDevice();
+ const DeviceInterface& vkd = m_context.getDeviceInterface();
+ TestLog& log = m_context.getTestContext().getLog();
+ bool allocateMore;
+
+ if (m_opNdx == 0)
+ {
+ log << TestLog::Message << "Performing " << m_opCount << " random VkAllocMemory() / VkFreeMemory() calls before freeing all memory." << TestLog::EndMessage;
+ log << TestLog::Message << "Using max one fourth of the memory in each memory heap." << TestLog::EndMessage;
+ }
+
+ if (m_opNdx >= m_opCount)
+ {
+ if (m_nonEmptyHeaps.empty())
+ return tcu::TestStatus::pass("Pass");
+ else
+ allocateMore = false;
+ }
+ else if (!m_nonEmptyHeaps.empty() && !m_nonFullHeaps.empty())
+ allocateMore = m_rng.getBool(); // Randomize if both operations are doable.
+ else if (m_nonEmptyHeaps.empty())
+ allocateMore = true; // Allocate more if there are no objects to free.
+ else if (m_nonFullHeaps.empty())
+ allocateMore = false; // Free objects if there is no free space for new objects.
+ else
+ {
+ allocateMore = false;
+ DE_FATAL("Fail");
+ }
+
+ if (allocateMore)
+ {
+ const size_t nonFullHeapNdx = (size_t)(m_rng.getUint32() % (deUint32)m_nonFullHeaps.size());
+ const size_t heapNdx = m_nonFullHeaps[nonFullHeapNdx];
+ Heap& heap = m_heaps[heapNdx];
+ const MemoryType& memoryType = m_rng.choose<MemoryType>(heap.types.begin(), heap.types.end());
+ const VkDeviceSize allocationSize = 1 + (m_rng.getUint64() % (deUint64)(heap.maxMemoryUsage - heap.memoryUsage));
+
+ const MemoryObject object =
+ {
+ (VkDeviceMemory)0,
+ allocationSize
+ };
+
+ heap.objects.push_back(object);
+
+ const VkMemoryAllocateInfo alloc =
+ {
+ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType
+ DE_NULL, // pNext
+ object.size, // allocationSize
+ memoryType.index // memoryTypeIndex;
+ };
+
+ VK_CHECK(vkd.allocateMemory(device, &alloc, (const VkAllocationCallbacks*)DE_NULL, &heap.objects.back().memory));
+ TCU_CHECK(!!heap.objects.back().memory);
+
+ // If heap was empty add to the non empty heaps.
+ if (heap.memoryUsage == 0)
+ {
+ DE_ASSERT(heap.objects.size() == 1);
+ m_nonEmptyHeaps.push_back(heapNdx);
+ }
+ else
+ DE_ASSERT(heap.objects.size() > 1);
+
+ heap.memoryUsage += allocationSize;
+
+ // If heap became full, remove from non full heaps.
+ if (heap.memoryUsage >= heap.maxMemoryUsage)
+ {
+ m_nonFullHeaps[nonFullHeapNdx] = m_nonFullHeaps.back();
+ m_nonFullHeaps.pop_back();
+ }
+ }
+ else
+ {
+ const size_t nonEmptyHeapNdx = (size_t)(m_rng.getUint32() % (deUint32)m_nonEmptyHeaps.size());
+ const size_t heapNdx = m_nonEmptyHeaps[nonEmptyHeapNdx];
+ Heap& heap = m_heaps[heapNdx];
+ const size_t memoryObjectNdx = m_rng.getUint32() % heap.objects.size();
+ MemoryObject& memoryObject = heap.objects[memoryObjectNdx];
+
+ vkd.freeMemory(device, memoryObject.memory, (const VkAllocationCallbacks*)DE_NULL);
+ memoryObject.memory = (VkDeviceMemory)0;
+
+ if (heap.memoryUsage >= heap.maxMemoryUsage && heap.memoryUsage - memoryObject.size < heap.maxMemoryUsage)
+ m_nonFullHeaps.push_back(heapNdx);
+
+ heap.memoryUsage -= memoryObject.size;
+
+ heap.objects[memoryObjectNdx] = heap.objects.back();
+ heap.objects.pop_back();
+
+ if (heap.memoryUsage == 0)
+ {
+ DE_ASSERT(heap.objects.empty());
+
+ m_nonEmptyHeaps[nonEmptyHeapNdx] = m_nonEmptyHeaps.back();
+ m_nonEmptyHeaps.pop_back();
+ }
+ else
+ DE_ASSERT(!heap.objects.empty());
+ }
+
+ m_opNdx++;
+ return tcu::TestStatus::incomplete();
+}
+
+
+} // anonymous
+
+tcu::TestCaseGroup* createAllocationTests (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "allocation", "Memory allocation tests."));
+
+ const VkDeviceSize KiB = 1024;
+ const VkDeviceSize MiB = 1024 * KiB;
+
+ const struct
+ {
+ const char* const str;
+ VkDeviceSize size;
+ } allocationSizes[] =
+ {
+ { "64", 64 },
+ { "128", 128 },
+ { "256", 256 },
+ { "512", 512 },
+ { "1KiB", 1*KiB },
+ { "4KiB", 4*KiB },
+ { "8KiB", 8*KiB },
+ { "1MiB", 1*MiB }
+ };
+
+ const float allocationPercents[] =
+ {
+ 0.01f, 0.1f, 0.25f
+ };
+
+ const int allocationCounts[] =
+ {
+ 1, 10, 100, 1000, -1
+ };
+
+ const struct
+ {
+ const char* const str;
+ const TestConfig::Order order;
+ } orders[] =
+ {
+ { "forward", TestConfig::ALLOC_FREE },
+ { "reverse", TestConfig::ALLOC_REVERSE_FREE },
+ { "mixed", TestConfig::MIXED_ALLOC_FREE }
+ };
+
+ {
+ de::MovePtr<tcu::TestCaseGroup> basicGroup (new tcu::TestCaseGroup(testCtx, "basic", "Basic memory allocation and free tests"));
+
+ for (size_t allocationSizeNdx = 0; allocationSizeNdx < DE_LENGTH_OF_ARRAY(allocationSizes); allocationSizeNdx++)
+ {
+ const VkDeviceSize allocationSize = allocationSizes[allocationSizeNdx].size;
+ const char* const allocationSizeName = allocationSizes[allocationSizeNdx].str;
+ de::MovePtr<tcu::TestCaseGroup> sizeGroup (new tcu::TestCaseGroup(testCtx, ("size_" + string(allocationSizeName)).c_str(), ("Test different allocation sizes " + de::toString(allocationSize)).c_str()));
+
+ for (size_t orderNdx = 0; orderNdx < DE_LENGTH_OF_ARRAY(orders); orderNdx++)
+ {
+ const TestConfig::Order order = orders[orderNdx].order;
+ const char* const orderName = orders[orderNdx].str;
+ const char* const orderDescription = orderName;
+ de::MovePtr<tcu::TestCaseGroup> orderGroup (new tcu::TestCaseGroup(testCtx, orderName, orderDescription));
+
+ for (size_t allocationCountNdx = 0; allocationCountNdx < DE_LENGTH_OF_ARRAY(allocationCounts); allocationCountNdx++)
+ {
+ const int allocationCount = allocationCounts[allocationCountNdx];
+
+ if (allocationCount != -1 && allocationCount * allocationSize > 50 * MiB)
+ continue;
+
+ TestConfig config;
+
+ config.memorySize = allocationSize;
+ config.order = order;
+
+ if (allocationCount == -1)
+ {
+ if (allocationSize < 4096)
+ continue;
+
+ config.memoryAllocationCount = (deUint32)(50 * MiB / allocationSize);
+
+ if (config.memoryAllocationCount == 0
+ || config.memoryAllocationCount == 1
+ || config.memoryAllocationCount == 10
+ || config.memoryAllocationCount == 100
+ || config.memoryAllocationCount == 1000)
+ continue;
+ }
+ else
+ config.memoryAllocationCount = allocationCount;
+
+ orderGroup->addChild(new InstanceFactory1<AllocateFreeTestInstance, TestConfig>(testCtx, tcu::NODETYPE_SELF_VALIDATE, "count_" + de::toString(config.memoryAllocationCount), "", config));
+ }
+
+ sizeGroup->addChild(orderGroup.release());
+ }
+
+ basicGroup->addChild(sizeGroup.release());
+ }
+
+ for (size_t allocationPercentNdx = 0; allocationPercentNdx < DE_LENGTH_OF_ARRAY(allocationPercents); allocationPercentNdx++)
+ {
+ const float allocationPercent = allocationPercents[allocationPercentNdx];
+ de::MovePtr<tcu::TestCaseGroup> percentGroup (new tcu::TestCaseGroup(testCtx, ("percent_" + de::toString((int)(100.0f * allocationPercent))).c_str(), ("Test different allocation percents " + de::toString(allocationPercent * 100.0f)).c_str()));
+
+ for (size_t orderNdx = 0; orderNdx < DE_LENGTH_OF_ARRAY(orders); orderNdx++)
+ {
+ const TestConfig::Order order = orders[orderNdx].order;
+ const char* const orderName = orders[orderNdx].str;
+ const char* const orderDescription = orderName;
+ de::MovePtr<tcu::TestCaseGroup> orderGroup (new tcu::TestCaseGroup(testCtx, orderName, orderDescription));
+
+ for (size_t allocationCountNdx = 0; allocationCountNdx < DE_LENGTH_OF_ARRAY(allocationCounts); allocationCountNdx++)
+ {
+ const int allocationCount = allocationCounts[allocationCountNdx];
+
+ if (allocationCount != -1 && allocationCount * allocationPercent > 0.25f)
+ continue;
+
+ TestConfig config;
+
+ config.memoryPercentage = allocationPercent;
+ config.order = order;
+
+ if (allocationCount == -1)
+ {
+ config.memoryAllocationCount = (int)(0.25f / allocationPercent);
+
+ if (config.memoryAllocationCount == 0
+ || config.memoryAllocationCount == 1
+ || config.memoryAllocationCount == 10
+ || config.memoryAllocationCount == 100
+ || config.memoryAllocationCount == 1000)
+ continue;
+ }
+ else
+ config.memoryAllocationCount = allocationCount;
+
+ orderGroup->addChild(new InstanceFactory1<AllocateFreeTestInstance, TestConfig>(testCtx, tcu::NODETYPE_SELF_VALIDATE, "count_" + de::toString(config.memoryAllocationCount), "", config));
+ }
+
+ percentGroup->addChild(orderGroup.release());
+ }
+
+ basicGroup->addChild(percentGroup.release());
+ }
+
+ group->addChild(basicGroup.release());
+ }
+
+ {
+ const deUint32 caseCount = 100;
+ de::MovePtr<tcu::TestCaseGroup> randomGroup (new tcu::TestCaseGroup(testCtx, "random", "Random memory allocation tests."));
+
+ for (deUint32 caseNdx = 0; caseNdx < caseCount; caseNdx++)
+ {
+ const deUint32 seed = deInt32Hash(caseNdx ^ 32480);
+
+ randomGroup->addChild(new InstanceFactory1<RandomAllocFreeTestInstance, deUint32>(testCtx, tcu::NODETYPE_SELF_VALIDATE, de::toString(caseNdx), "Random case", seed));
+ }
+
+ group->addChild(randomGroup.release());
+ }
+
+ return group.release();
+}
+
+} // memory
+} // vkt
--- /dev/null
+#ifndef _VKTMEMORYALLOCATIONTESTS_HPP
+#define _VKTMEMORYALLOCATIONTESTS_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Simple memory allocation tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+namespace memory
+{
+
+tcu::TestCaseGroup* createAllocationTests (tcu::TestContext& testCtx);
+
+} // memory
+} // vkt
+
+#endif // _VKTMEMORYALLOCATIONTESTS_HPP
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Simple memory mapping tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "vktMemoryMappingTests.hpp"
+
+#include "vktTestCaseUtil.hpp"
+
+#include "tcuMaybe.hpp"
+#include "tcuResultCollector.hpp"
+#include "tcuTestLog.hpp"
+
+#include "vkDeviceUtil.hpp"
+#include "vkPlatform.hpp"
+#include "vkQueryUtil.hpp"
+#include "vkRef.hpp"
+#include "vkStrUtil.hpp"
+
+#include "deRandom.hpp"
+#include "deSharedPtr.hpp"
+#include "deStringUtil.hpp"
+#include "deUniquePtr.hpp"
+
+#include <string>
+#include <vector>
+
+using tcu::Maybe;
+using tcu::TestLog;
+
+using de::SharedPtr;
+
+using std::string;
+using std::vector;
+
+using namespace vk;
+
+namespace vkt
+{
+namespace memory
+{
+namespace
+{
+Move<VkDeviceMemory> allocMemory (const DeviceInterface& vk, VkDevice device, VkDeviceSize pAllocInfo_allocationSize, deUint32 pAllocInfo_memoryTypeIndex)
+{
+ VkDeviceMemory object = 0;
+ const VkMemoryAllocateInfo pAllocInfo =
+ {
+ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+ DE_NULL,
+ pAllocInfo_allocationSize,
+ pAllocInfo_memoryTypeIndex,
+ };
+ VK_CHECK(vk.allocateMemory(device, &pAllocInfo, (const VkAllocationCallbacks*)DE_NULL, &object));
+ return Move<VkDeviceMemory>(check<VkDeviceMemory>(object), Deleter<VkDeviceMemory>(vk, device));
+}
+
+struct MemoryRange
+{
+ MemoryRange (VkDeviceSize offset_ = ~(VkDeviceSize)0, VkDeviceSize size_ = ~(VkDeviceSize)0)
+ : offset (offset_)
+ , size (size_)
+ {
+ }
+
+ VkDeviceSize offset;
+ VkDeviceSize size;
+};
+
+struct TestConfig
+{
+ TestConfig (void)
+ : allocationSize (~(VkDeviceSize)0)
+ {
+ }
+
+ VkDeviceSize allocationSize;
+ deUint32 seed;
+
+ MemoryRange mapping;
+ vector<MemoryRange> flushMappings;
+ vector<MemoryRange> invalidateMappings;
+ bool remap;
+};
+
+bool compareAndLogBuffer (TestLog& log, size_t size, const deUint8* result, const deUint8* reference)
+{
+ size_t failedBytes = 0;
+ size_t firstFailed = (size_t)-1;
+
+ for (size_t ndx = 0; ndx < size; ndx++)
+ {
+ if (result[ndx] != reference[ndx])
+ {
+ failedBytes++;
+
+ if (firstFailed == (size_t)-1)
+ firstFailed = ndx;
+ }
+ }
+
+ if (failedBytes > 0)
+ {
+ log << TestLog::Message << "Comparison failed. Failed bytes " << failedBytes << ". First failed at offset " << firstFailed << "." << TestLog::EndMessage;
+
+ std::ostringstream expectedValues;
+ std::ostringstream resultValues;
+
+ for (size_t ndx = firstFailed; ndx < firstFailed + 10 && ndx < size; ndx++)
+ {
+ if (ndx != firstFailed)
+ {
+ expectedValues << ", ";
+ resultValues << ", ";
+ }
+
+ expectedValues << reference[ndx];
+ resultValues << result[ndx];
+ }
+
+ if (firstFailed + 10 < size)
+ {
+ expectedValues << "...";
+ resultValues << "...";
+ }
+
+ log << TestLog::Message << "Expected values at offset: " << firstFailed << ", " << expectedValues.str() << TestLog::EndMessage;
+ log << TestLog::Message << "Result values at offset: " << firstFailed << ", " << resultValues.str() << TestLog::EndMessage;
+
+ return false;
+ }
+ else
+ return true;
+}
+
+tcu::TestStatus testMemoryMapping (Context& context, const TestConfig config)
+{
+ TestLog& log = context.getTestContext().getLog();
+ tcu::ResultCollector result (log);
+ const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
+ const VkDevice device = context.getDevice();
+ const InstanceInterface& vki = context.getInstanceInterface();
+ const DeviceInterface& vkd = context.getDeviceInterface();
+ const VkPhysicalDeviceMemoryProperties memoryProperties = getPhysicalDeviceMemoryProperties(vki, physicalDevice);
+
+ {
+ const tcu::ScopedLogSection section (log, "TestCaseInfo", "TestCaseInfo");
+
+ log << TestLog::Message << "Seed: " << config.seed << TestLog::EndMessage;
+ log << TestLog::Message << "Allocation size: " << config.allocationSize << TestLog::EndMessage;
+ log << TestLog::Message << "Mapping, offset: " << config.mapping.offset << ", size: " << config.mapping.size << TestLog::EndMessage;
+
+ if (!config.flushMappings.empty())
+ {
+ log << TestLog::Message << "Invalidating following ranges:" << TestLog::EndMessage;
+
+ for (size_t ndx = 0; ndx < config.flushMappings.size(); ndx++)
+ log << TestLog::Message << "\tOffset: " << config.flushMappings[ndx].offset << ", Size: " << config.flushMappings[ndx].size << TestLog::EndMessage;
+ }
+
+ if (config.remap)
+ log << TestLog::Message << "Remapping memory between flush and invalidation." << TestLog::EndMessage;
+
+ if (!config.invalidateMappings.empty())
+ {
+ log << TestLog::Message << "Flushing following ranges:" << TestLog::EndMessage;
+
+ for (size_t ndx = 0; ndx < config.invalidateMappings.size(); ndx++)
+ log << TestLog::Message << "\tOffset: " << config.invalidateMappings[ndx].offset << ", Size: " << config.invalidateMappings[ndx].size << TestLog::EndMessage;
+ }
+ }
+
+ for (deUint32 memoryTypeIndex = 0; memoryTypeIndex < memoryProperties.memoryTypeCount; memoryTypeIndex++)
+ {
+ try
+ {
+ const tcu::ScopedLogSection section (log, "MemoryType" + de::toString(memoryTypeIndex), "MemoryType" + de::toString(memoryTypeIndex));
+ const VkMemoryType& memoryType = memoryProperties.memoryTypes[memoryTypeIndex];
+ const VkMemoryHeap& memoryHeap = memoryProperties.memoryHeaps[memoryType.heapIndex];
+
+ log << TestLog::Message << "MemoryType: " << memoryType << TestLog::EndMessage;
+ log << TestLog::Message << "MemoryHeap: " << memoryHeap << TestLog::EndMessage;
+
+ if ((memoryType.propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0)
+ {
+ log << TestLog::Message << "Memory type doesn't support mapping." << TestLog::EndMessage;
+ }
+ else
+ {
+ const Unique<VkDeviceMemory> memory (allocMemory(vkd, device, config.allocationSize, memoryTypeIndex));
+ de::Random rng (config.seed);
+ vector<deUint8> reference ((size_t)config.allocationSize);
+ deUint8* mapping = DE_NULL;
+
+ {
+ void* ptr;
+ VK_CHECK(vkd.mapMemory(device, *memory, config.mapping.offset, config.mapping.size, 0u, &ptr));
+ TCU_CHECK(ptr);
+
+ mapping = (deUint8*)ptr;
+ }
+
+ for (VkDeviceSize ndx = 0; ndx < config.mapping.size; ndx++)
+ {
+ const deUint8 val = rng.getUint8();
+
+ mapping[ndx] = val;
+ reference[(size_t)(config.mapping.offset + ndx)] = val;
+ }
+
+ if (!config.flushMappings.empty())
+ {
+ vector<VkMappedMemoryRange> ranges;
+
+ for (size_t ndx = 0; ndx < config.flushMappings.size(); ndx++)
+ {
+ const VkMappedMemoryRange range =
+ {
+ VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
+ DE_NULL,
+
+ *memory,
+ config.flushMappings[ndx].offset,
+ config.flushMappings[ndx].size
+ };
+
+ ranges.push_back(range);
+ }
+
+ VK_CHECK(vkd.flushMappedMemoryRanges(device, (deUint32)ranges.size(), &ranges[0]));
+ }
+
+ if (config.remap)
+ {
+ void* ptr;
+ vkd.unmapMemory(device, *memory);
+ VK_CHECK(vkd.mapMemory(device, *memory, config.mapping.offset, config.mapping.size, 0u, &ptr));
+ TCU_CHECK(ptr);
+
+ mapping = (deUint8*)ptr;
+ }
+
+ if (!config.invalidateMappings.empty())
+ {
+ vector<VkMappedMemoryRange> ranges;
+
+ for (size_t ndx = 0; ndx < config.invalidateMappings.size(); ndx++)
+ {
+ const VkMappedMemoryRange range =
+ {
+ VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
+ DE_NULL,
+
+ *memory,
+ config.invalidateMappings[ndx].offset,
+ config.invalidateMappings[ndx].size
+ };
+
+ ranges.push_back(range);
+ }
+
+ VK_CHECK(vkd.invalidateMappedMemoryRanges(device, (deUint32)ranges.size(), &ranges[0]));
+ }
+
+ if (!compareAndLogBuffer(log, (size_t)config.mapping.size, mapping, &reference[(size_t)config.mapping.offset]))
+ result.fail("Unexpected values read from mapped memory.");
+
+ vkd.unmapMemory(device, *memory);
+ }
+ }
+ catch (const tcu::TestError& error)
+ {
+ result.fail(error.getMessage());
+ }
+ }
+
+ return tcu::TestStatus(result.getResult(), result.getMessage());
+}
+
+class MemoryMapping
+{
+public:
+ MemoryMapping (const MemoryRange& range,
+ void* ptr,
+ deUint16* refPtr);
+
+ void randomRead (de::Random& rng);
+ void randomWrite (de::Random& rng);
+ void randomModify (de::Random& rng);
+
+private:
+ MemoryRange m_range;
+ void* m_ptr;
+ deUint16* m_refPtr;
+};
+
+MemoryMapping::MemoryMapping (const MemoryRange& range,
+ void* ptr,
+ deUint16* refPtr)
+ : m_range (range)
+ , m_ptr (ptr)
+ , m_refPtr (refPtr)
+{
+ DE_ASSERT(range.size > 0);
+}
+
+void MemoryMapping::randomRead (de::Random& rng)
+{
+ const size_t count = (size_t)rng.getInt(0, 100);
+
+ for (size_t ndx = 0; ndx < count; ndx++)
+ {
+ const size_t pos = (size_t)(rng.getUint64() % (deUint64)m_range.size);
+ const deUint8 val = ((deUint8*) m_ptr)[pos];
+
+ if (m_refPtr[pos] < 256)
+ TCU_CHECK((deUint16)val == m_refPtr[pos]);
+ else
+ m_refPtr[pos] = (deUint16)val;
+ }
+}
+
+void MemoryMapping::randomWrite (de::Random& rng)
+{
+ const size_t count = (size_t)rng.getInt(0, 100);
+
+ for (size_t ndx = 0; ndx < count; ndx++)
+ {
+ const size_t pos = (size_t)(rng.getUint64() % (deUint64)m_range.size);
+ const deUint8 val = rng.getUint8();
+
+ ((deUint8*)m_ptr)[pos] = val;
+ m_refPtr[pos] = (deUint16)val;
+ }
+}
+
+void MemoryMapping::randomModify (de::Random& rng)
+{
+ const size_t count = (size_t)rng.getInt(0, 100);
+
+ for (size_t ndx = 0; ndx < count; ndx++)
+ {
+ const size_t pos = (size_t)(rng.getUint64() % (deUint64)m_range.size);
+ const deUint8 val = ((deUint8*)m_ptr)[pos];
+ const deUint8 mask = rng.getUint8();
+
+ if (m_refPtr[pos] < 256)
+ TCU_CHECK((deUint16)val == m_refPtr[pos]);
+
+ ((deUint8*)m_ptr)[pos] = val ^ mask;
+ m_refPtr[pos] = (deUint16)(val ^ mask);
+ }
+}
+
+void randomRanges (de::Random& rng, vector<VkMappedMemoryRange>& ranges, size_t count, VkDeviceMemory memory, VkDeviceSize maxSize)
+{
+ ranges.resize(count);
+
+ for (size_t rangeNdx = 0; rangeNdx < count; rangeNdx++)
+ {
+ const VkDeviceSize size = (maxSize > 1 ? (VkDeviceSize)(1 + (rng.getUint64() % (deUint64)(maxSize - 1))) : 1);
+ const VkDeviceSize offset = (VkDeviceSize)(rng.getUint64() % (deUint64)(maxSize - size + 1));
+
+ const VkMappedMemoryRange range =
+ {
+ VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
+ DE_NULL,
+
+ memory,
+ offset,
+ size
+ };
+ ranges[rangeNdx] = range;
+ }
+}
+
+class MemoryObject
+{
+public:
+ MemoryObject (const DeviceInterface& vkd,
+ VkDevice device,
+ VkDeviceSize size,
+ deUint32 memoryTypeIndex);
+
+ ~MemoryObject (void);
+
+ MemoryMapping* mapRandom (const DeviceInterface& vkd, VkDevice device, de::Random& rng);
+ void unmap (void);
+
+ void randomFlush (const DeviceInterface& vkd, VkDevice device, de::Random& rng);
+ void randomInvalidate (const DeviceInterface& vkd, VkDevice device, de::Random& rng);
+
+ VkDeviceSize getSize (void) const { return m_size; }
+ MemoryMapping* getMapping (void) { return m_mapping; }
+
+private:
+ const DeviceInterface& m_vkd;
+ VkDevice m_device;
+
+ deUint32 m_memoryTypeIndex;
+ VkDeviceSize m_size;
+
+ Move<VkDeviceMemory> m_memory;
+
+ MemoryMapping* m_mapping;
+ vector<deUint16> m_reference;
+};
+
+MemoryObject::MemoryObject (const DeviceInterface& vkd,
+ VkDevice device,
+ VkDeviceSize size,
+ deUint32 memoryTypeIndex)
+ : m_vkd (vkd)
+ , m_device (device)
+ , m_memoryTypeIndex (memoryTypeIndex)
+ , m_size (size)
+ , m_mapping (DE_NULL)
+{
+ m_memory = allocMemory(m_vkd, m_device, m_size, m_memoryTypeIndex);
+ m_reference.resize((size_t)m_size, 0xFFFFu);
+}
+
+MemoryObject::~MemoryObject (void)
+{
+ delete m_mapping;
+}
+
+MemoryMapping* MemoryObject::mapRandom (const DeviceInterface& vkd, VkDevice device, de::Random& rng)
+{
+ const VkDeviceSize size = (m_size > 1 ? (VkDeviceSize)(1 + (rng.getUint64() % (deUint64)(m_size - 1))) : 1);
+ const VkDeviceSize offset = (VkDeviceSize)(rng.getUint64() % (deUint64)(m_size - size + 1));
+ void* ptr;
+
+ DE_ASSERT(!m_mapping);
+
+ VK_CHECK(vkd.mapMemory(device, *m_memory, offset, size, 0u, &ptr));
+ TCU_CHECK(ptr);
+ m_mapping = new MemoryMapping(MemoryRange(offset, size), ptr, &(m_reference[(size_t)offset]));
+
+ return m_mapping;
+}
+
+void MemoryObject::unmap (void)
+{
+ m_vkd.unmapMemory(m_device, *m_memory);
+
+ delete m_mapping;
+ m_mapping = DE_NULL;
+}
+
+void MemoryObject::randomFlush (const DeviceInterface& vkd, VkDevice device, de::Random& rng)
+{
+ const size_t rangeCount = (size_t)rng.getInt(0, 10);
+ vector<VkMappedMemoryRange> ranges (rangeCount);
+
+ randomRanges(rng, ranges, rangeCount, *m_memory, m_size);
+
+ VK_CHECK(vkd.flushMappedMemoryRanges(device, (deUint32)ranges.size(), &ranges[0]));
+}
+
+void MemoryObject::randomInvalidate (const DeviceInterface& vkd, VkDevice device, de::Random& rng)
+{
+ const size_t rangeCount = (size_t)rng.getInt(0, 10);
+ vector<VkMappedMemoryRange> ranges (rangeCount);
+
+ randomRanges(rng, ranges, rangeCount, *m_memory, m_size);
+
+ VK_CHECK(vkd.invalidateMappedMemoryRanges(device, (deUint32)ranges.size(), &ranges[0]));
+}
+
+enum
+{
+ // Use only 1/8 of each memory heap.
+ MAX_MEMORY_USAGE_DIV = 8
+};
+
+template<typename T>
+void removeFirstEqual (vector<T>& vec, const T& val)
+{
+ for (size_t ndx = 0; ndx < vec.size(); ndx++)
+ {
+ if (vec[ndx] == val)
+ {
+ vec[ndx] = vec.back();
+ vec.pop_back();
+ return;
+ }
+ }
+}
+
+class MemoryHeap
+{
+public:
+ MemoryHeap (const VkMemoryHeap& heap,
+ const vector<deUint32>& memoryTypes)
+ : m_heap (heap)
+ , m_memoryTypes (memoryTypes)
+ , m_usage (0)
+ {
+ }
+
+ ~MemoryHeap (void)
+ {
+ for (vector<MemoryObject*>::iterator iter = m_objects.begin(); iter != m_objects.end(); ++iter)
+ delete *iter;
+ }
+
+ bool full (void) const { return m_usage * MAX_MEMORY_USAGE_DIV >= m_heap.size; }
+ bool empty (void) const { return m_usage == 0; }
+
+ MemoryObject* allocateRandom (const DeviceInterface& vkd, VkDevice device, de::Random& rng)
+ {
+ const VkDeviceSize size = 1 + (rng.getUint64() % ((m_heap.size / MAX_MEMORY_USAGE_DIV) - m_usage - 1));
+ const deUint32 type = rng.choose<deUint32>(m_memoryTypes.begin(), m_memoryTypes.end());
+ MemoryObject* const object = new MemoryObject(vkd, device, size, type);
+
+ m_usage += size;
+ m_objects.push_back(object);
+
+ return object;
+ }
+
+ MemoryObject* getRandomObject (de::Random& rng) const
+ {
+ return rng.choose<MemoryObject*>(m_objects.begin(), m_objects.end());
+ }
+
+ void free (MemoryObject* object)
+ {
+ removeFirstEqual(m_objects, object);
+ m_usage -= object->getSize();
+ delete object;
+ }
+
+private:
+ VkMemoryHeap m_heap;
+ vector<deUint32> m_memoryTypes;
+
+ VkDeviceSize m_usage;
+ vector<MemoryObject*> m_objects;
+};
+
+class RandomMemoryMappingInstance : public TestInstance
+{
+public:
+ RandomMemoryMappingInstance (Context& context, deUint32 seed)
+ : TestInstance (context)
+ , m_rng (seed)
+ , m_opNdx (0)
+ {
+ const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
+ const InstanceInterface& vki = context.getInstanceInterface();
+ const VkPhysicalDeviceMemoryProperties memoryProperties = getPhysicalDeviceMemoryProperties(vki, physicalDevice);
+
+ // Initialize heaps
+ {
+ vector<vector<deUint32> > memoryTypes (memoryProperties.memoryHeapCount);
+
+ for (deUint32 memoryTypeNdx = 0; memoryTypeNdx < memoryProperties.memoryTypeCount; memoryTypeNdx++)
+ {
+ if (memoryProperties.memoryTypes[memoryTypeNdx].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
+ memoryTypes[memoryProperties.memoryTypes[memoryTypeNdx].heapIndex].push_back(memoryTypeNdx);
+ }
+
+ for (deUint32 heapIndex = 0; heapIndex < memoryProperties.memoryHeapCount; heapIndex++)
+ {
+ const VkMemoryHeap heapInfo = memoryProperties.memoryHeaps[heapIndex];
+
+ if (!memoryTypes[heapIndex].empty())
+ {
+ const de::SharedPtr<MemoryHeap> heap (new MemoryHeap(heapInfo, memoryTypes[heapIndex]));
+
+ if (!heap->full())
+ m_nonFullHeaps.push_back(heap);
+ }
+ }
+ }
+ }
+
+ ~RandomMemoryMappingInstance (void)
+ {
+ }
+
+ tcu::TestStatus iterate (void)
+ {
+ const size_t opCount = 100;
+ const float memoryOpProbability = 0.5f; // 0.50
+ const float flushInvalidateProbability = 0.4f; // 0.20
+ const float mapProbability = 0.50f; // 0.15
+ const float unmapProbability = 0.25f; // 0.075
+
+ const float allocProbability = 0.75f; // Versun free
+
+ const VkDevice device = m_context.getDevice();
+ const DeviceInterface& vkd = m_context.getDeviceInterface();
+
+ if (m_opNdx < opCount)
+ {
+ if (!m_memoryMappings.empty() && m_rng.getFloat() < memoryOpProbability)
+ {
+ // Perform operations on mapped memory
+ MemoryMapping* const mapping = m_rng.choose<MemoryMapping*>(m_memoryMappings.begin(), m_memoryMappings.end());
+
+ enum Op
+ {
+ OP_READ = 0,
+ OP_WRITE,
+ OP_MODIFY,
+ OP_LAST
+ };
+
+ const Op op = (Op)(m_rng.getUint32() % OP_LAST);
+
+ switch (op)
+ {
+ case OP_READ:
+ mapping->randomRead(m_rng);
+ break;
+
+ case OP_WRITE:
+ mapping->randomWrite(m_rng);
+ break;
+
+ case OP_MODIFY:
+ mapping->randomModify(m_rng);
+ break;
+
+ default:
+ DE_FATAL("Invalid operation");
+ }
+ }
+ else if (!m_mappedMemoryObjects.empty() && m_rng.getFloat() < flushInvalidateProbability)
+ {
+ MemoryObject* const object = m_rng.choose<MemoryObject*>(m_mappedMemoryObjects.begin(), m_mappedMemoryObjects.end());
+
+ if (m_rng.getBool())
+ object->randomFlush(vkd, device, m_rng);
+ else
+ object->randomInvalidate(vkd, device, m_rng);
+ }
+ else if (!m_mappedMemoryObjects.empty() && m_rng.getFloat() < unmapProbability)
+ {
+ // Unmap memory object
+ MemoryObject* const object = m_rng.choose<MemoryObject*>(m_mappedMemoryObjects.begin(), m_mappedMemoryObjects.end());
+
+ // Remove mapping
+ removeFirstEqual(m_memoryMappings, object->getMapping());
+
+ object->unmap();
+ removeFirstEqual(m_mappedMemoryObjects, object);
+ m_nonMappedMemoryObjects.push_back(object);
+ }
+ else if (!m_nonMappedMemoryObjects.empty() && m_rng.getFloat() < mapProbability)
+ {
+ // Map memory object
+ MemoryObject* const object = m_rng.choose<MemoryObject*>(m_nonMappedMemoryObjects.begin(), m_nonMappedMemoryObjects.end());
+ MemoryMapping* mapping = object->mapRandom(vkd, device, m_rng);
+
+ m_memoryMappings.push_back(mapping);
+ m_mappedMemoryObjects.push_back(object);
+ removeFirstEqual(m_nonMappedMemoryObjects, object);
+ }
+ else
+ {
+ if (!m_nonFullHeaps.empty() && (m_nonEmptyHeaps.empty() || m_rng.getFloat() < allocProbability))
+ {
+ // Allocate more memory objects
+ de::SharedPtr<MemoryHeap> const heap = m_rng.choose<de::SharedPtr<MemoryHeap> >(m_nonFullHeaps.begin(), m_nonFullHeaps.end());
+
+ if (heap->empty())
+ m_nonEmptyHeaps.push_back(heap);
+
+ {
+ MemoryObject* const object = heap->allocateRandom(vkd, device, m_rng);
+
+ if (heap->full())
+ removeFirstEqual(m_nonFullHeaps, heap);
+
+ m_nonMappedMemoryObjects.push_back(object);
+ }
+ }
+ else
+ {
+ // Free memory objects
+ de::SharedPtr<MemoryHeap> const heap = m_rng.choose<de::SharedPtr<MemoryHeap> >(m_nonEmptyHeaps.begin(), m_nonEmptyHeaps.end());
+ MemoryObject* const object = heap->getRandomObject(m_rng);
+
+ // Remove mapping
+ if (object->getMapping())
+ removeFirstEqual(m_memoryMappings, object->getMapping());
+
+ removeFirstEqual(m_mappedMemoryObjects, object);
+ removeFirstEqual(m_nonMappedMemoryObjects, object);
+
+ if (heap->full())
+ m_nonFullHeaps.push_back(heap);
+
+ heap->free(object);
+
+ if (heap->empty())
+ removeFirstEqual(m_nonEmptyHeaps, heap);
+ }
+ }
+
+ m_opNdx++;
+ return tcu::TestStatus::incomplete();
+ }
+ else
+ return tcu::TestStatus::pass("Pass");
+ }
+
+private:
+ de::Random m_rng;
+ size_t m_opNdx;
+
+ vector<de::SharedPtr<MemoryHeap> > m_nonEmptyHeaps;
+ vector<de::SharedPtr<MemoryHeap> > m_nonFullHeaps;
+
+ vector<MemoryObject*> m_mappedMemoryObjects;
+ vector<MemoryObject*> m_nonMappedMemoryObjects;
+ vector<MemoryMapping*> m_memoryMappings;
+};
+
+enum Op
+{
+ OP_NONE = 0,
+
+ OP_FLUSH,
+ OP_SUB_FLUSH,
+ OP_SUB_FLUSH_SEPARATE,
+ OP_SUB_FLUSH_OVERLAPPING,
+
+ OP_INVALIDATE,
+ OP_SUB_INVALIDATE,
+ OP_SUB_INVALIDATE_SEPARATE,
+ OP_SUB_INVALIDATE_OVERLAPPING,
+
+ OP_REMAP,
+
+ OP_LAST
+};
+
+TestConfig subMappedConfig (VkDeviceSize allocationSize,
+ const MemoryRange& mapping,
+ Op op,
+ deUint32 seed)
+{
+ TestConfig config;
+
+ config.allocationSize = allocationSize;
+ config.seed = seed;
+ config.mapping = mapping;
+ config.remap = false;
+
+ switch (op)
+ {
+ case OP_NONE:
+ return config;
+
+ case OP_REMAP:
+ config.remap = true;
+ return config;
+
+ case OP_FLUSH:
+ config.flushMappings = vector<MemoryRange>(1, MemoryRange(0, allocationSize));
+ return config;
+
+ case OP_SUB_FLUSH:
+ DE_ASSERT(allocationSize / 4 > 0);
+
+ config.flushMappings = vector<MemoryRange>(1, MemoryRange(allocationSize / 4, allocationSize / 2));
+ return config;
+
+ case OP_SUB_FLUSH_SEPARATE:
+ DE_ASSERT(allocationSize / 2 > 0);
+
+ config.flushMappings.push_back(MemoryRange(allocationSize / 2, allocationSize - (allocationSize / 2)));
+ config.flushMappings.push_back(MemoryRange(0, allocationSize / 2));
+
+ return config;
+
+ case OP_SUB_FLUSH_OVERLAPPING:
+ DE_ASSERT((allocationSize / 3) > 0);
+
+ config.flushMappings.push_back(MemoryRange(allocationSize / 3, allocationSize - (allocationSize / 2)));
+ config.flushMappings.push_back(MemoryRange(0, (2 * allocationSize) / 3));
+
+ return config;
+
+ case OP_INVALIDATE:
+ config.invalidateMappings = vector<MemoryRange>(1, MemoryRange(0, allocationSize));
+ return config;
+
+ case OP_SUB_INVALIDATE:
+ DE_ASSERT(allocationSize / 4 > 0);
+
+ config.invalidateMappings = vector<MemoryRange>(1, MemoryRange(allocationSize / 4, allocationSize / 2));
+ return config;
+
+ case OP_SUB_INVALIDATE_SEPARATE:
+ DE_ASSERT(allocationSize / 2 > 0);
+
+ config.invalidateMappings.push_back(MemoryRange(allocationSize / 2, allocationSize - (allocationSize / 2)));
+ config.invalidateMappings.push_back(MemoryRange(0, allocationSize / 2));
+
+ return config;
+
+ case OP_SUB_INVALIDATE_OVERLAPPING:
+ DE_ASSERT((allocationSize / 3) > 0);
+
+ config.invalidateMappings.push_back(MemoryRange(allocationSize / 3, allocationSize - (allocationSize / 2)));
+ config.invalidateMappings.push_back(MemoryRange(0, (2 * allocationSize) / 3));
+
+ return config;
+
+ default:
+ DE_FATAL("Unknown Op");
+ return TestConfig();
+ }
+}
+
+TestConfig fullMappedConfig (VkDeviceSize allocationSize,
+ Op op,
+ deUint32 seed)
+{
+ return subMappedConfig(allocationSize, MemoryRange(0, allocationSize), op, seed);
+}
+
+} // anonymous
+
+tcu::TestCaseGroup* createMappingTests (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "mapping", "Memory mapping tests."));
+
+ const VkDeviceSize allocationSizes[] =
+ {
+ 33, 257, 4087, 8095, 1*1024*1024 + 1
+ };
+
+ const VkDeviceSize offsets[] =
+ {
+ 0, 17, 129, 255, 1025, 32*1024+1
+ };
+
+ const VkDeviceSize sizes[] =
+ {
+ 31, 255, 1025, 4085, 1*1024*1024 - 1
+ };
+
+ const struct
+ {
+ const Op op;
+ const char* const name;
+ } ops[] =
+ {
+ { OP_NONE, "simple" },
+ { OP_REMAP, "remap" },
+ { OP_FLUSH, "flush" },
+ { OP_SUB_FLUSH, "subflush" },
+ { OP_SUB_FLUSH_SEPARATE, "subflush_separate" },
+ { OP_SUB_FLUSH_SEPARATE, "subflush_overlapping" },
+
+ { OP_INVALIDATE, "invalidate" },
+ { OP_SUB_INVALIDATE, "subinvalidate" },
+ { OP_SUB_INVALIDATE_SEPARATE, "subinvalidate_separate" },
+ { OP_SUB_INVALIDATE_SEPARATE, "subinvalidate_overlapping" }
+ };
+
+ // .full
+ {
+ de::MovePtr<tcu::TestCaseGroup> fullGroup (new tcu::TestCaseGroup(testCtx, "full", "Map memory completely."));
+
+ for (size_t allocationSizeNdx = 0; allocationSizeNdx < DE_LENGTH_OF_ARRAY(allocationSizes); allocationSizeNdx++)
+ {
+ const VkDeviceSize allocationSize = allocationSizes[allocationSizeNdx];
+ de::MovePtr<tcu::TestCaseGroup> allocationSizeGroup (new tcu::TestCaseGroup(testCtx, de::toString(allocationSize).c_str(), ""));
+
+ for (size_t opNdx = 0; opNdx < DE_LENGTH_OF_ARRAY(ops); opNdx++)
+ {
+ const Op op = ops[opNdx].op;
+ const char* const name = ops[opNdx].name;
+ const deUint32 seed = (deUint32)(opNdx * allocationSizeNdx);
+ const TestConfig config = fullMappedConfig(allocationSize, op, seed);
+
+ addFunctionCase(allocationSizeGroup.get(), name, name, testMemoryMapping, config);
+ }
+
+ fullGroup->addChild(allocationSizeGroup.release());
+ }
+
+ group->addChild(fullGroup.release());
+ }
+
+ // .sub
+ {
+ de::MovePtr<tcu::TestCaseGroup> subGroup (new tcu::TestCaseGroup(testCtx, "sub", "Map part of the memory."));
+
+ for (size_t allocationSizeNdx = 0; allocationSizeNdx < DE_LENGTH_OF_ARRAY(allocationSizes); allocationSizeNdx++)
+ {
+ const VkDeviceSize allocationSize = allocationSizes[allocationSizeNdx];
+ de::MovePtr<tcu::TestCaseGroup> allocationSizeGroup (new tcu::TestCaseGroup(testCtx, de::toString(allocationSize).c_str(), ""));
+
+ for (size_t offsetNdx = 0; offsetNdx < DE_LENGTH_OF_ARRAY(offsets); offsetNdx++)
+ {
+ const VkDeviceSize offset = offsets[offsetNdx];
+
+ if (offset >= allocationSize)
+ continue;
+
+ de::MovePtr<tcu::TestCaseGroup> offsetGroup (new tcu::TestCaseGroup(testCtx, ("offset_" + de::toString(offset)).c_str(), ""));
+
+ for (size_t sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); sizeNdx++)
+ {
+ const VkDeviceSize size = sizes[sizeNdx];
+
+ if (offset + size > allocationSize)
+ continue;
+
+ if (offset == 0 && size == allocationSize)
+ continue;
+
+ de::MovePtr<tcu::TestCaseGroup> sizeGroup (new tcu::TestCaseGroup(testCtx, ("size_" + de::toString(size)).c_str(), ""));
+
+ for (size_t opNdx = 0; opNdx < DE_LENGTH_OF_ARRAY(ops); opNdx++)
+ {
+ const deUint32 seed = (deUint32)(opNdx * allocationSizeNdx);
+ const Op op = ops[opNdx].op;
+ const char* const name = ops[opNdx].name;
+ const TestConfig config = subMappedConfig(allocationSize, MemoryRange(offset, size), op, seed);
+
+ addFunctionCase(sizeGroup.get(), name, name, testMemoryMapping, config);
+ }
+
+ offsetGroup->addChild(sizeGroup.release());
+ }
+
+ allocationSizeGroup->addChild(offsetGroup.release());
+ }
+
+ subGroup->addChild(allocationSizeGroup.release());
+ }
+
+ group->addChild(subGroup.release());
+ }
+
+ // .random
+ {
+ de::MovePtr<tcu::TestCaseGroup> randomGroup (new tcu::TestCaseGroup(testCtx, "random", "Random memory mapping tests."));
+ de::Random rng (3927960301u);
+
+ for (size_t ndx = 0; ndx < 100; ndx++)
+ {
+ const deUint32 seed = rng.getUint32();
+ const std::string name = de::toString(ndx);
+
+ randomGroup->addChild(new InstanceFactory1<RandomMemoryMappingInstance, deUint32>(testCtx, tcu::NODETYPE_SELF_VALIDATE, de::toString(ndx), "Random case", seed));
+ }
+
+ group->addChild(randomGroup.release());
+ }
+
+ return group.release();
+}
+
+} // memory
+} // vkt
--- /dev/null
+#ifndef _VKTMEMORYMAPPINGTESTS_HPP
+#define _VKTMEMORYMAPPINGTESTS_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Simple memory mapping tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+namespace memory
+{
+
+tcu::TestCaseGroup* createMappingTests (tcu::TestContext& testCtx);
+
+} // memory
+} // vkt
+
+#endif // _VKTMEMORYMAPPINGTESTS_HPP
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Memory Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktMemoryTests.hpp"
+
+#include "vktMemoryAllocationTests.hpp"
+#include "vktMemoryMappingTests.hpp"
+
+#include "deUniquePtr.hpp"
+
+namespace vkt
+{
+namespace memory
+{
+
+tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> memoryTests (new tcu::TestCaseGroup(testCtx, "memory", "Memory Tests"));
+
+ memoryTests->addChild(createAllocationTests (testCtx));
+ memoryTests->addChild(createMappingTests (testCtx));
+
+ return memoryTests.release();
+}
+
+} // memory
+} // vkt
--- /dev/null
+#ifndef _VKTMEMORYTESTS_HPP
+#define _VKTMEMORYTESTS_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Memory tests
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+namespace memory
+{
+
+tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx);
+
+} // memory
+} // vkt
+
+#endif // _VKTMEMORYTESTS_HPP
--- /dev/null
+
+include_directories(
+ ..
+ )
+
+set(DEQP_VK_PIPELINE_SRCS
+ vktPipelineBlendTests.cpp
+ vktPipelineBlendTests.hpp
+ vktPipelineClearUtil.cpp
+ vktPipelineClearUtil.hpp
+ vktPipelineDepthTests.cpp
+ vktPipelineDepthTests.hpp
+ vktPipelineImageSamplingInstance.cpp
+ vktPipelineImageSamplingInstance.hpp
+ vktPipelineImageTests.cpp
+ vktPipelineImageTests.hpp
+ vktPipelineImageUtil.cpp
+ vktPipelineImageUtil.hpp
+ vktPipelineImageViewTests.cpp
+ vktPipelineImageViewTests.hpp
+ vktPipelineReferenceRenderer.cpp
+ vktPipelineReferenceRenderer.hpp
+ vktPipelineSamplerTests.cpp
+ vktPipelineSamplerTests.hpp
+ vktPipelineStencilTests.cpp
+ vktPipelineStencilTests.hpp
+ vktPipelineTests.cpp
+ vktPipelineTests.hpp
+ vktPipelineVertexUtil.cpp
+ vktPipelineVertexUtil.hpp
+ )
+
+set(DEQP_VK_PIPELINE_LIBS
+ tcutil
+ vkutil
+ referencerenderer
+ )
+
+add_library(deqp-vk-pipeline STATIC ${DEQP_VK_PIPELINE_SRCS})
+target_link_libraries(deqp-vk-pipeline ${DEQP_VK_PIPELINE_LIBS})
+
--- /dev/null
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Imagination Technologies Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by Khronos,
+ * at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Blend Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktPipelineBlendTests.hpp"
+#include "vktPipelineClearUtil.hpp"
+#include "vktPipelineImageUtil.hpp"
+#include "vktPipelineVertexUtil.hpp"
+#include "vktPipelineUniqueRandomIterator.hpp"
+#include "vktPipelineReferenceRenderer.hpp"
+#include "vktTestCase.hpp"
+#include "vkImageUtil.hpp"
+#include "vkMemUtil.hpp"
+#include "vkPlatform.hpp"
+#include "vkPrograms.hpp"
+#include "vkQueryUtil.hpp"
+#include "vkRef.hpp"
+#include "vkRefUtil.hpp"
+#include "tcuImageCompare.hpp"
+#include "tcuPlatform.hpp"
+#include "tcuTextureUtil.hpp"
+#include "deRandom.hpp"
+#include "deStringUtil.hpp"
+#include "deUniquePtr.hpp"
+#include <cstring>
+#include <set>
+#include <sstream>
+#include <vector>
+
+namespace vkt
+{
+namespace pipeline
+{
+
+using namespace vk;
+
+namespace
+{
+
+bool isSupportedBlendFormat (const InstanceInterface& instanceInterface, VkPhysicalDevice device, VkFormat format)
+{
+ VkFormatProperties formatProps;
+
+ instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
+
+ return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) &&
+ (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT);
+}
+
+class BlendStateUniqueRandomIterator : public UniqueRandomIterator<VkPipelineColorBlendAttachmentState>
+{
+public:
+ BlendStateUniqueRandomIterator (deUint32 numberOfCombinations, int seed);
+ virtual ~BlendStateUniqueRandomIterator (void) {}
+ VkPipelineColorBlendAttachmentState getIndexedValue (deUint32 index);
+
+private:
+ const static VkBlendFactor m_blendFactors[];
+ const static VkBlendOp m_blendOps[];
+
+ // Pre-calculated constants
+ const static deUint32 m_blendFactorsLength;
+ const static deUint32 m_blendFactorsLength2;
+ const static deUint32 m_blendFactorsLength3;
+ const static deUint32 m_blendFactorsLength4;
+ const static deUint32 m_blendOpsLength;
+
+ // Total number of cross-combinations of (srcBlendColor x destBlendColor x blendOpColor x srcBlendAlpha x destBlendAlpha x blendOpAlpha)
+ const static deUint32 m_totalBlendStates;
+};
+
+class BlendTest : public vkt::TestCase
+{
+public:
+ enum
+ {
+ QUAD_COUNT = 4
+ };
+
+ const static VkColorComponentFlags s_colorWriteMasks[QUAD_COUNT];
+ const static tcu::Vec4 s_blendConst;
+
+ BlendTest (tcu::TestContext& testContext,
+ const std::string& name,
+ const std::string& description,
+ const VkFormat colorFormat,
+ const VkPipelineColorBlendAttachmentState blendStates[QUAD_COUNT]);
+ virtual ~BlendTest (void);
+ virtual void initPrograms (SourceCollections& sourceCollections) const;
+ virtual TestInstance* createInstance (Context& context) const;
+
+private:
+ const VkFormat m_colorFormat;
+ VkPipelineColorBlendAttachmentState m_blendStates[QUAD_COUNT];
+};
+
+class BlendTestInstance : public vkt::TestInstance
+{
+public:
+ BlendTestInstance (Context& context, const VkFormat colorFormat, const VkPipelineColorBlendAttachmentState blendStates[BlendTest::QUAD_COUNT]);
+ virtual ~BlendTestInstance (void);
+ virtual tcu::TestStatus iterate (void);
+
+private:
+ static float getNormChannelThreshold (const tcu::TextureFormat& format, int numBits);
+ static tcu::Vec4 getFormatThreshold (const tcu::TextureFormat& format);
+ tcu::TestStatus verifyImage (void);
+
+ VkPipelineColorBlendAttachmentState m_blendStates[BlendTest::QUAD_COUNT];
+
+ const tcu::IVec2 m_renderSize;
+ const VkFormat m_colorFormat;
+
+ VkImageCreateInfo m_colorImageCreateInfo;
+ Move<VkImage> m_colorImage;
+ de::MovePtr<Allocation> m_colorImageAlloc;
+ Move<VkImageView> m_colorAttachmentView;
+ Move<VkRenderPass> m_renderPass;
+ Move<VkFramebuffer> m_framebuffer;
+
+ Move<VkShaderModule> m_vertexShaderModule;
+ Move<VkShaderModule> m_fragmentShaderModule;
+
+ Move<VkBuffer> m_vertexBuffer;
+ std::vector<Vertex4RGBA> m_vertices;
+ de::MovePtr<Allocation> m_vertexBufferAlloc;
+
+ Move<VkPipelineLayout> m_pipelineLayout;
+ Move<VkPipeline> m_graphicsPipelines[BlendTest::QUAD_COUNT];
+
+ Move<VkCommandPool> m_cmdPool;
+ Move<VkCommandBuffer> m_cmdBuffer;
+
+ Move<VkFence> m_fence;
+};
+
+
+// BlendStateUniqueRandomIterator
+
+const VkBlendFactor BlendStateUniqueRandomIterator::m_blendFactors[] =
+{
+ VK_BLEND_FACTOR_ZERO,
+ VK_BLEND_FACTOR_ONE,
+ VK_BLEND_FACTOR_SRC_COLOR,
+ VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR,
+ VK_BLEND_FACTOR_DST_COLOR,
+ VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR,
+ VK_BLEND_FACTOR_SRC_ALPHA,
+ VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
+ VK_BLEND_FACTOR_DST_ALPHA,
+ VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA,
+ VK_BLEND_FACTOR_CONSTANT_COLOR,
+ VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR,
+ VK_BLEND_FACTOR_CONSTANT_ALPHA,
+ VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA,
+ VK_BLEND_FACTOR_SRC_ALPHA_SATURATE
+};
+
+const VkBlendOp BlendStateUniqueRandomIterator::m_blendOps[] =
+{
+ VK_BLEND_OP_ADD,
+ VK_BLEND_OP_SUBTRACT,
+ VK_BLEND_OP_REVERSE_SUBTRACT,
+ VK_BLEND_OP_MIN,
+ VK_BLEND_OP_MAX
+};
+
+const deUint32 BlendStateUniqueRandomIterator::m_blendFactorsLength = DE_LENGTH_OF_ARRAY(m_blendFactors);
+const deUint32 BlendStateUniqueRandomIterator::m_blendFactorsLength2 = m_blendFactorsLength * m_blendFactorsLength;
+const deUint32 BlendStateUniqueRandomIterator::m_blendFactorsLength3 = m_blendFactorsLength2 * m_blendFactorsLength;
+const deUint32 BlendStateUniqueRandomIterator::m_blendFactorsLength4 = m_blendFactorsLength3 * m_blendFactorsLength;
+const deUint32 BlendStateUniqueRandomIterator::m_blendOpsLength = DE_LENGTH_OF_ARRAY(m_blendOps);
+const deUint32 BlendStateUniqueRandomIterator::m_totalBlendStates = m_blendFactorsLength4 * m_blendOpsLength * m_blendOpsLength;
+
+
+BlendStateUniqueRandomIterator::BlendStateUniqueRandomIterator (deUint32 numberOfCombinations, int seed)
+ : UniqueRandomIterator<VkPipelineColorBlendAttachmentState>(numberOfCombinations, m_totalBlendStates, seed)
+{
+}
+
+VkPipelineColorBlendAttachmentState BlendStateUniqueRandomIterator::getIndexedValue (deUint32 index)
+{
+ const deUint32 blendOpAlphaIndex = index / (m_blendFactorsLength4 * m_blendOpsLength);
+ const deUint32 blendOpAlphaSeqIndex = blendOpAlphaIndex * (m_blendFactorsLength4 * m_blendOpsLength);
+
+ const deUint32 destBlendAlphaIndex = (index - blendOpAlphaSeqIndex) / (m_blendFactorsLength3 * m_blendOpsLength);
+ const deUint32 destBlendAlphaSeqIndex = destBlendAlphaIndex * (m_blendFactorsLength3 * m_blendOpsLength);
+
+ const deUint32 srcBlendAlphaIndex = (index - blendOpAlphaSeqIndex - destBlendAlphaSeqIndex) / (m_blendFactorsLength2 * m_blendOpsLength);
+ const deUint32 srcBlendAlphaSeqIndex = srcBlendAlphaIndex * (m_blendFactorsLength2 * m_blendOpsLength);
+
+ const deUint32 blendOpColorIndex = (index - blendOpAlphaSeqIndex - destBlendAlphaSeqIndex - srcBlendAlphaSeqIndex) / m_blendFactorsLength2;
+ const deUint32 blendOpColorSeqIndex = blendOpColorIndex * m_blendFactorsLength2;
+
+ const deUint32 destBlendColorIndex = (index - blendOpAlphaSeqIndex - destBlendAlphaSeqIndex - srcBlendAlphaSeqIndex - blendOpColorSeqIndex) / m_blendFactorsLength;
+ const deUint32 destBlendColorSeqIndex = destBlendColorIndex * m_blendFactorsLength;
+
+ const deUint32 srcBlendColorIndex = index - blendOpAlphaSeqIndex - destBlendAlphaSeqIndex - srcBlendAlphaSeqIndex - blendOpColorSeqIndex - destBlendColorSeqIndex;
+
+ const VkPipelineColorBlendAttachmentState blendAttachmentState =
+ {
+ true, // VkBool32 blendEnable;
+ m_blendFactors[srcBlendColorIndex], // VkBlendFactor srcColorBlendFactor;
+ m_blendFactors[destBlendColorIndex], // VkBlendFactor dstColorBlendFactor;
+ m_blendOps[blendOpColorIndex], // VkBlendOp colorBlendOp;
+ m_blendFactors[srcBlendAlphaIndex], // VkBlendFactor srcAlphaBlendFactor;
+ m_blendFactors[destBlendAlphaIndex], // VkBlendFactor dstAlphaBlendFactor;
+ m_blendOps[blendOpAlphaIndex], // VkBlendOp alphaBlendOp;
+ VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | // VkColorComponentFlags colorWriteMask;
+ VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
+ };
+
+ return blendAttachmentState;
+}
+
+
+// BlendTest
+
+const VkColorComponentFlags BlendTest::s_colorWriteMasks[BlendTest::QUAD_COUNT] = { VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT, // Pair of channels: R & G
+ VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT, // Pair of channels: G & B
+ VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, // Pair of channels: B & A
+ VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT }; // All channels
+
+const tcu::Vec4 BlendTest::s_blendConst = tcu::Vec4(0.1f, 0.2f, 0.3f, 0.4f);
+
+BlendTest::BlendTest (tcu::TestContext& testContext,
+ const std::string& name,
+ const std::string& description,
+ const VkFormat colorFormat,
+ const VkPipelineColorBlendAttachmentState blendStates[QUAD_COUNT])
+ : vkt::TestCase (testContext, name, description)
+ , m_colorFormat(colorFormat)
+{
+ deMemcpy(m_blendStates, blendStates, sizeof(VkPipelineColorBlendAttachmentState) * QUAD_COUNT);
+}
+
+BlendTest::~BlendTest (void)
+{
+}
+
+TestInstance* BlendTest::createInstance(Context& context) const
+{
+ return new BlendTestInstance(context, m_colorFormat, m_blendStates);
+}
+
+void BlendTest::initPrograms (SourceCollections& sourceCollections) const
+{
+ std::ostringstream fragmentSource;
+
+ sourceCollections.glslSources.add("color_vert") << glu::VertexSource(
+ "#version 310 es\n"
+ "layout(location = 0) in highp vec4 position;\n"
+ "layout(location = 1) in highp vec4 color;\n"
+ "layout(location = 0) out highp vec4 vtxColor;\n"
+ "void main (void)\n"
+ "{\n"
+ " gl_Position = position;\n"
+ " vtxColor = color;\n"
+ "}\n");
+
+ fragmentSource << "#version 310 es\n"
+ "layout(location = 0) in highp vec4 vtxColor;\n"
+ "layout(location = 0) out highp vec4 fragColor;\n"
+ "void main (void)\n"
+ "{\n"
+ " fragColor = vtxColor;\n"
+ "}\n";
+
+ sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(fragmentSource.str());
+}
+
+
+// BlendTestInstance
+
+BlendTestInstance::BlendTestInstance (Context& context,
+ const VkFormat colorFormat,
+ const VkPipelineColorBlendAttachmentState blendStates[BlendTest::QUAD_COUNT])
+ : vkt::TestInstance (context)
+ , m_renderSize (32, 32)
+ , m_colorFormat (colorFormat)
+{
+ const DeviceInterface& vk = m_context.getDeviceInterface();
+ const VkDevice vkDevice = m_context.getDevice();
+ const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
+ SimpleAllocator memAlloc (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
+
+ // Copy depth operators
+ deMemcpy(m_blendStates, blendStates, sizeof(VkPipelineColorBlendAttachmentState) * BlendTest::QUAD_COUNT);
+
+ // Create color image
+ {
+ if (!isSupportedBlendFormat(context.getInstanceInterface(), context.getPhysicalDevice(), m_colorFormat))
+ throw tcu::NotSupportedError(std::string("Unsupported color blending format: ") + getFormatName(m_colorFormat));
+
+ const VkImageCreateInfo colorImageParams =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkImageCreateFlags flags;
+ VK_IMAGE_TYPE_2D, // VkImageType imageType;
+ m_colorFormat, // VkFormat format;
+ { m_renderSize.x(), m_renderSize.y(), 1u }, // VkExtent3D extent;
+ 1u, // deUint32 mipLevels;
+ 1u, // deUint32 arrayLayers;
+ VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
+ VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
+ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
+ VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
+ 1u, // deUint32 queueFamilyIndexCount;
+ &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
+ VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
+ };
+
+ m_colorImageCreateInfo = colorImageParams;
+ m_colorImage = createImage(vk, vkDevice, &m_colorImageCreateInfo);
+
+ // Allocate and bind color image memory
+ m_colorImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
+ VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
+ }
+
+ // Create color attachment view
+ {
+ const VkImageViewCreateInfo colorAttachmentViewParams =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkImageViewCreateFlags flags;
+ *m_colorImage, // VkImage image;
+ VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
+ m_colorFormat, // VkFormat format;
+ getFormatComponentMapping(m_colorFormat), // VkComponentMapping components;
+ { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange;
+ };
+
+ m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
+ }
+
+ // Create render pass
+ {
+ const VkAttachmentDescription colorAttachmentDescription =
+ {
+ 0u, // VkAttachmentDescriptionFlags flags;
+ m_colorFormat, // VkFormat format;
+ VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
+ VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
+ VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
+ VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
+ VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout;
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
+ };
+
+ const VkAttachmentReference colorAttachmentReference =
+ {
+ 0u, // deUint32 attachment;
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
+ };
+
+ const VkSubpassDescription subpassDescription =
+ {
+ 0u, // VkSubpassDescriptionFlag flags;
+ VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
+ 0u, // deUint32 inputAttachmentCount;
+ DE_NULL, // const VkAttachmentReference* pInputAttachments;
+ 1u, // deUint32 colorAttachmentCount;
+ &colorAttachmentReference, // const VkAttachmentReference* pColorAttachments;
+ DE_NULL, // const VkAttachmentReference* pResolveAttachments;
+ DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
+ 0u, // deUint32 preserveAttachmentCount;
+ DE_NULL // const VkAttachmentReference* pPreserveAttachments;
+ };
+
+ const VkRenderPassCreateInfo renderPassParams =
+ {
+ VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkRenderPassCreateFlags flags;
+ 1u, // deUint32 attachmentCount;
+ &colorAttachmentDescription, // const VkAttachmentDescription* pAttachments;
+ 1u, // deUint32 subpassCount;
+ &subpassDescription, // const VkSubpassDescription* pSubpasses;
+ 0u, // deUint32 dependencyCount;
+ DE_NULL // const VkSubpassDependency* pDependencies;
+ };
+
+ m_renderPass = createRenderPass(vk, vkDevice, &renderPassParams);
+ }
+
+ // Create framebuffer
+ {
+ const VkFramebufferCreateInfo framebufferParams =
+ {
+ VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkFramebufferCreateFlags flags;
+ *m_renderPass, // VkRenderPass renderPass;
+ 1u, // deUint32 attachmentCount;
+ &m_colorAttachmentView.get(), // const VkImageView* pAttachments;
+ (deUint32)m_renderSize.x(), // deUint32 width;
+ (deUint32)m_renderSize.y(), // deUint32 height;
+ 1u // deUint32 layers;
+ };
+
+ m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
+ }
+
+ // Create pipeline layout
+ {
+ const VkPipelineLayoutCreateInfo pipelineLayoutParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineLayoutCreateFlags flags;
+ 0u, // deUint32 setLayoutCount;
+ DE_NULL, // const VkDescriptorSetLayout* pSetLayouts;
+ 0u, // deUint32 pushConstantRangeCount;
+ DE_NULL // const VkPushConstantRange* pPushConstantRanges;
+ };
+
+ m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
+ }
+
+ m_vertexShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0);
+ m_fragmentShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag"), 0);
+
+ // Create pipeline
+ {
+ const VkPipelineShaderStageCreateInfo shaderStages[2] =
+ {
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineShaderStageCreateFlags flags;
+ VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage;
+ *m_vertexShaderModule, // VkShaderModule module;
+ "main", // const char* pName;
+ DE_NULL // const VkSpecializationInfo* pSpecializationInfo;
+ },
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineShaderStageCreateFlags flags;
+ VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage;
+ *m_fragmentShaderModule, // VkShaderModule module;
+ "main", // const char* pName;
+ DE_NULL // const VkSpecializationInfo* pSpecializationInfo;
+ }
+ };
+
+ const VkVertexInputBindingDescription vertexInputBindingDescription =
+ {
+ 0u, // deUint32 binding;
+ sizeof(Vertex4RGBA), // deUint32 strideInBytes;
+ VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate inputRate;
+ };
+
+ const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
+ {
+ {
+ 0u, // deUint32 location;
+ 0u, // deUint32 binding;
+ VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
+ 0u // deUint32 offset;
+ },
+ {
+ 1u, // deUint32 location;
+ 0u, // deUint32 binding;
+ VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
+ (deUint32)(sizeof(float) * 4), // deUint32 offset;
+ }
+ };
+
+ const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineVertexInputStateCreateFlags flags;
+ 1u, // deUint32 vertexBindingDescriptionCount;
+ &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
+ 2u, // deUint32 vertexAttributeDescriptionCount;
+ vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
+ };
+
+ const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineInputAssemblyStateCreateFlags flags;
+ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology topology;
+ false // VkBool32 primitiveRestartEnable;
+ };
+
+ const VkViewport viewport =
+ {
+ 0.0f, // float x;
+ 0.0f, // float y;
+ (float)m_renderSize.x(), // float width;
+ (float)m_renderSize.y(), // float height;
+ 0.0f, // float minDepth;
+ 1.0f // float maxDepth;
+ };
+
+ const VkRect2D scissor = { { 0, 0 }, { m_renderSize.x(), m_renderSize.y() } };
+
+ const VkPipelineViewportStateCreateInfo viewportStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineViewportStateCreateFlags flags;
+ 1u, // deUint32 viewportCount;
+ &viewport, // const VkViewport* pViewports;
+ 1u, // deUint32 scissorCount;
+ &scissor // const VkRect2D* pScissors;
+ };
+
+ const VkPipelineRasterizationStateCreateInfo rasterStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineRasterizationStateCreateFlags flags;
+ false, // VkBool32 depthClampEnable;
+ false, // VkBool32 rasterizerDiscardEnable;
+ VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
+ VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
+ VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
+ false, // VkBool32 depthBiasEnable;
+ 0.0f, // float depthBiasConstantFactor;
+ 0.0f, // float depthBiasClamp;
+ 0.0f, // float depthBiasSlopeFactor;
+ 1.0f // float lineWidth;
+ };
+
+ const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineMultisampleStateCreateFlags flags;
+ VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
+ false, // VkBool32 sampleShadingEnable;
+ 0.0f, // float minSampleShading;
+ DE_NULL, // const VkSampleMask* pSampleMask;
+ false, // VkBool32 alphaToCoverageEnable;
+ false // VkBool32 alphaToOneEnable;
+ };
+
+ const VkPipelineDepthStencilStateCreateInfo depthStencilStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineDepthStencilStateCreateFlags flags;
+ false, // VkBool32 depthTestEnable;
+ false, // VkBool32 depthWriteEnable;
+ VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp;
+ false, // VkBool32 depthBoundsTestEnable;
+ false, // VkBool32 stencilTestEnable;
+ // VkStencilOpState front;
+ {
+ VK_STENCIL_OP_KEEP, // VkStencilOp failOp;
+ VK_STENCIL_OP_KEEP, // VkStencilOp passOp;
+ VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp;
+ VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
+ 0u, // deUint32 compareMask;
+ 0u, // deUint32 writeMask;
+ 0u // deUint32 reference;
+ },
+ // VkStencilOpState back;
+ {
+ VK_STENCIL_OP_KEEP, // VkStencilOp failOp;
+ VK_STENCIL_OP_KEEP, // VkStencilOp passOp;
+ VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp;
+ VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
+ 0u, // deUint32 compareMask;
+ 0u, // deUint32 writeMask;
+ 0u // deUint32 reference;
+ },
+ -1.0f, // float minDepthBounds;
+ +1.0f // float maxDepthBounds;
+ };
+
+ // The color blend attachment will be set up before creating the graphics pipeline.
+ VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineColorBlendStateCreateFlags flags;
+ false, // VkBool32 logicOpEnable;
+ VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
+ 0u, // deUint32 attachmentCount;
+ DE_NULL, // const VkPipelineColorBlendAttachmentState* pAttachments;
+ { // float blendConstants[4];
+ BlendTest::s_blendConst.x(),
+ BlendTest::s_blendConst.y(),
+ BlendTest::s_blendConst.z(),
+ BlendTest::s_blendConst.w()
+ }
+ };
+
+ const VkPipelineDynamicStateCreateInfo dynamicStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineDynamicStateCreateFlags flags;
+ 0u, // deUint32 dynamicStateCount;
+ DE_NULL // const VkDynamicState* pDynamicStates;
+ };
+
+ const VkGraphicsPipelineCreateInfo graphicsPipelineParams =
+ {
+ VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineCreateFlags flags;
+ 2u, // deUint32 stageCount;
+ shaderStages, // const VkPipelineShaderStageCreateInfo* pStages;
+ &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
+ &inputAssemblyStateParams, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
+ DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
+ &viewportStateParams, // const VkPipelineViewportStateCreateInfo* pViewportState;
+ &rasterStateParams, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
+ &multisampleStateParams, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
+ &depthStencilStateParams, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
+ &colorBlendStateParams, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
+ &dynamicStateParams, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
+ *m_pipelineLayout, // VkPipelineLayout layout;
+ *m_renderPass, // VkRenderPass renderPass;
+ 0u, // deUint32 subpass;
+ 0u, // VkPipeline basePipelineHandle;
+ 0u // deInt32 basePipelineIndex;
+ };
+
+ for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++)
+ {
+ colorBlendStateParams.attachmentCount = 1u;
+ colorBlendStateParams.pAttachments = &m_blendStates[quadNdx];
+ m_graphicsPipelines[quadNdx] = createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams);
+ }
+ }
+
+ // Create vertex buffer
+ {
+ const VkBufferCreateInfo vertexBufferParams =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkBufferCreateFlags flags;
+ 1024u, // VkDeviceSize size;
+ VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
+ VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
+ 1u, // deUint32 queueFamilyIndexCount;
+ &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
+ };
+
+ m_vertices = createOverlappingQuads();
+ m_vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams);
+ m_vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
+
+ VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
+
+ // Adjust vertex colors
+ if (!isFloatFormat(m_colorFormat))
+ {
+ const tcu::TextureFormatInfo formatInfo = tcu::getTextureFormatInfo(mapVkFormat(m_colorFormat));
+ for (size_t vertexNdx = 0; vertexNdx < m_vertices.size(); vertexNdx++)
+ m_vertices[vertexNdx].color = (m_vertices[vertexNdx].color - formatInfo.lookupBias) / formatInfo.lookupScale;
+ }
+
+ // Upload vertex data
+ deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
+
+ const VkMappedMemoryRange flushRange =
+ {
+ VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ m_vertexBufferAlloc->getMemory(), // VkDeviceMemory memory;
+ m_vertexBufferAlloc->getOffset(), // VkDeviceSize offset;
+ vertexBufferParams.size // VkDeviceSize size;
+ };
+
+ vk.flushMappedMemoryRanges(vkDevice, 1, &flushRange);
+ }
+
+ // Create command pool
+ {
+ const VkCommandPoolCreateInfo cmdPoolParams =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // VkCommandPoolCreateFlags flags;
+ queueFamilyIndex // deUint32 queueFamilyIndex;
+ };
+
+ m_cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams);
+ }
+
+ // Create command buffer
+ {
+ const VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ *m_cmdPool, // VkCommandPool commandPool;
+ VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
+ 1u, // deUint32 bufferCount;
+ };
+
+ const VkCommandBufferBeginInfo cmdBufferBeginInfo =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkCommandBufferUsageFlags flags;
+ 0u, // VkRenderPass renderPass;
+ DE_NULL, // deUint32 subpass;
+ DE_NULL, // VkFramebuffer framebuffer;
+ false, // VkBool32 occlusionQueryEnable;
+ 0u, // VkQueryControlFlags queryFlags;
+ 0u // VkQueryPipelineStatisticFlags pipelineStatistics;
+ };
+
+ const VkClearValue attachmentClearValue = defaultClearValue(m_colorFormat);
+
+ const VkRenderPassBeginInfo renderPassBeginInfo =
+ {
+ VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ *m_renderPass, // VkRenderPass renderPass;
+ *m_framebuffer, // VkFramebuffer framebuffer;
+ { { 0, 0 }, { m_renderSize.x(), m_renderSize.y() } }, // VkRect2D renderArea;
+ 1, // deUint32 clearValueCount;
+ &attachmentClearValue // const VkClearValue* pClearValues;
+ };
+
+ m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferAllocateInfo);
+
+ VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
+ vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
+
+ const VkDeviceSize quadOffset = (m_vertices.size() / BlendTest::QUAD_COUNT) * sizeof(Vertex4RGBA);
+
+ for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++)
+ {
+ VkDeviceSize vertexBufferOffset = quadOffset * quadNdx;
+
+ vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelines[quadNdx]);
+ vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
+ vk.cmdDraw(*m_cmdBuffer, (deUint32)(m_vertices.size() / BlendTest::QUAD_COUNT), 1, 0, 0);
+ }
+
+ vk.cmdEndRenderPass(*m_cmdBuffer);
+ VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
+ }
+
+ // Create fence
+ {
+ const VkFenceCreateInfo fenceParams =
+ {
+ VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u // VkFenceCreateFlags flags;
+ };
+
+ m_fence = createFence(vk, vkDevice, &fenceParams);
+ }
+}
+
+BlendTestInstance::~BlendTestInstance (void)
+{
+}
+
+tcu::TestStatus BlendTestInstance::iterate (void)
+{
+ const DeviceInterface& vk = m_context.getDeviceInterface();
+ const VkDevice vkDevice = m_context.getDevice();
+ const VkQueue queue = m_context.getUniversalQueue();
+ const VkSubmitInfo submitInfo =
+ {
+ VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // deUint32 waitSemaphoreCount;
+ DE_NULL, // const VkSemaphore* pWaitSemaphores;
+ 1u, // deUint32 commandBufferCount;
+ &m_cmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
+ 0u, // deUint32 signalSemaphoreCount;
+ DE_NULL // const VkSemaphore* pSignalSemaphores;
+ };
+
+ VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
+ VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
+ VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity */));
+
+ return verifyImage();
+}
+
+float BlendTestInstance::getNormChannelThreshold (const tcu::TextureFormat& format, int numBits)
+{
+ switch (tcu::getTextureChannelClass(format.type))
+ {
+ case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: return BlendTest::QUAD_COUNT / static_cast<float>((1 << numBits) - 1);
+ case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: return BlendTest::QUAD_COUNT / static_cast<float>((1 << (numBits - 1)) - 1);
+ default:
+ break;
+ }
+
+ DE_ASSERT(false);
+ return 0.0f;
+}
+
+tcu::Vec4 BlendTestInstance::getFormatThreshold (const tcu::TextureFormat& format)
+{
+ using tcu::Vec4;
+ using tcu::TextureFormat;
+
+ Vec4 threshold(0.01f);
+
+ switch (format.type)
+ {
+ case TextureFormat::UNORM_BYTE_44:
+ threshold = Vec4(getNormChannelThreshold(format, 4), getNormChannelThreshold(format, 4), 1.0f, 1.0f);
+ break;
+
+ case TextureFormat::UNORM_SHORT_565:
+ threshold = Vec4(getNormChannelThreshold(format, 5), getNormChannelThreshold(format, 6), getNormChannelThreshold(format, 5), 1.0f);
+ break;
+
+ case TextureFormat::UNORM_SHORT_555:
+ threshold = Vec4(getNormChannelThreshold(format, 5), getNormChannelThreshold(format, 5), getNormChannelThreshold(format, 5), 1.0f);
+ break;
+
+ case TextureFormat::UNORM_SHORT_4444:
+ threshold = Vec4(getNormChannelThreshold(format, 4));
+ break;
+
+ case TextureFormat::UNORM_SHORT_5551:
+ threshold = Vec4(getNormChannelThreshold(format, 5), getNormChannelThreshold(format, 5), getNormChannelThreshold(format, 5), 0.1f);
+ break;
+
+ case TextureFormat::UNORM_INT_1010102_REV:
+ case TextureFormat::SNORM_INT_1010102_REV:
+ threshold = Vec4(getNormChannelThreshold(format, 10), getNormChannelThreshold(format, 10), getNormChannelThreshold(format, 10), 0.1f);
+ break;
+
+ case TextureFormat::UNORM_INT8:
+ case TextureFormat::SNORM_INT8:
+ threshold = Vec4(getNormChannelThreshold(format, 8));
+ break;
+
+ case TextureFormat::UNORM_INT16:
+ case TextureFormat::SNORM_INT16:
+ threshold = Vec4(getNormChannelThreshold(format, 16));
+ break;
+
+ case TextureFormat::UNORM_INT32:
+ case TextureFormat::SNORM_INT32:
+ threshold = Vec4(getNormChannelThreshold(format, 32));
+ break;
+
+ case TextureFormat::HALF_FLOAT:
+ threshold = Vec4(0.005f);
+ break;
+
+ case TextureFormat::FLOAT:
+ threshold = Vec4(0.00001f);
+ break;
+
+ case TextureFormat::UNSIGNED_INT_11F_11F_10F_REV:
+ threshold = Vec4(0.02f, 0.02f, 0.02f, 1.0f);
+ break;
+
+ case TextureFormat::UNSIGNED_INT_999_E5_REV:
+ threshold = Vec4(0.05f, 0.05f, 0.05f, 1.0f);
+ break;
+
+ default:
+ DE_ASSERT(false);
+ }
+
+ // Return value matching the channel order specified by the format
+ if (format.order == tcu::TextureFormat::BGR || format.order == tcu::TextureFormat::BGRA)
+ return threshold.swizzle(2, 1, 0, 3);
+ else
+ return threshold;
+}
+
+tcu::TestStatus BlendTestInstance::verifyImage (void)
+{
+ const tcu::TextureFormat tcuColorFormat = mapVkFormat(m_colorFormat);
+ const tcu::TextureFormat tcuDepthFormat = tcu::TextureFormat(); // Undefined depth/stencil format
+ const ColorVertexShader vertexShader;
+ const ColorFragmentShader fragmentShader (tcuColorFormat, tcuDepthFormat);
+ const rr::Program program (&vertexShader, &fragmentShader);
+ ReferenceRenderer refRenderer (m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuDepthFormat, &program);
+ bool compareOk = false;
+
+ // Render reference image
+ {
+ for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++)
+ {
+ const VkPipelineColorBlendAttachmentState& blendState = m_blendStates[quadNdx];
+
+ // Set blend state
+ rr::RenderState renderState (refRenderer.getViewportState());
+ renderState.fragOps.blendMode = rr::BLENDMODE_STANDARD;
+ renderState.fragOps.blendRGBState.srcFunc = mapVkBlendFactor(blendState.srcColorBlendFactor);
+ renderState.fragOps.blendRGBState.dstFunc = mapVkBlendFactor(blendState.dstColorBlendFactor);
+ renderState.fragOps.blendRGBState.equation = mapVkBlendOp(blendState.colorBlendOp);
+ renderState.fragOps.blendAState.srcFunc = mapVkBlendFactor(blendState.srcAlphaBlendFactor);
+ renderState.fragOps.blendAState.dstFunc = mapVkBlendFactor(blendState.dstAlphaBlendFactor);
+ renderState.fragOps.blendAState.equation = mapVkBlendOp(blendState.alphaBlendOp);
+ renderState.fragOps.blendColor = BlendTest::s_blendConst;
+ renderState.fragOps.colorMask = mapVkColorComponentFlags(BlendTest::s_colorWriteMasks[quadNdx]);
+
+ refRenderer.draw(renderState,
+ rr::PRIMITIVETYPE_TRIANGLES,
+ std::vector<Vertex4RGBA>(m_vertices.begin() + quadNdx * 6,
+ m_vertices.begin() + (quadNdx + 1) * 6));
+ }
+ }
+
+
+ // Compare result with reference image
+ {
+ const DeviceInterface& vk = m_context.getDeviceInterface();
+ const VkDevice vkDevice = m_context.getDevice();
+ const VkQueue queue = m_context.getUniversalQueue();
+ const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
+ SimpleAllocator allocator (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
+ de::UniquePtr<tcu::TextureLevel> result (readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize).release());
+ const tcu::Vec4 threshold (getFormatThreshold(tcuColorFormat));
+
+ compareOk = tcu::floatThresholdCompare(m_context.getTestContext().getLog(),
+ "FloatImageCompare",
+ "Image comparison",
+ refRenderer.getAccess(),
+ result->getAccess(),
+ threshold,
+ tcu::COMPARE_LOG_RESULT);
+ }
+
+ if (compareOk)
+ return tcu::TestStatus::pass("Result image matches reference");
+ else
+ return tcu::TestStatus::fail("Image mismatch");
+}
+
+} // anonymous
+
+std::string getBlendStateName (const VkPipelineColorBlendAttachmentState& blendState)
+{
+ const char* shortBlendFactorNames[] =
+ {
+ "z", // VK_BLEND_ZERO
+ "o", // VK_BLEND_ONE
+ "sc", // VK_BLEND_SRC_COLOR
+ "1msc", // VK_BLEND_ONE_MINUS_SRC_COLOR
+ "dc", // VK_BLEND_DEST_COLOR
+ "1mdc", // VK_BLEND_ONE_MINUS_DEST_COLOR
+ "sa", // VK_BLEND_SRC_ALPHA
+ "1msa", // VK_BLEND_ONE_MINUS_SRC_ALPHA
+ "da", // VK_BLEND_DEST_ALPHA
+ "1mda", // VK_BLEND_ONE_MINUS_DEST_ALPHA
+ "cc", // VK_BLEND_CONSTANT_COLOR
+ "1mcc", // VK_BLEND_ONE_MINUS_CONSTANT_COLOR
+ "ca", // VK_BLEND_CONSTANT_ALPHA
+ "1mca", // VK_BLEND_ONE_MINUS_CONSTANT_ALPHA
+ "sas" // VK_BLEND_SRC_ALPHA_SATURATE
+ };
+
+ const char* blendOpNames[] =
+ {
+ "add", // VK_BLEND_OP_ADD
+ "sub", // VK_BLEND_OP_SUBTRACT
+ "rsub", // VK_BLEND_OP_REVERSE_SUBTRACT
+ "min", // VK_BLEND_OP_MIN
+ "max", // VK_BLEND_OP_MAX
+ };
+
+ std::ostringstream shortName;
+
+ shortName << "color_" << shortBlendFactorNames[blendState.srcColorBlendFactor] << "_" << shortBlendFactorNames[blendState.dstColorBlendFactor] << "_" << blendOpNames[blendState.colorBlendOp];
+ shortName << "_alpha_" << shortBlendFactorNames[blendState.srcAlphaBlendFactor] << "_" << shortBlendFactorNames[blendState.dstAlphaBlendFactor] << "_" << blendOpNames[blendState.alphaBlendOp];
+
+ return shortName.str();
+}
+
+std::string getBlendStateSetName (const VkPipelineColorBlendAttachmentState blendStates[BlendTest::QUAD_COUNT])
+{
+ std::ostringstream name;
+
+ for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++)
+ {
+ name << getBlendStateName(blendStates[quadNdx]);
+
+ if (quadNdx < BlendTest::QUAD_COUNT - 1)
+ name << "-";
+ }
+
+ return name.str();
+}
+
+std::string getBlendStateSetDescription (const VkPipelineColorBlendAttachmentState blendStates[BlendTest::QUAD_COUNT])
+{
+ std::ostringstream description;
+
+ description << "Draws " << BlendTest::QUAD_COUNT << " quads with the following blend states:\n";
+
+ for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++)
+ description << blendStates[quadNdx] << "\n";
+
+ return description.str();
+}
+
+std::string getFormatCaseName (VkFormat format)
+{
+ const std::string fullName = getFormatName(format);
+
+ DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_"));
+
+ return de::toLower(fullName.substr(10));
+}
+
+tcu::TestCaseGroup* createBlendTests (tcu::TestContext& testCtx)
+{
+ const deUint32 blendStatesPerFormat = 100 * BlendTest::QUAD_COUNT;
+
+ // Formats that are dEQP-compatible, non-integer and uncompressed
+ const VkFormat blendFormats[] =
+ {
+ VK_FORMAT_R4G4_UNORM_PACK8,
+ VK_FORMAT_R4G4B4A4_UNORM_PACK16,
+ VK_FORMAT_R5G6B5_UNORM_PACK16,
+ VK_FORMAT_R5G5B5A1_UNORM_PACK16,
+ VK_FORMAT_R8_UNORM,
+ VK_FORMAT_R8_SNORM,
+ VK_FORMAT_R8_SRGB,
+ VK_FORMAT_R8G8_UNORM,
+ VK_FORMAT_R8G8_SNORM,
+ VK_FORMAT_R8G8_SRGB,
+ VK_FORMAT_R8G8B8_UNORM,
+ VK_FORMAT_R8G8B8_SNORM,
+ VK_FORMAT_R8G8B8_SRGB,
+ VK_FORMAT_R8G8B8A8_UNORM,
+ VK_FORMAT_R8G8B8A8_SNORM,
+ VK_FORMAT_R8G8B8A8_SRGB,
+ VK_FORMAT_A2R10G10B10_UNORM_PACK32,
+ VK_FORMAT_R16_UNORM,
+ VK_FORMAT_R16_SNORM,
+ VK_FORMAT_R16_SFLOAT,
+ VK_FORMAT_R16G16_UNORM,
+ VK_FORMAT_R16G16_SNORM,
+ VK_FORMAT_R16G16_SFLOAT,
+ VK_FORMAT_R16G16B16_UNORM,
+ VK_FORMAT_R16G16B16_SNORM,
+ VK_FORMAT_R16G16B16_SFLOAT,
+ VK_FORMAT_R16G16B16A16_UNORM,
+ VK_FORMAT_R16G16B16A16_SNORM,
+ VK_FORMAT_R16G16B16A16_SFLOAT,
+ VK_FORMAT_R32_SFLOAT,
+ VK_FORMAT_R32G32_SFLOAT,
+ VK_FORMAT_R32G32B32_SFLOAT,
+ VK_FORMAT_R32G32B32A32_SFLOAT,
+ VK_FORMAT_B10G11R11_UFLOAT_PACK32,
+ VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
+ VK_FORMAT_B4G4R4A4_UNORM_PACK16,
+ VK_FORMAT_B5G5R5A1_UNORM_PACK16,
+ };
+
+ de::MovePtr<tcu::TestCaseGroup> blendTests (new tcu::TestCaseGroup(testCtx, "blend", "Blend tests"));
+ de::MovePtr<tcu::TestCaseGroup> formatTests (new tcu::TestCaseGroup(testCtx, "format", "Uses different blend formats"));
+ BlendStateUniqueRandomIterator blendStateItr (blendStatesPerFormat, 123);
+
+ for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(blendFormats); formatNdx++)
+ {
+ const VkFormat format = blendFormats[formatNdx];
+ de::MovePtr<tcu::TestCaseGroup> formatTest (new tcu::TestCaseGroup(testCtx,
+ getFormatCaseName(format).c_str(),
+ (std::string("Uses format ") + getFormatName(format)).c_str()));
+ de::MovePtr<tcu::TestCaseGroup> blendStateTests;
+ {
+ std::ostringstream blendStateDescription;
+ blendStateDescription << "Combines blend factors, operators and channel write masks. The constant color used in all tests is " << BlendTest::s_blendConst;
+ blendStateTests = de::MovePtr<tcu::TestCaseGroup>(new tcu::TestCaseGroup(testCtx, "states", blendStateDescription.str().c_str()));
+ }
+
+ blendStateItr.reset();
+
+ while (blendStateItr.hasNext())
+ {
+ VkPipelineColorBlendAttachmentState quadBlendConfigs[BlendTest::QUAD_COUNT];
+
+ for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++)
+ {
+ quadBlendConfigs[quadNdx] = blendStateItr.next();
+ quadBlendConfigs[quadNdx].colorWriteMask = BlendTest::s_colorWriteMasks[quadNdx];
+ }
+
+ blendStateTests->addChild(new BlendTest(testCtx,
+ getBlendStateSetName(quadBlendConfigs),
+ getBlendStateSetDescription(quadBlendConfigs),
+ format,
+ quadBlendConfigs));
+ }
+ formatTest->addChild(blendStateTests.release());
+ formatTests->addChild(formatTest.release());
+ }
+ blendTests->addChild(formatTests.release());
+
+ return blendTests.release();
+}
+
+} // pipeline
+} // vkt
--- /dev/null
+#ifndef _VKTPIPELINEBLENDTESTS_HPP
+#define _VKTPIPELINEBLENDTESTS_HPP
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Imagination Technologies Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by Khronos,
+ * at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Blend Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktTestCase.hpp"
+
+namespace vkt
+{
+namespace pipeline
+{
+
+tcu::TestCaseGroup* createBlendTests (tcu::TestContext& testCtx);
+
+} // pipeline
+} // vkt
+
+#endif // _VKTPIPELINEBLENDTESTS_HPP
--- /dev/null
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Imagination Technologies Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by Khronos,
+ * at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Utilities for clear values.
+ *//*--------------------------------------------------------------------*/
+
+#include "vktPipelineClearUtil.hpp"
+#include "vkImageUtil.hpp"
+#include "tcuTextureUtil.hpp"
+
+namespace vkt
+{
+namespace pipeline
+{
+
+using namespace vk;
+
+tcu::Vec4 defaultClearColor (const tcu::TextureFormat& format)
+{
+ if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_FLOATING_POINT)
+ return defaultClearColorUnorm();
+ else
+ {
+ const tcu::TextureFormatInfo formatInfo = tcu::getTextureFormatInfo(format);
+ return (defaultClearColorUnorm() - formatInfo.lookupBias) / formatInfo.lookupScale;
+ }
+}
+
+tcu::IVec4 defaultClearColorInt (const tcu::TextureFormat& format)
+{
+ const tcu::TextureFormatInfo formatInfo = tcu::getTextureFormatInfo(format);
+ const tcu::Vec4 color = (defaultClearColorUnorm() - formatInfo.lookupBias) / formatInfo.lookupScale;
+
+ const tcu::IVec4 result ((deInt32)deFloatRound(color.x()), (deInt32)deFloatRound(color.y()),
+ (deInt32)deFloatRound(color.z()), (deInt32)deFloatRound(color.w()));
+
+ return result;
+}
+
+tcu::UVec4 defaultClearColorUint (const tcu::TextureFormat& format)
+{
+ const tcu::TextureFormatInfo formatInfo = tcu::getTextureFormatInfo(format);
+ const tcu::Vec4 color = (defaultClearColorUnorm() - formatInfo.lookupBias) / formatInfo.lookupScale;
+
+ const tcu::UVec4 result ((deUint32)deFloatRound(color.x()), (deUint32)deFloatRound(color.y()),
+ (deUint32)deFloatRound(color.z()), (deUint32)deFloatRound(color.w()));
+
+ return result;
+}
+
+tcu::Vec4 defaultClearColorUnorm (void)
+{
+ return tcu::Vec4(0.39f, 0.58f, 0.93f, 1.0f);
+}
+
+float defaultClearDepth (void)
+{
+ return 1.0f;
+}
+
+deUint32 defaultClearStencil (void)
+{
+ return 0;
+}
+
+VkClearDepthStencilValue defaultClearDepthStencilValue (void)
+{
+ VkClearDepthStencilValue clearDepthStencilValue;
+ clearDepthStencilValue.depth = defaultClearDepth();
+ clearDepthStencilValue.stencil = defaultClearStencil();
+
+ return clearDepthStencilValue;
+}
+
+VkClearValue defaultClearValue (VkFormat clearFormat)
+{
+ VkClearValue clearValue;
+
+ if (isDepthStencilFormat(clearFormat))
+ {
+ const VkClearDepthStencilValue dsValue = defaultClearDepthStencilValue();
+ clearValue.depthStencil.stencil = dsValue.stencil;
+ clearValue.depthStencil.depth = dsValue.depth;
+ }
+ else
+ {
+ const tcu::TextureFormat tcuClearFormat = mapVkFormat(clearFormat);
+ if (isUintFormat(clearFormat))
+ {
+ const tcu::UVec4 defaultColor = defaultClearColorUint(tcuClearFormat);
+ clearValue.color.uint32[0] = defaultColor.x();
+ clearValue.color.uint32[1] = defaultColor.y();
+ clearValue.color.uint32[2] = defaultColor.z();
+ clearValue.color.uint32[3] = defaultColor.w();
+ }
+ else if (isIntFormat(clearFormat))
+ {
+ const tcu::IVec4 defaultColor = defaultClearColorInt(tcuClearFormat);
+ clearValue.color.int32[0] = defaultColor.x();
+ clearValue.color.int32[1] = defaultColor.y();
+ clearValue.color.int32[2] = defaultColor.z();
+ clearValue.color.int32[3] = defaultColor.w();
+ }
+ else
+ {
+ const tcu::Vec4 defaultColor = defaultClearColor(tcuClearFormat);
+ clearValue.color.float32[0] = defaultColor.x();
+ clearValue.color.float32[1] = defaultColor.y();
+ clearValue.color.float32[2] = defaultColor.z();
+ clearValue.color.float32[3] = defaultColor.w();
+ }
+ }
+
+ return clearValue;
+}
+
+} // pipeline
+} // vkt
--- /dev/null
+#ifndef _VKTPIPELINECLEARUTIL_HPP
+#define _VKTPIPELINECLEARUTIL_HPP
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Imagination Technologies Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by Khronos,
+ * at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Utilities for clear values.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuTexture.hpp"
+#include "tcuVectorUtil.hpp"
+#include "vkDefs.hpp"
+
+namespace vkt
+{
+namespace pipeline
+{
+
+tcu::Vec4 defaultClearColor (const tcu::TextureFormat& format);
+tcu::IVec4 defaultClearColorInt (const tcu::TextureFormat& format);
+tcu::UVec4 defaultClearColorUint (const tcu::TextureFormat& format);
+tcu::Vec4 defaultClearColorUnorm (void);
+float defaultClearDepth (void);
+deUint32 defaultClearStencil (void);
+
+vk::VkClearDepthStencilValue defaultClearDepthStencilValue (void);
+vk::VkClearValue defaultClearValue (vk::VkFormat format);
+
+} // pipeline
+} // vkt
+
+#endif // _VKTPIPELINECLEARUTIL_HPP
--- /dev/null
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Imagination Technologies Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by Khronos,
+ * at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Depth Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktPipelineDepthTests.hpp"
+#include "vktPipelineClearUtil.hpp"
+#include "vktPipelineImageUtil.hpp"
+#include "vktPipelineVertexUtil.hpp"
+#include "vktPipelineReferenceRenderer.hpp"
+#include "vktTestCase.hpp"
+#include "vktTestCaseUtil.hpp"
+#include "vkImageUtil.hpp"
+#include "vkMemUtil.hpp"
+#include "vkPrograms.hpp"
+#include "vkQueryUtil.hpp"
+#include "vkRef.hpp"
+#include "vkRefUtil.hpp"
+#include "tcuImageCompare.hpp"
+#include "deUniquePtr.hpp"
+#include "deStringUtil.hpp"
+#include "deMemory.h"
+
+#include <sstream>
+#include <vector>
+
+namespace vkt
+{
+namespace pipeline
+{
+
+using namespace vk;
+
+namespace
+{
+
+bool isSupportedDepthStencilFormat (const InstanceInterface& instanceInterface, VkPhysicalDevice device, VkFormat format)
+{
+ VkFormatProperties formatProps;
+
+ instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
+
+ return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0u;
+}
+
+tcu::TestStatus testSupportsDepthStencilFormat (Context& context, VkFormat format)
+{
+ DE_ASSERT(vk::isDepthStencilFormat(format));
+
+ if (isSupportedDepthStencilFormat(context.getInstanceInterface(), context.getPhysicalDevice(), format))
+ return tcu::TestStatus::pass("Format can be used in depth/stencil attachment");
+ else
+ return tcu::TestStatus::fail("Unsupported depth/stencil attachment format");
+}
+
+tcu::TestStatus testSupportsAtLeastOneDepthStencilFormat (Context& context, const std::vector<VkFormat> formats)
+{
+ std::ostringstream supportedFormatsMsg;
+ bool pass = false;
+
+ DE_ASSERT(!formats.empty());
+
+ for (size_t formatNdx = 0; formatNdx < formats.size(); formatNdx++)
+ {
+ const VkFormat format = formats[formatNdx];
+
+ DE_ASSERT(vk::isDepthStencilFormat(format));
+
+ if (isSupportedDepthStencilFormat(context.getInstanceInterface(), context.getPhysicalDevice(), format))
+ {
+ pass = true;
+ supportedFormatsMsg << vk::getFormatName(format);
+
+ if (formatNdx < formats.size() - 1)
+ supportedFormatsMsg << ", ";
+ }
+ }
+
+ if (pass)
+ return tcu::TestStatus::pass(std::string("Supported depth/stencil formats: ") + supportedFormatsMsg.str());
+ else
+ return tcu::TestStatus::fail("All depth/stencil formats are unsupported");
+}
+
+class DepthTest : public vkt::TestCase
+{
+public:
+ enum
+ {
+ QUAD_COUNT = 4
+ };
+
+ static const float quadDepths[QUAD_COUNT];
+
+ DepthTest (tcu::TestContext& testContext,
+ const std::string& name,
+ const std::string& description,
+ const VkFormat depthFormat,
+ const VkCompareOp depthCompareOps[QUAD_COUNT]);
+ virtual ~DepthTest (void);
+ virtual void initPrograms (SourceCollections& programCollection) const;
+ virtual TestInstance* createInstance (Context& context) const;
+
+private:
+ const VkFormat m_depthFormat;
+ VkCompareOp m_depthCompareOps[QUAD_COUNT];
+};
+
+class DepthTestInstance : public vkt::TestInstance
+{
+public:
+ DepthTestInstance (Context& context, const VkFormat depthFormat, const VkCompareOp depthCompareOps[DepthTest::QUAD_COUNT]);
+ virtual ~DepthTestInstance (void);
+ virtual tcu::TestStatus iterate (void);
+
+private:
+ tcu::TestStatus verifyImage (void);
+
+private:
+ VkCompareOp m_depthCompareOps[DepthTest::QUAD_COUNT];
+ const tcu::IVec2 m_renderSize;
+ const VkFormat m_colorFormat;
+ const VkFormat m_depthFormat;
+
+ Move<VkImage> m_colorImage;
+ de::MovePtr<Allocation> m_colorImageAlloc;
+ Move<VkImage> m_depthImage;
+ de::MovePtr<Allocation> m_depthImageAlloc;
+ Move<VkImageView> m_colorAttachmentView;
+ Move<VkImageView> m_depthAttachmentView;
+ Move<VkRenderPass> m_renderPass;
+ Move<VkFramebuffer> m_framebuffer;
+
+ Move<VkShaderModule> m_vertexShaderModule;
+ Move<VkShaderModule> m_fragmentShaderModule;
+
+ Move<VkBuffer> m_vertexBuffer;
+ std::vector<Vertex4RGBA> m_vertices;
+ de::MovePtr<Allocation> m_vertexBufferAlloc;
+
+ Move<VkPipelineLayout> m_pipelineLayout;
+ Move<VkPipeline> m_graphicsPipelines[DepthTest::QUAD_COUNT];
+
+ Move<VkCommandPool> m_cmdPool;
+ Move<VkCommandBuffer> m_cmdBuffer;
+
+ Move<VkFence> m_fence;
+};
+
+const float DepthTest::quadDepths[QUAD_COUNT] =
+{
+ 0.1f,
+ 0.0f,
+ 0.3f,
+ 0.2f
+};
+
+DepthTest::DepthTest (tcu::TestContext& testContext,
+ const std::string& name,
+ const std::string& description,
+ const VkFormat depthFormat,
+ const VkCompareOp depthCompareOps[QUAD_COUNT])
+ : vkt::TestCase (testContext, name, description)
+ , m_depthFormat (depthFormat)
+{
+ deMemcpy(m_depthCompareOps, depthCompareOps, sizeof(VkCompareOp) * QUAD_COUNT);
+}
+
+DepthTest::~DepthTest (void)
+{
+}
+
+TestInstance* DepthTest::createInstance (Context& context) const
+{
+ return new DepthTestInstance(context, m_depthFormat, m_depthCompareOps);
+}
+
+void DepthTest::initPrograms (SourceCollections& programCollection) const
+{
+ programCollection.glslSources.add("color_vert") << glu::VertexSource(
+ "#version 310 es\n"
+ "layout(location = 0) in vec4 position;\n"
+ "layout(location = 1) in vec4 color;\n"
+ "layout(location = 0) out highp vec4 vtxColor;\n"
+ "void main (void)\n"
+ "{\n"
+ " gl_Position = position;\n"
+ " vtxColor = color;\n"
+ "}\n");
+
+ programCollection.glslSources.add("color_frag") << glu::FragmentSource(
+ "#version 310 es\n"
+ "layout(location = 0) in highp vec4 vtxColor;\n"
+ "layout(location = 0) out highp vec4 fragColor;\n"
+ "void main (void)\n"
+ "{\n"
+ " fragColor = vtxColor;\n"
+ "}\n");
+}
+
+DepthTestInstance::DepthTestInstance (Context& context,
+ const VkFormat depthFormat,
+ const VkCompareOp depthCompareOps[DepthTest::QUAD_COUNT])
+ : vkt::TestInstance (context)
+ , m_renderSize (32, 32)
+ , m_colorFormat (VK_FORMAT_R8G8B8A8_UNORM)
+ , m_depthFormat (depthFormat)
+{
+ const DeviceInterface& vk = context.getDeviceInterface();
+ const VkDevice vkDevice = context.getDevice();
+ const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
+ SimpleAllocator memAlloc (vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
+ const VkComponentMapping componentMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
+
+ // Copy depth operators
+ deMemcpy(m_depthCompareOps, depthCompareOps, sizeof(VkCompareOp) * DepthTest::QUAD_COUNT);
+
+ // Create color image
+ {
+ const VkImageCreateInfo colorImageParams =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkImageCreateFlags flags;
+ VK_IMAGE_TYPE_2D, // VkImageType imageType;
+ m_colorFormat, // VkFormat format;
+ { m_renderSize.x(), m_renderSize.y(), 1u }, // VkExtent3D extent;
+ 1u, // deUint32 mipLevels;
+ 1u, // deUint32 arrayLayers;
+ VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
+ VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
+ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
+ VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
+ 1u, // deUint32 queueFamilyIndexCount;
+ &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
+ VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
+ };
+
+ m_colorImage = createImage(vk, vkDevice, &colorImageParams);
+
+ // Allocate and bind color image memory
+ m_colorImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
+ VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
+ }
+
+ // Create depth image
+ {
+ // Check format support
+ if (!isSupportedDepthStencilFormat(context.getInstanceInterface(), context.getPhysicalDevice(), m_depthFormat))
+ throw tcu::NotSupportedError(std::string("Unsupported depth/stencil format: ") + getFormatName(m_depthFormat));
+
+ const VkImageCreateInfo depthImageParams =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkImageCreateFlags flags;
+ VK_IMAGE_TYPE_2D, // VkImageType imageType;
+ m_depthFormat, // VkFormat format;
+ { m_renderSize.x(), m_renderSize.y(), 1u }, // VkExtent3D extent;
+ 1u, // deUint32 mipLevels;
+ 1u, // deUint32 arrayLayers;
+ VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
+ VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
+ VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, // VkImageUsageFlags usage;
+ VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
+ 1u, // deUint32 queueFamilyIndexCount;
+ &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
+ VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
+ };
+
+ m_depthImage = createImage(vk, vkDevice, &depthImageParams);
+
+ // Allocate and bind depth image memory
+ m_depthImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_depthImage), MemoryRequirement::Any);
+ VK_CHECK(vk.bindImageMemory(vkDevice, *m_depthImage, m_depthImageAlloc->getMemory(), m_depthImageAlloc->getOffset()));
+ }
+
+ // Create color attachment view
+ {
+ const VkImageViewCreateInfo colorAttachmentViewParams =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkImageViewCreateFlags flags;
+ *m_colorImage, // VkImage image;
+ VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
+ m_colorFormat, // VkFormat format;
+ componentMappingRGBA, // VkComponentMapping components;
+ { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange;
+ };
+
+ m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
+ }
+
+ // Create depth attachment view
+ {
+ const VkImageViewCreateInfo depthAttachmentViewParams =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkImageViewCreateFlags flags;
+ *m_depthImage, // VkImage image;
+ VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
+ m_depthFormat, // VkFormat format;
+ componentMappingRGBA, // VkComponentMapping components;
+ { VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange;
+ };
+
+ m_depthAttachmentView = createImageView(vk, vkDevice, &depthAttachmentViewParams);
+ }
+
+ // Create render pass
+ {
+ const VkAttachmentDescription colorAttachmentDescription =
+ {
+ 0u, // VkAttachmentDescriptionFlags flags;
+ m_colorFormat, // VkFormat format;
+ VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
+ VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
+ VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
+ VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
+ VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout;
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout;
+ };
+
+ const VkAttachmentDescription depthAttachmentDescription =
+ {
+ 0u, // VkAttachmentDescriptionFlags flags;
+ m_depthFormat, // VkFormat format;
+ VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
+ VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
+ VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp storeOp;
+ VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
+ VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout;
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
+ };
+
+ const VkAttachmentDescription attachments[2] =
+ {
+ colorAttachmentDescription,
+ depthAttachmentDescription
+ };
+
+ const VkAttachmentReference colorAttachmentReference =
+ {
+ 0u, // deUint32 attachment;
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
+ };
+
+ const VkAttachmentReference depthAttachmentReference =
+ {
+ 1u, // deUint32 attachment;
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL // VkImageLayout layout;
+ };
+
+ const VkSubpassDescription subpassDescription =
+ {
+ 0u, // VkSubpassDescriptionFlags flags;
+ VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
+ 0u, // deUint32 inputAttachmentCount;
+ DE_NULL, // const VkAttachmentReference* pInputAttachments;
+ 1u, // deUint32 colorAttachmentCount;
+ &colorAttachmentReference, // const VkAttachmentReference* pColorAttachments;
+ DE_NULL, // const VkAttachmentReference* pResolveAttachments;
+ &depthAttachmentReference, // const VkAttachmentReference* pDepthStencilAttachment;
+ 0u, // deUint32 preserveAttachmentCount;
+ DE_NULL // const VkAttachmentReference* pPreserveAttachments;
+ };
+
+ const VkRenderPassCreateInfo renderPassParams =
+ {
+ VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkRenderPassCreateFlags flags;
+ 2u, // deUint32 attachmentCount;
+ attachments, // const VkAttachmentDescription* pAttachments;
+ 1u, // deUint32 subpassCount;
+ &subpassDescription, // const VkSubpassDescription* pSubpasses;
+ 0u, // deUint32 dependencyCount;
+ DE_NULL // const VkSubpassDependency* pDependencies;
+ };
+
+ m_renderPass = createRenderPass(vk, vkDevice, &renderPassParams);
+ }
+
+ // Create framebuffer
+ {
+ const VkImageView attachmentBindInfos[2] =
+ {
+ *m_colorAttachmentView,
+ *m_depthAttachmentView,
+ };
+
+ const VkFramebufferCreateInfo framebufferParams =
+ {
+ VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkFramebufferCreateFlags flags;
+ *m_renderPass, // VkRenderPass renderPass;
+ 2u, // deUint32 attachmentCount;
+ attachmentBindInfos, // const VkImageView* pAttachments;
+ (deUint32)m_renderSize.x(), // deUint32 width;
+ (deUint32)m_renderSize.y(), // deUint32 height;
+ 1u // deUint32 layers;
+ };
+
+ m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
+ }
+
+ // Create pipeline layout
+ {
+ const VkPipelineLayoutCreateInfo pipelineLayoutParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineLayoutCreateFlags flags;
+ 0u, // deUint32 setLayoutCount;
+ DE_NULL, // const VkDescriptorSetLayout* pSetLayouts;
+ 0u, // deUint32 pushConstantRangeCount;
+ DE_NULL // const VkPushConstantRange* pPushConstantRanges;
+ };
+
+ m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
+ }
+
+ // Shader modules
+ m_vertexShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0);
+ m_fragmentShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag"), 0);
+
+ // Create pipeline
+ {
+ const VkPipelineShaderStageCreateInfo shaderStages[2] =
+ {
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineShaderStageCreateFlags flags;
+ VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage;
+ *m_vertexShaderModule, // VkShaderModule module;
+ "main", // const char* pName;
+ DE_NULL // const VkSpecializationInfo* pSpecializationInfo;
+ },
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineShaderStageCreateFlags flags;
+ VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage;
+ *m_fragmentShaderModule, // VkShaderModule module;
+ "main", // const char* pName;
+ DE_NULL // const VkSpecializationInfo* pSpecializationInfo;
+ }
+ };
+
+ const VkVertexInputBindingDescription vertexInputBindingDescription =
+ {
+ 0u, // deUint32 binding;
+ sizeof(Vertex4RGBA), // deUint32 strideInBytes;
+ VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate inputRate;
+ };
+
+ const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
+ {
+ {
+ 0u, // deUint32 location;
+ 0u, // deUint32 binding;
+ VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
+ 0u // deUint32 offset;
+ },
+ {
+ 1u, // deUint32 location;
+ 0u, // deUint32 binding;
+ VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
+ DE_OFFSET_OF(Vertex4RGBA, color), // deUint32 offset;
+ }
+ };
+
+ const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineVertexInputStateCreateFlags flags;
+ 1u, // deUint32 vertexBindingDescriptionCount;
+ &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
+ 2u, // deUint32 vertexAttributeDescriptionCount;
+ vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
+ };
+
+ const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineInputAssemblyStateCreateFlags flags;
+ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology topology;
+ false // VkBool32 primitiveRestartEnable;
+ };
+
+ const VkViewport viewport =
+ {
+ 0.0f, // float x;
+ 0.0f, // float y;
+ (float)m_renderSize.x(), // float width;
+ (float)m_renderSize.y(), // float height;
+ 0.0f, // float minDepth;
+ 1.0f // float maxDepth;
+ };
+ const VkRect2D scissor =
+ {
+ { 0, 0 }, // VkOffset2D offset;
+ { m_renderSize.x(), m_renderSize.y() } // VkExtent2D extent;
+ };
+ const VkPipelineViewportStateCreateInfo viewportStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineViewportStateCreateFlags flags;
+ 1u, // deUint32 viewportCount;
+ &viewport, // const VkViewport* pViewports;
+ 1u, // deUint32 scissorCount;
+ &scissor // const VkRect2D* pScissors;
+ };
+
+ const VkPipelineRasterizationStateCreateInfo rasterStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineRasterizationStateCreateFlags flags;
+ false, // VkBool32 depthClampEnable;
+ false, // VkBool32 rasterizerDiscardEnable;
+ VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
+ VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
+ VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
+ VK_FALSE, // VkBool32 depthBiasEnable;
+ 0.0f, // float depthBiasConstantFactor;
+ 0.0f, // float depthBiasClamp;
+ 0.0f, // float depthBiasSlopeFactor;
+ 1.0f, // float lineWidth;
+ };
+
+ const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
+ {
+ false, // VkBool32 blendEnable;
+ VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
+ VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
+ VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
+ VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor;
+ VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
+ VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
+ VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | // VkColorComponentFlags colorWriteMask;
+ VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
+ };
+
+ const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0, // VkPipelineColorBlendStateCreateFlags flags;
+ false, // VkBool32 logicOpEnable;
+ VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
+ 1u, // deUint32 attachmentCount;
+ &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
+ { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4];
+ };
+
+ const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineMultisampleStateCreateFlags flags;
+ VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
+ false, // VkBool32 sampleShadingEnable;
+ 0.0f, // float minSampleShading;
+ DE_NULL, // const VkSampleMask* pSampleMask;
+ false, // VkBool32 alphaToCoverageEnable;
+ false // VkBool32 alphaToOneEnable;
+ };
+
+ const VkPipelineDynamicStateCreateInfo dynamicStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineDynamicStateCreateFlags flags;
+ 0u, // deUint32 dynamicStateCount;
+ DE_NULL // const VkDynamicState* pDynamicStates;
+ };
+
+ VkPipelineDepthStencilStateCreateInfo depthStencilStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineDepthStencilStateCreateFlags flags;
+ true, // VkBool32 depthTestEnable;
+ true, // VkBool32 depthWriteEnable;
+ VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp;
+ false, // VkBool32 depthBoundsTestEnable;
+ false, // VkBool32 stencilTestEnable;
+ // VkStencilOpState front;
+ {
+ VK_STENCIL_OP_KEEP, // VkStencilOp failOp;
+ VK_STENCIL_OP_KEEP, // VkStencilOp passOp;
+ VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp;
+ VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
+ 0u, // deUint32 compareMask;
+ 0u, // deUint32 writeMask;
+ 0u, // deUint32 reference;
+ },
+ // VkStencilOpState back;
+ {
+ VK_STENCIL_OP_KEEP, // VkStencilOp failOp;
+ VK_STENCIL_OP_KEEP, // VkStencilOp passOp;
+ VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp;
+ VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
+ 0u, // deUint32 compareMask;
+ 0u, // deUint32 writeMask;
+ 0u, // deUint32 reference;
+ },
+ -1.0f, // float minDepthBounds;
+ +1.0f, // float maxDepthBounds;
+ };
+
+ const VkGraphicsPipelineCreateInfo graphicsPipelineParams =
+ {
+ VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineCreateFlags flags;
+ 2u, // deUint32 stageCount;
+ shaderStages, // const VkPipelineShaderStageCreateInfo* pStages;
+ &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
+ &inputAssemblyStateParams, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
+ DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
+ &viewportStateParams, // const VkPipelineViewportStateCreateInfo* pViewportState;
+ &rasterStateParams, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
+ &multisampleStateParams, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
+ &depthStencilStateParams, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
+ &colorBlendStateParams, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
+ &dynamicStateParams, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
+ *m_pipelineLayout, // VkPipelineLayout layout;
+ *m_renderPass, // VkRenderPass renderPass;
+ 0u, // deUint32 subpass;
+ 0u, // VkPipeline basePipelineHandle;
+ 0u, // deInt32 basePipelineIndex;
+ };
+
+ for (int quadNdx = 0; quadNdx < DepthTest::QUAD_COUNT; quadNdx++)
+ {
+ depthStencilStateParams.depthCompareOp = depthCompareOps[quadNdx];
+ m_graphicsPipelines[quadNdx] = createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams);
+ }
+ }
+
+ // Create vertex buffer
+ {
+ const VkBufferCreateInfo vertexBufferParams =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkBufferCreateFlags flags;
+ 1024u, // VkDeviceSize size;
+ VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
+ VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
+ 1u, // deUint32 queueFamilyIndexCount;
+ &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
+ };
+
+ m_vertices = createOverlappingQuads();
+ m_vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams);
+ m_vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
+
+ VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
+
+ // Adjust depths
+ for (int quadNdx = 0; quadNdx < DepthTest::QUAD_COUNT; quadNdx++)
+ for (int vertexNdx = 0; vertexNdx < 6; vertexNdx++)
+ m_vertices[quadNdx * 6 + vertexNdx].position.z() = DepthTest::quadDepths[quadNdx];
+
+ // Load vertices into vertex buffer
+ deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
+ flushMappedMemoryRange(vk, vkDevice, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset(), vertexBufferParams.size);
+ }
+
+ // Create command pool
+ {
+ const VkCommandPoolCreateInfo cmdPoolParams =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // VkCmdPoolCreateFlags flags;
+ queueFamilyIndex // deUint32 queueFamilyIndex;
+ };
+
+ m_cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams);
+ }
+
+ // Create command buffer
+ {
+ const VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ *m_cmdPool, // VkCommandPool commandPool;
+ VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
+ 1u // deUint32 bufferCount;
+ };
+
+ const VkCommandBufferBeginInfo cmdBufferBeginInfo =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkCommandBufferUsageFlags flags;
+ DE_NULL, // VkRenderPass renderPass;
+ 0u, // deUint32 subpass;
+ DE_NULL, // VkFramebuffer framebuffer;
+ false, // VkBool32 occlusionQueryEnable;
+ 0u, // VkQueryControlFlags queryFlags;
+ 0u // VkQueryPipelineStatisticFlags pipelineStatistics;
+ };
+
+ const VkClearValue attachmentClearValues[2] =
+ {
+ defaultClearValue(m_colorFormat),
+ defaultClearValue(m_depthFormat),
+ };
+
+ const VkRenderPassBeginInfo renderPassBeginInfo =
+ {
+ VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ *m_renderPass, // VkRenderPass renderPass;
+ *m_framebuffer, // VkFramebuffer framebuffer;
+ { { 0, 0 }, { m_renderSize.x(), m_renderSize.y() } }, // VkRect2D renderArea;
+ 2, // deUint32 clearValueCount;
+ attachmentClearValues // const VkClearValue* pClearValues;
+ };
+
+ m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferAllocateInfo);
+
+ VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
+ vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
+
+ const VkDeviceSize quadOffset = (m_vertices.size() / DepthTest::QUAD_COUNT) * sizeof(Vertex4RGBA);
+
+ for (int quadNdx = 0; quadNdx < DepthTest::QUAD_COUNT; quadNdx++)
+ {
+ VkDeviceSize vertexBufferOffset = quadOffset * quadNdx;
+
+ vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelines[quadNdx]);
+ vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
+ vk.cmdDraw(*m_cmdBuffer, (deUint32)(m_vertices.size() / DepthTest::QUAD_COUNT), 1, 0, 0);
+ }
+
+ vk.cmdEndRenderPass(*m_cmdBuffer);
+ VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
+ }
+
+ // Create fence
+ {
+ const VkFenceCreateInfo fenceParams =
+ {
+ VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u // VkFenceCreateFlags flags;
+ };
+
+ m_fence = createFence(vk, vkDevice, &fenceParams);
+ }
+}
+
+DepthTestInstance::~DepthTestInstance (void)
+{
+}
+
+tcu::TestStatus DepthTestInstance::iterate (void)
+{
+ const DeviceInterface& vk = m_context.getDeviceInterface();
+ const VkDevice vkDevice = m_context.getDevice();
+ const VkQueue queue = m_context.getUniversalQueue();
+ const VkSubmitInfo submitInfo =
+ {
+ VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // deUint32 waitSemaphoreCount;
+ DE_NULL, // const VkSemaphore* pWaitSemaphores;
+ 1u, // deUint32 commandBufferCount;
+ &m_cmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
+ 0u, // deUint32 signalSemaphoreCount;
+ DE_NULL // const VkSemaphore* pSignalSemaphores;
+ };
+
+ VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
+ VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
+ VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity*/));
+
+ return verifyImage();
+}
+
+tcu::TestStatus DepthTestInstance::verifyImage (void)
+{
+ const tcu::TextureFormat tcuColorFormat = mapVkFormat(m_colorFormat);
+ const tcu::TextureFormat tcuDepthFormat = mapVkFormat(m_depthFormat);
+ const ColorVertexShader vertexShader;
+ const ColorFragmentShader fragmentShader (tcuColorFormat, tcuDepthFormat);
+ const rr::Program program (&vertexShader, &fragmentShader);
+ ReferenceRenderer refRenderer (m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuDepthFormat, &program);
+ bool compareOk = false;
+
+ // Render reference image
+ {
+ for (int quadNdx = 0; quadNdx < DepthTest::QUAD_COUNT; quadNdx++)
+ {
+ // Set depth state
+ rr::RenderState renderState(refRenderer.getViewportState());
+ renderState.fragOps.depthTestEnabled = true;
+ renderState.fragOps.depthFunc = mapVkCompareOp(m_depthCompareOps[quadNdx]);
+
+ refRenderer.draw(renderState,
+ rr::PRIMITIVETYPE_TRIANGLES,
+ std::vector<Vertex4RGBA>(m_vertices.begin() + quadNdx * 6,
+ m_vertices.begin() + (quadNdx + 1) * 6));
+ }
+ }
+
+ // Compare result with reference image
+ {
+ const DeviceInterface& vk = m_context.getDeviceInterface();
+ const VkDevice vkDevice = m_context.getDevice();
+ const VkQueue queue = m_context.getUniversalQueue();
+ const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
+ SimpleAllocator allocator (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
+ de::MovePtr<tcu::TextureLevel> result = readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize);
+
+ compareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
+ "IntImageCompare",
+ "Image comparison",
+ refRenderer.getAccess(),
+ result->getAccess(),
+ tcu::UVec4(2, 2, 2, 2),
+ tcu::IVec3(1, 1, 0),
+ true,
+ tcu::COMPARE_LOG_RESULT);
+ }
+
+ if (compareOk)
+ return tcu::TestStatus::pass("Result image matches reference");
+ else
+ return tcu::TestStatus::fail("Image mismatch");
+}
+
+std::string getFormatCaseName (const VkFormat format)
+{
+ const std::string fullName = getFormatName(format);
+
+ DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_"));
+
+ return de::toLower(fullName.substr(10));
+}
+
+std::string getCompareOpsName (const VkCompareOp quadDepthOps[DepthTest::QUAD_COUNT])
+{
+ std::ostringstream name;
+
+ for (int quadNdx = 0; quadNdx < DepthTest::QUAD_COUNT; quadNdx++)
+ {
+ const std::string fullOpName = getCompareOpName(quadDepthOps[quadNdx]);
+
+ DE_ASSERT(de::beginsWith(fullOpName, "VK_COMPARE_OP_"));
+
+ name << de::toLower(fullOpName.substr(14));
+
+ if (quadNdx < DepthTest::QUAD_COUNT - 1)
+ name << "_";
+ }
+
+ return name.str();
+}
+
+std::string getCompareOpsDescription (const VkCompareOp quadDepthOps[DepthTest::QUAD_COUNT])
+{
+ std::ostringstream desc;
+ desc << "Draws " << DepthTest::QUAD_COUNT << " quads with depth compare ops: ";
+
+ for (int quadNdx = 0; quadNdx < DepthTest::QUAD_COUNT; quadNdx++)
+ {
+ desc << getCompareOpName(quadDepthOps[quadNdx]) << " at depth " << DepthTest::quadDepths[quadNdx];
+
+ if (quadNdx < DepthTest::QUAD_COUNT - 1)
+ desc << ", ";
+ }
+ return desc.str();
+}
+
+
+} // anonymous
+
+tcu::TestCaseGroup* createDepthTests (tcu::TestContext& testCtx)
+{
+ const VkFormat depthFormats[] =
+ {
+ VK_FORMAT_D16_UNORM,
+ VK_FORMAT_X8_D24_UNORM_PACK32,
+ VK_FORMAT_D32_SFLOAT,
+ VK_FORMAT_D16_UNORM_S8_UINT,
+ VK_FORMAT_D24_UNORM_S8_UINT,
+ VK_FORMAT_D32_SFLOAT_S8_UINT
+ };
+
+ // Each entry configures the depth compare operators of QUAD_COUNT quads.
+ // All entries cover pair-wise combinations of compare operators.
+ const VkCompareOp depthOps[][DepthTest::QUAD_COUNT] =
+ {
+ { VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_NOT_EQUAL },
+ { VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_GREATER },
+ { VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_LESS_OR_EQUAL },
+ { VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_GREATER_OR_EQUAL },
+ { VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_ALWAYS },
+ { VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_LESS, VK_COMPARE_OP_LESS, VK_COMPARE_OP_LESS },
+ { VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_NEVER },
+ { VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_EQUAL },
+ { VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_LESS },
+ { VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_NOT_EQUAL },
+ { VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_GREATER },
+ { VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_LESS, VK_COMPARE_OP_LESS_OR_EQUAL },
+ { VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_EQUAL },
+ { VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_LESS, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_ALWAYS },
+ { VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_GREATER_OR_EQUAL },
+ { VK_COMPARE_OP_GREATER, VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_LESS },
+ { VK_COMPARE_OP_GREATER, VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_ALWAYS },
+ { VK_COMPARE_OP_GREATER, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_GREATER },
+ { VK_COMPARE_OP_GREATER, VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_NOT_EQUAL },
+ { VK_COMPARE_OP_GREATER, VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_GREATER_OR_EQUAL },
+ { VK_COMPARE_OP_GREATER, VK_COMPARE_OP_LESS, VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_NEVER },
+ { VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_GREATER },
+ { VK_COMPARE_OP_GREATER, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_LESS_OR_EQUAL },
+ { VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_NOT_EQUAL },
+ { VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_GREATER_OR_EQUAL },
+ { VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_LESS_OR_EQUAL },
+ { VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_LESS },
+ { VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_LESS, VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_EQUAL },
+ { VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_LESS, VK_COMPARE_OP_NEVER },
+ { VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_LESS_OR_EQUAL },
+ { VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_LESS, VK_COMPARE_OP_EQUAL },
+ { VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_LESS },
+ { VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_ALWAYS },
+ { VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_LESS, VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_GREATER_OR_EQUAL },
+ { VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_NEVER },
+ { VK_COMPARE_OP_LESS, VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_LESS, VK_COMPARE_OP_GREATER_OR_EQUAL },
+ { VK_COMPARE_OP_LESS, VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_LESS_OR_EQUAL },
+ { VK_COMPARE_OP_LESS, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_NEVER },
+ { VK_COMPARE_OP_LESS, VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_EQUAL },
+ { VK_COMPARE_OP_LESS, VK_COMPARE_OP_LESS, VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_NOT_EQUAL },
+ { VK_COMPARE_OP_LESS, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_ALWAYS },
+ { VK_COMPARE_OP_NEVER, VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_ALWAYS },
+ { VK_COMPARE_OP_LESS, VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_LESS },
+ { VK_COMPARE_OP_NEVER, VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_EQUAL },
+ { VK_COMPARE_OP_NEVER, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_LESS, VK_COMPARE_OP_GREATER },
+ { VK_COMPARE_OP_NEVER, VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_NOT_EQUAL },
+ { VK_COMPARE_OP_NEVER, VK_COMPARE_OP_LESS, VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_LESS_OR_EQUAL },
+ { VK_COMPARE_OP_NEVER, VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_GREATER_OR_EQUAL },
+ { VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_NEVER },
+ { VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_LESS },
+ { VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_LESS, VK_COMPARE_OP_ALWAYS },
+ { VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_GREATER },
+ { VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_EQUAL },
+ { VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_NOT_EQUAL },
+ { VK_COMPARE_OP_NEVER, VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_LESS },
+ { VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_NEVER },
+ { VK_COMPARE_OP_GREATER, VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_LESS, VK_COMPARE_OP_NOT_EQUAL },
+ { VK_COMPARE_OP_GREATER, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_EQUAL },
+ { VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_LESS_OR_EQUAL },
+ { VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_GREATER },
+ { VK_COMPARE_OP_NEVER, VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_NEVER },
+ { VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_LESS, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_GREATER },
+ { VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_NOT_EQUAL },
+ { VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_ALWAYS },
+ { VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_GREATER },
+ { VK_COMPARE_OP_LESS, VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_LESS, VK_COMPARE_OP_GREATER },
+ { VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_GREATER_OR_EQUAL },
+ { VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_LESS_OR_EQUAL },
+ { VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_LESS },
+ { VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_NEVER },
+ { VK_COMPARE_OP_LESS, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_EQUAL },
+ { VK_COMPARE_OP_NEVER, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_GREATER_OR_EQUAL },
+ { VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_ALWAYS },
+ { VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_GREATER }
+ };
+
+ de::MovePtr<tcu::TestCaseGroup> depthTests (new tcu::TestCaseGroup(testCtx, "depth", "Depth tests"));
+
+ // Tests for format features
+ {
+ de::MovePtr<tcu::TestCaseGroup> formatFeaturesTests (new tcu::TestCaseGroup(testCtx, "format_features", "Checks depth format features"));
+
+ // Formats that must be supported in all implementations
+ addFunctionCase(formatFeaturesTests.get(),
+ "support_d16_unorm",
+ "Tests if VK_FORMAT_D16_UNORM is supported as depth/stencil attachment format",
+ testSupportsDepthStencilFormat,
+ VK_FORMAT_D16_UNORM);
+
+ // Sets where at least one of the formats must be supported
+ const VkFormat depthOnlyFormats[] = { VK_FORMAT_X8_D24_UNORM_PACK32, VK_FORMAT_D32_SFLOAT };
+ const VkFormat depthStencilFormats[] = { VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT };
+
+ addFunctionCase(formatFeaturesTests.get(),
+ "support_d24_unorm_or_d32_sfloat",
+ "Tests if any of VK_FORMAT_D24_UNORM_X8 or VK_FORMAT_D32_SFLOAT are supported as depth/stencil attachment format",
+ testSupportsAtLeastOneDepthStencilFormat,
+ std::vector<VkFormat>(depthOnlyFormats, depthOnlyFormats + DE_LENGTH_OF_ARRAY(depthOnlyFormats)));
+
+ addFunctionCase(formatFeaturesTests.get(),
+ "support_d24_unorm_s8_uint_or_d32_sfloat_s8_uint",
+ "Tests if any of VK_FORMAT_D24_UNORM_S8_UINT or VK_FORMAT_D32_SFLOAT_S8_UINT are supported as depth/stencil attachment format",
+ testSupportsAtLeastOneDepthStencilFormat,
+ std::vector<VkFormat>(depthStencilFormats, depthStencilFormats + DE_LENGTH_OF_ARRAY(depthStencilFormats)));
+
+ depthTests->addChild(formatFeaturesTests.release());
+ }
+
+ // Tests for format and compare operators
+ {
+ de::MovePtr<tcu::TestCaseGroup> formatTests (new tcu::TestCaseGroup(testCtx, "format", "Uses different depth formats"));
+
+ for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(depthFormats); formatNdx++)
+ {
+ de::MovePtr<tcu::TestCaseGroup> formatTest (new tcu::TestCaseGroup(testCtx,
+ getFormatCaseName(depthFormats[formatNdx]).c_str(),
+ (std::string("Uses format ") + getFormatName(depthFormats[formatNdx])).c_str()));
+ de::MovePtr<tcu::TestCaseGroup> compareOpsTests (new tcu::TestCaseGroup(testCtx, "compare_ops", "Combines depth compare operators"));
+
+ for (size_t opsNdx = 0; opsNdx < DE_LENGTH_OF_ARRAY(depthOps); opsNdx++)
+ {
+ compareOpsTests->addChild(new DepthTest(testCtx,
+ getCompareOpsName(depthOps[opsNdx]),
+ getCompareOpsDescription(depthOps[opsNdx]),
+ depthFormats[formatNdx],
+ depthOps[opsNdx]));
+ }
+ formatTest->addChild(compareOpsTests.release());
+ formatTests->addChild(formatTest.release());
+ }
+ depthTests->addChild(formatTests.release());
+ }
+
+ return depthTests.release();
+}
+
+} // pipeline
+} // vkt
--- /dev/null
+#ifndef _VKTPIPELINEDEPTHTESTS_HPP
+#define _VKTPIPELINEDEPTHTESTS_HPP
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Imagination Technologies Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by Khronos,
+ * at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Depth Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktTestCase.hpp"
+
+namespace vkt
+{
+namespace pipeline
+{
+
+tcu::TestCaseGroup* createDepthTests (tcu::TestContext& testCtx);
+
+} // pipeline
+} // vkt
+
+#endif // _VKTPIPELINEDEPTHTESTS_HPP
--- /dev/null
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Imagination Technologies Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by Khronos,
+ * at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Image sampling case
+ *//*--------------------------------------------------------------------*/
+
+#include "vktPipelineImageSamplingInstance.hpp"
+#include "vktPipelineClearUtil.hpp"
+#include "vktPipelineReferenceRenderer.hpp"
+#include "vkBuilderUtil.hpp"
+#include "vkImageUtil.hpp"
+#include "vkPrograms.hpp"
+#include "vkQueryUtil.hpp"
+#include "vkRefUtil.hpp"
+#include "tcuImageCompare.hpp"
+
+namespace vkt
+{
+namespace pipeline
+{
+
+using namespace vk;
+using de::MovePtr;
+
+namespace
+{
+
+static VkImageType getCompatibleImageType (VkImageViewType viewType)
+{
+ switch (viewType)
+ {
+ case VK_IMAGE_VIEW_TYPE_1D: return VK_IMAGE_TYPE_1D;
+ case VK_IMAGE_VIEW_TYPE_1D_ARRAY: return VK_IMAGE_TYPE_1D;
+ case VK_IMAGE_VIEW_TYPE_2D: return VK_IMAGE_TYPE_2D;
+ case VK_IMAGE_VIEW_TYPE_2D_ARRAY: return VK_IMAGE_TYPE_2D;
+ case VK_IMAGE_VIEW_TYPE_3D: return VK_IMAGE_TYPE_3D;
+ case VK_IMAGE_VIEW_TYPE_CUBE: return VK_IMAGE_TYPE_2D;
+ case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: return VK_IMAGE_TYPE_2D;
+ default:
+ break;
+ }
+
+ DE_ASSERT(false);
+ return VK_IMAGE_TYPE_1D;
+}
+
+template<typename TcuFormatType>
+static MovePtr<TestTexture> createTestTexture (const TcuFormatType format, VkImageViewType viewType, const tcu::IVec3& size, int layerCount)
+{
+ MovePtr<TestTexture> texture;
+ const VkImageType imageType = getCompatibleImageType(viewType);
+
+ switch (imageType)
+ {
+ case VK_IMAGE_TYPE_1D:
+ if (layerCount == 1)
+ texture = MovePtr<TestTexture>(new TestTexture1D(format, size.x()));
+ else
+ texture = MovePtr<TestTexture>(new TestTexture1DArray(format, size.x(), layerCount));
+
+ break;
+
+ case VK_IMAGE_TYPE_2D:
+ if (layerCount == 1)
+ {
+ texture = MovePtr<TestTexture>(new TestTexture2D(format, size.x(), size.y()));
+ }
+ else
+ {
+ if (viewType == VK_IMAGE_VIEW_TYPE_CUBE || viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
+ {
+ if (layerCount == tcu::CUBEFACE_LAST)
+ {
+ texture = MovePtr<TestTexture>(new TestTextureCube(format, size.x()));
+ }
+ else
+ {
+ DE_ASSERT(layerCount % tcu::CUBEFACE_LAST == 0);
+
+ texture = MovePtr<TestTexture>(new TestTextureCubeArray(format, size.x(), layerCount));
+ }
+ }
+ else
+ {
+ texture = MovePtr<TestTexture>(new TestTexture2DArray(format, size.x(), size.y(), layerCount));
+ }
+ }
+
+ break;
+
+ case VK_IMAGE_TYPE_3D:
+ texture = MovePtr<TestTexture>(new TestTexture3D(format, size.x(), size.y(), size.z()));
+ break;
+
+ default:
+ DE_ASSERT(false);
+ }
+
+ return texture;
+}
+
+template<typename TcuTextureType>
+static void copySubresourceRange (TcuTextureType& dest, const TcuTextureType& src, const VkImageSubresourceRange& subresourceRange)
+{
+ DE_ASSERT(subresourceRange.levelCount <= (deUint32)dest.getNumLevels());
+ DE_ASSERT(subresourceRange.baseMipLevel + subresourceRange.levelCount <= (deUint32)src.getNumLevels());
+
+ for (int levelNdx = 0; levelNdx < dest.getNumLevels(); levelNdx++)
+ {
+ const tcu::ConstPixelBufferAccess srcLevel (src.getLevel(subresourceRange.baseMipLevel + levelNdx));
+ const deUint32 srcLayerOffset = subresourceRange.baseArrayLayer * srcLevel.getWidth() * srcLevel.getHeight() * srcLevel.getFormat().getPixelSize();
+ const tcu::ConstPixelBufferAccess srcLevelLayers (srcLevel.getFormat(), srcLevel.getWidth(), srcLevel.getHeight(), subresourceRange.layerCount, (deUint8*)srcLevel.getDataPtr() + srcLayerOffset);
+
+ if (dest.isLevelEmpty(levelNdx))
+ dest.allocLevel(levelNdx);
+
+ tcu::copy(dest.getLevel(levelNdx), srcLevelLayers);
+ }
+}
+
+template<>
+void copySubresourceRange<tcu::Texture1DArray> (tcu::Texture1DArray& dest, const tcu::Texture1DArray& src, const VkImageSubresourceRange& subresourceRange)
+{
+ DE_ASSERT(subresourceRange.levelCount <= (deUint32)dest.getNumLevels());
+ DE_ASSERT(subresourceRange.baseMipLevel + subresourceRange.levelCount <= (deUint32)src.getNumLevels());
+
+ DE_ASSERT(subresourceRange.layerCount == (deUint32)dest.getNumLayers());
+ DE_ASSERT(subresourceRange.baseArrayLayer + subresourceRange.layerCount <= (deUint32)src.getNumLayers());
+
+ for (int levelNdx = 0; levelNdx < dest.getNumLevels(); levelNdx++)
+ {
+ const tcu::ConstPixelBufferAccess srcLevel (src.getLevel(subresourceRange.baseMipLevel + levelNdx));
+ const deUint32 srcLayerOffset = subresourceRange.baseArrayLayer * srcLevel.getWidth() * srcLevel.getFormat().getPixelSize();
+ const tcu::ConstPixelBufferAccess srcLevelLayers (srcLevel.getFormat(), srcLevel.getWidth(), subresourceRange.layerCount, 1, (deUint8*)srcLevel.getDataPtr() + srcLayerOffset);
+
+ if (dest.isLevelEmpty(levelNdx))
+ dest.allocLevel(levelNdx);
+
+ tcu::copy(dest.getLevel(levelNdx), srcLevelLayers);
+ }
+}
+
+static MovePtr<Program> createRefProgram (const tcu::TextureFormat& renderTargetFormat,
+ const tcu::Sampler& sampler,
+ float samplerLod,
+ const tcu::UVec4& componentMapping,
+ const TestTexture& testTexture,
+ VkImageViewType viewType,
+ int layerCount,
+ const VkImageSubresourceRange& subresource)
+{
+ MovePtr<Program> program;
+ const VkImageType imageType = getCompatibleImageType(viewType);
+
+ switch (imageType)
+ {
+ case VK_IMAGE_TYPE_1D:
+ if (layerCount == 1)
+ {
+ const tcu::Texture1D& texture = dynamic_cast<const TestTexture1D&>(testTexture).getTexture();
+ program = MovePtr<Program>(new SamplerProgram<tcu::Texture1D>(renderTargetFormat, texture, sampler, samplerLod, componentMapping));
+ }
+ else
+ {
+ const tcu::Texture1DArray& texture = dynamic_cast<const TestTexture1DArray&>(testTexture).getTexture();
+
+ if (subresource.baseMipLevel > 0 || subresource.layerCount < (deUint32)texture.getNumLayers())
+ {
+ // Not all texture levels and layers are needed. Create new sub-texture.
+ const tcu::ConstPixelBufferAccess baseLevel = texture.getLevel(subresource.baseMipLevel);
+ tcu::Texture1DArray textureView (texture.getFormat(), baseLevel.getWidth(), subresource.layerCount);
+
+ copySubresourceRange(textureView, texture, subresource);
+
+ program = MovePtr<Program>(new SamplerProgram<tcu::Texture1DArray>(renderTargetFormat, textureView, sampler, samplerLod, componentMapping));
+ }
+ else
+ {
+ program = MovePtr<Program>(new SamplerProgram<tcu::Texture1DArray>(renderTargetFormat, texture, sampler, samplerLod, componentMapping));
+ }
+ }
+ break;
+
+ case VK_IMAGE_TYPE_2D:
+ if (layerCount == 1)
+ {
+ const tcu::Texture2D& texture = dynamic_cast<const TestTexture2D&>(testTexture).getTexture();
+ program = MovePtr<Program>(new SamplerProgram<tcu::Texture2D>(renderTargetFormat, texture, sampler, samplerLod, componentMapping));
+ }
+ else
+ {
+ if (viewType == VK_IMAGE_VIEW_TYPE_CUBE || viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
+ {
+ if (layerCount == tcu::CUBEFACE_LAST)
+ {
+ const tcu::TextureCube& texture = dynamic_cast<const TestTextureCube&>(testTexture).getTexture();
+ program = MovePtr<Program>(new SamplerProgram<tcu::TextureCube>(renderTargetFormat, texture, sampler, samplerLod, componentMapping));
+ }
+ else
+ {
+ DE_ASSERT(layerCount % tcu::CUBEFACE_LAST == 0);
+
+ const tcu::TextureCubeArray& texture = dynamic_cast<const TestTextureCubeArray&>(testTexture).getTexture();
+
+ if (subresource.baseMipLevel > 0 || subresource.layerCount < (deUint32)texture.getDepth())
+ {
+ DE_ASSERT(subresource.baseArrayLayer + subresource.layerCount <= (deUint32)texture.getDepth());
+
+ // Not all texture levels and layers are needed. Create new sub-texture.
+ const tcu::ConstPixelBufferAccess baseLevel = texture.getLevel(subresource.baseMipLevel);
+ tcu::TextureCubeArray textureView (texture.getFormat(), baseLevel.getWidth(), subresource.layerCount);
+
+ copySubresourceRange(textureView, texture, subresource);
+
+ program = MovePtr<Program>(new SamplerProgram<tcu::TextureCubeArray>(renderTargetFormat, textureView, sampler, samplerLod, componentMapping));
+ }
+ else
+ {
+ // Use all array layers
+ program = MovePtr<Program>(new SamplerProgram<tcu::TextureCubeArray>(renderTargetFormat, texture, sampler, samplerLod, componentMapping));
+ }
+ }
+ }
+ else
+ {
+ const tcu::Texture2DArray& texture = dynamic_cast<const TestTexture2DArray&>(testTexture).getTexture();
+
+ if (subresource.baseMipLevel > 0 || subresource.layerCount < (deUint32)texture.getNumLayers())
+ {
+ DE_ASSERT(subresource.baseArrayLayer + subresource.layerCount <= (deUint32)texture.getNumLayers());
+
+ // Not all texture levels and layers are needed. Create new sub-texture.
+ const tcu::ConstPixelBufferAccess baseLevel = texture.getLevel(subresource.baseMipLevel);
+ tcu::Texture2DArray textureView (texture.getFormat(), baseLevel.getWidth(), baseLevel.getHeight(), subresource.layerCount);
+
+ copySubresourceRange(textureView, texture, subresource);
+
+ program = MovePtr<Program>(new SamplerProgram<tcu::Texture2DArray>(renderTargetFormat, textureView, sampler, samplerLod, componentMapping));
+ }
+ else
+ {
+ // Use all array layers
+ program = MovePtr<Program>(new SamplerProgram<tcu::Texture2DArray>(renderTargetFormat, texture, sampler, samplerLod, componentMapping));
+ }
+ }
+ }
+ break;
+
+ case VK_IMAGE_TYPE_3D:
+ {
+ const tcu::Texture3D& texture = dynamic_cast<const TestTexture3D&>(testTexture).getTexture();
+ program = MovePtr<Program>(new SamplerProgram<tcu::Texture3D>(renderTargetFormat, texture, sampler, samplerLod, componentMapping));
+ }
+ break;
+
+ default:
+ DE_ASSERT(false);
+ }
+
+ return program;
+}
+
+} // anonymous
+
+ImageSamplingInstance::ImageSamplingInstance (Context& context,
+ const tcu::IVec2& renderSize,
+ VkImageViewType imageViewType,
+ VkFormat imageFormat,
+ const tcu::IVec3& imageSize,
+ int layerCount,
+ const VkComponentMapping& componentMapping,
+ const VkImageSubresourceRange& subresourceRange,
+ const VkSamplerCreateInfo& samplerParams,
+ float samplerLod,
+ const std::vector<Vertex4Tex4>& vertices)
+ : vkt::TestInstance (context)
+ , m_imageViewType (imageViewType)
+ , m_imageSize (imageSize)
+ , m_layerCount (layerCount)
+ , m_componentMapping (componentMapping)
+ , m_subresourceRange (subresourceRange)
+ , m_samplerParams (samplerParams)
+ , m_samplerLod (samplerLod)
+ , m_renderSize (renderSize)
+ , m_colorFormat (VK_FORMAT_R8G8B8A8_UNORM)
+ , m_vertices (vertices)
+{
+ const DeviceInterface& vk = context.getDeviceInterface();
+ const VkDevice vkDevice = context.getDevice();
+ const VkQueue queue = context.getUniversalQueue();
+ const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
+ SimpleAllocator memAlloc (vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
+ const VkComponentMapping componentMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
+
+ if (!isSupportedSamplableFormat(context.getInstanceInterface(), context.getPhysicalDevice(), imageFormat))
+ throw tcu::NotSupportedError(std::string("Unsupported format for sampling: ") + getFormatName(imageFormat));
+
+ // Create texture image, view and sampler
+ {
+ VkImageCreateFlags imageFlags = 0u;
+
+ if (m_imageViewType == VK_IMAGE_VIEW_TYPE_CUBE || m_imageViewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
+ imageFlags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
+
+ // Initialize texture data
+ if (isCompressedFormat(imageFormat))
+ m_texture = createTestTexture(mapVkCompressedFormat(imageFormat), imageViewType, imageSize, layerCount);
+ else
+ m_texture = createTestTexture(mapVkFormat(imageFormat), imageViewType, imageSize, layerCount);
+
+ const VkImageCreateInfo imageParams =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ imageFlags, // VkImageCreateFlags flags;
+ getCompatibleImageType(m_imageViewType), // VkImageType imageType;
+ imageFormat, // VkFormat format;
+ { // VkExtent3D extent;
+ m_imageSize.x(),
+ m_imageSize.y(),
+ m_imageSize.z()
+ },
+ (deUint32)m_texture->getNumLevels(), // deUint32 mipLevels;
+ (deUint32)m_layerCount, // deUint32 arrayLayers;
+ VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
+ VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
+ VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
+ VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
+ 1u, // deUint32 queueFamilyIndexCount;
+ &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
+ VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
+ };
+
+ m_image = createImage(vk, vkDevice, &imageParams);
+ m_imageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_image), MemoryRequirement::Any);
+ VK_CHECK(vk.bindImageMemory(vkDevice, *m_image, m_imageAlloc->getMemory(), m_imageAlloc->getOffset()));
+
+ // Upload texture data
+ uploadTestTexture(vk, vkDevice, queue, queueFamilyIndex, memAlloc, *m_texture, *m_image);
+
+ // Create image view and sampler
+ const VkImageViewCreateInfo imageViewParams =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkImageViewCreateFlags flags;
+ *m_image, // VkImage image;
+ m_imageViewType, // VkImageViewType viewType;
+ imageFormat, // VkFormat format;
+ m_componentMapping, // VkComponentMapping components;
+ m_subresourceRange, // VkImageSubresourceRange subresourceRange;
+ };
+
+ m_imageView = createImageView(vk, vkDevice, &imageViewParams);
+ m_sampler = createSampler(vk, vkDevice, &m_samplerParams);
+ }
+
+ // Create descriptor set for combined image and sampler
+ {
+ DescriptorPoolBuilder descriptorPoolBuilder;
+ descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1u);
+ m_descriptorPool = descriptorPoolBuilder.build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
+
+ DescriptorSetLayoutBuilder setLayoutBuilder;
+ setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT);
+ m_descriptorSetLayout = setLayoutBuilder.build(vk, vkDevice);
+
+ const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo =
+ {
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ *m_descriptorPool, // VkDescriptorPool descriptorPool;
+ 1u, // deUint32 setLayoutCount;
+ &m_descriptorSetLayout.get() // const VkDescriptorSetLayout* pSetLayouts;
+ };
+
+ m_descriptorSet = allocateDescriptorSet(vk, vkDevice, &descriptorSetAllocateInfo);
+
+ const VkDescriptorImageInfo descriptorImageInfo =
+ {
+ *m_sampler, // VkSampler sampler;
+ *m_imageView, // VkImageView imageView;
+ VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout imageLayout;
+ };
+
+ DescriptorSetUpdateBuilder setUpdateBuilder;
+ setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &descriptorImageInfo);
+ setUpdateBuilder.update(vk, vkDevice);
+ }
+
+ // Create color image and view
+ {
+ const VkImageCreateInfo colorImageParams =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkImageCreateFlags flags;
+ VK_IMAGE_TYPE_2D, // VkImageType imageType;
+ m_colorFormat, // VkFormat format;
+ { m_renderSize.x(), m_renderSize.y(), 1u }, // VkExtent3D extent;
+ 1u, // deUint32 mipLevels;
+ 1u, // deUint32 arrayLayers;
+ VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
+ VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
+ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
+ VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
+ 1u, // deUint32 queueFamilyIndexCount;
+ &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
+ VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
+ };
+
+ m_colorImage = createImage(vk, vkDevice, &colorImageParams);
+ m_colorImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
+ VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
+
+ const VkImageViewCreateInfo colorAttachmentViewParams =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkImageViewCreateFlags flags;
+ *m_colorImage, // VkImage image;
+ VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
+ m_colorFormat, // VkFormat format;
+ componentMappingRGBA, // VkComponentMapping components;
+ { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange;
+ };
+
+ m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
+ }
+
+ // Create render pass
+ {
+ const VkAttachmentDescription colorAttachmentDescription =
+ {
+ 0u, // VkAttachmentDescriptionFlags flags;
+ m_colorFormat, // VkFormat format;
+ VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
+ VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
+ VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
+ VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
+ VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout;
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout;
+ };
+
+ const VkAttachmentReference colorAttachmentReference =
+ {
+ 0u, // deUint32 attachment;
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
+ };
+
+ const VkSubpassDescription subpassDescription =
+ {
+ 0u, // VkSubpassDescriptionFlags flags;
+ VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
+ 0u, // deUint32 inputAttachmentCount;
+ DE_NULL, // const VkAttachmentReference* pInputAttachments;
+ 1u, // deUint32 colorAttachmentCount;
+ &colorAttachmentReference, // const VkAttachmentReference* pColorAttachments;
+ DE_NULL, // const VkAttachmentReference* pResolveAttachments;
+ DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
+ 0u, // deUint32 preserveAttachmentCount;
+ DE_NULL // const VkAttachmentReference* pPreserveAttachments;
+ };
+
+ const VkRenderPassCreateInfo renderPassParams =
+ {
+ VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkRenderPassCreateFlags flags;
+ 1u, // deUint32 attachmentCount;
+ &colorAttachmentDescription, // const VkAttachmentDescription* pAttachments;
+ 1u, // deUint32 subpassCount;
+ &subpassDescription, // const VkSubpassDescription* pSubpasses;
+ 0u, // deUint32 dependencyCount;
+ DE_NULL // const VkSubpassDependency* pDependencies;
+ };
+
+ m_renderPass = createRenderPass(vk, vkDevice, &renderPassParams);
+ }
+
+ // Create framebuffer
+ {
+ const VkFramebufferCreateInfo framebufferParams =
+ {
+ VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkFramebufferCreateFlags flags;
+ *m_renderPass, // VkRenderPass renderPass;
+ 1u, // deUint32 attachmentCount;
+ &m_colorAttachmentView.get(), // const VkImageView* pAttachments;
+ (deUint32)m_renderSize.x(), // deUint32 width;
+ (deUint32)m_renderSize.y(), // deUint32 height;
+ 1u // deUint32 layers;
+ };
+
+ m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
+ }
+
+ // Create pipeline layout
+ {
+ const VkPipelineLayoutCreateInfo pipelineLayoutParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineLayoutCreateFlags flags;
+ 1u, // deUint32 setLayoutCount;
+ &m_descriptorSetLayout.get(), // const VkDescriptorSetLayout* pSetLayouts;
+ 0u, // deUint32 pushConstantRangeCount;
+ DE_NULL // const VkPushConstantRange* pPushConstantRanges;
+ };
+
+ m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
+ }
+
+ m_vertexShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("tex_vert"), 0);
+ m_fragmentShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("tex_frag"), 0);
+
+ // Create pipeline
+ {
+ const VkPipelineShaderStageCreateInfo shaderStages[2] =
+ {
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineShaderStageCreateFlags flags;
+ VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage;
+ *m_vertexShaderModule, // VkShaderModule module;
+ "main", // const char* pName;
+ DE_NULL // const VkSpecializationInfo* pSpecializationInfo;
+ },
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineShaderStageCreateFlags flags;
+ VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage;
+ *m_fragmentShaderModule, // VkShaderModule module;
+ "main", // const char* pName;
+ DE_NULL // const VkSpecializationInfo* pSpecializationInfo;
+ }
+ };
+
+ const VkVertexInputBindingDescription vertexInputBindingDescription =
+ {
+ 0u, // deUint32 binding;
+ sizeof(Vertex4Tex4), // deUint32 strideInBytes;
+ VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate inputRate;
+ };
+
+ const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
+ {
+ {
+ 0u, // deUint32 location;
+ 0u, // deUint32 binding;
+ VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
+ 0u // deUint32 offset;
+ },
+ {
+ 1u, // deUint32 location;
+ 0u, // deUint32 binding;
+ VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
+ DE_OFFSET_OF(Vertex4Tex4, texCoord), // deUint32 offset;
+ }
+ };
+
+ const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineVertexInputStateCreateFlags flags;
+ 1u, // deUint32 vertexBindingDescriptionCount;
+ &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
+ 2u, // deUint32 vertexAttributeDescriptionCount;
+ vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
+ };
+
+ const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineInputAssemblyStateCreateFlags flags;
+ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology topology;
+ false // VkBool32 primitiveRestartEnable;
+ };
+
+ const VkViewport viewport =
+ {
+ 0.0f, // float x;
+ 0.0f, // float y;
+ (float)m_renderSize.x(), // float width;
+ (float)m_renderSize.y(), // float height;
+ 0.0f, // float minDepth;
+ 1.0f // float maxDepth;
+ };
+
+ const VkRect2D scissor = { { 0, 0 }, { m_renderSize.x(), m_renderSize.y() } };
+
+ const VkPipelineViewportStateCreateInfo viewportStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineViewportStateCreateFlags flags;
+ 1u, // deUint32 viewportCount;
+ &viewport, // const VkViewport* pViewports;
+ 1u, // deUint32 scissorCount;
+ &scissor // const VkRect2D* pScissors;
+ };
+
+ const VkPipelineRasterizationStateCreateInfo rasterStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineRasterizationStateCreateFlags flags;
+ false, // VkBool32 depthClampEnable;
+ false, // VkBool32 rasterizerDiscardEnable;
+ VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
+ VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
+ VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
+ false, // VkBool32 depthBiasEnable;
+ 0.0f, // float depthBiasConstantFactor;
+ 0.0f, // float depthBiasClamp;
+ 0.0f, // float depthBiasSlopeFactor;
+ 1.0f // float lineWidth;
+ };
+
+ const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
+ {
+ false, // VkBool32 blendEnable;
+ VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
+ VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
+ VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
+ VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor;
+ VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
+ VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
+ VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | // VkColorComponentFlags colorWriteMask;
+ VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
+ };
+
+ const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineColorBlendStateCreateFlags flags;
+ false, // VkBool32 logicOpEnable;
+ VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
+ 1u, // deUint32 attachmentCount;
+ &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
+ { 0.0f, 0.0f, 0.0f, 0.0f } // float blendConstants[4];
+ };
+
+ const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineMultisampleStateCreateFlags flags;
+ VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
+ false, // VkBool32 sampleShadingEnable;
+ 0.0f, // float minSampleShading;
+ DE_NULL, // const VkSampleMask* pSampleMask;
+ false, // VkBool32 alphaToCoverageEnable;
+ false // VkBool32 alphaToOneEnable;
+ };
+
+ VkPipelineDepthStencilStateCreateInfo depthStencilStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineDepthStencilStateCreateFlags flags;
+ false, // VkBool32 depthTestEnable;
+ false, // VkBool32 depthWriteEnable;
+ VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp;
+ false, // VkBool32 depthBoundsTestEnable;
+ false, // VkBool32 stencilTestEnable;
+ { // VkStencilOpState front;
+ VK_STENCIL_OP_ZERO, // VkStencilOp failOp;
+ VK_STENCIL_OP_ZERO, // VkStencilOp passOp;
+ VK_STENCIL_OP_ZERO, // VkStencilOp depthFailOp;
+ VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
+ 0u, // deUint32 compareMask;
+ 0u, // deUint32 writeMask;
+ 0u // deUint32 reference;
+ },
+ { // VkStencilOpState back;
+ VK_STENCIL_OP_ZERO, // VkStencilOp failOp;
+ VK_STENCIL_OP_ZERO, // VkStencilOp passOp;
+ VK_STENCIL_OP_ZERO, // VkStencilOp depthFailOp;
+ VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
+ 0u, // deUint32 compareMask;
+ 0u, // deUint32 writeMask;
+ 0u // deUint32 reference;
+ },
+ -1.0f, // float minDepthBounds;
+ +1.0f // float maxDepthBounds;
+ };
+
+ const VkPipelineDynamicStateCreateInfo dynamicStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineDynamicStateCreateFlags flags;
+ 0u, // deUint32 dynamicStateCount;
+ DE_NULL // const VkDynamicState* pDynamicStates;
+ };
+
+ const VkGraphicsPipelineCreateInfo graphicsPipelineParams =
+ {
+ VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineCreateFlags flags;
+ 2u, // deUint32 stageCount;
+ shaderStages, // const VkPipelineShaderStageCreateInfo* pStages;
+ &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
+ &inputAssemblyStateParams, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
+ DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
+ &viewportStateParams, // const VkPipelineViewportStateCreateInfo* pViewportState;
+ &rasterStateParams, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
+ &multisampleStateParams, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
+ &depthStencilStateParams, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
+ &colorBlendStateParams, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
+ &dynamicStateParams, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
+ *m_pipelineLayout, // VkPipelineLayout layout;
+ *m_renderPass, // VkRenderPass renderPass;
+ 0u, // deUint32 subpass;
+ 0u, // VkPipeline basePipelineHandle;
+ 0u // deInt32 basePipelineIndex;
+ };
+
+ m_graphicsPipeline = createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams);
+ }
+
+ // Create vertex buffer
+ {
+ const VkDeviceSize vertexBufferSize = (VkDeviceSize)(m_vertices.size() * sizeof(Vertex4Tex4));
+ const VkBufferCreateInfo vertexBufferParams =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkBufferCreateFlags flags;
+ vertexBufferSize, // VkDeviceSize size;
+ VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
+ VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
+ 1u, // deUint32 queueFamilyIndexCount;
+ &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
+ };
+
+ DE_ASSERT(vertexBufferSize > 0);
+
+ m_vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams);
+ m_vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
+
+ VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
+
+ // Load vertices into vertex buffer
+ deMemcpy(m_vertexBufferAlloc->getHostPtr(), &m_vertices[0], vertexBufferSize);
+ flushMappedMemoryRange(vk, vkDevice, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset(), vertexBufferParams.size);
+ }
+
+ // Create command pool
+ {
+ const VkCommandPoolCreateInfo cmdPoolParams =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // VkCommandPoolCreateFlags flags;
+ queueFamilyIndex // deUint32 queueFamilyIndex;
+ };
+
+ m_cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams);
+ }
+
+ // Create command buffer
+ {
+ const VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ *m_cmdPool, // VkCommandPool commandPool;
+ VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
+ 1u, // deUint32 bufferCount;
+ };
+
+ const VkCommandBufferBeginInfo cmdBufferBeginInfo =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkCommandBufferUsageFlags flags;
+ DE_NULL, // VkRenderPass renderPass;
+ 0u, // deUint32 subpass;
+ DE_NULL, // VkFramebuffer framebuffer;
+ false, // VkBool32 occlusionQueryEnable;
+ 0u, // VkQueryControlFlags queryFlags;
+ 0u // VkQueryPipelineStatisticFlags pipelineStatistics;
+ };
+
+ const VkClearValue attachmentClearValue = defaultClearValue(m_colorFormat);
+
+ const VkRenderPassBeginInfo renderPassBeginInfo =
+ {
+ VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ *m_renderPass, // VkRenderPass renderPass;
+ *m_framebuffer, // VkFramebuffer framebuffer;
+ { { 0, 0 }, { m_renderSize.x(), m_renderSize.y() } }, // VkRect2D renderArea;
+ 1, // deUint32 clearValueCount;
+ &attachmentClearValue // const VkClearValue* pClearValues;
+ };
+
+ m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferAllocateInfo);
+
+ VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
+ vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
+
+ vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline);
+
+ vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0, 1, &m_descriptorSet.get(), 0, DE_NULL);
+
+ const VkDeviceSize vertexBufferOffset = 0;
+ vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
+ vk.cmdDraw(*m_cmdBuffer, (deUint32)m_vertices.size(), 1, 0, 0);
+
+ vk.cmdEndRenderPass(*m_cmdBuffer);
+ VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
+ }
+
+ // Create fence
+ {
+ const VkFenceCreateInfo fenceParams =
+ {
+ VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u // VkFenceCreateFlags flags;
+ };
+
+ m_fence = createFence(vk, vkDevice, &fenceParams);
+ }
+}
+
+ImageSamplingInstance::~ImageSamplingInstance (void)
+{
+}
+
+tcu::TestStatus ImageSamplingInstance::iterate (void)
+{
+ const DeviceInterface& vk = m_context.getDeviceInterface();
+ const VkDevice vkDevice = m_context.getDevice();
+ const VkQueue queue = m_context.getUniversalQueue();
+ const VkSubmitInfo submitInfo =
+ {
+ VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // deUint32 waitSemaphoreCount;
+ DE_NULL, // const VkSemaphore* pWaitSemaphores;
+ 1u, // deUint32 commandBufferCount;
+ &m_cmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
+ 0u, // deUint32 signalSemaphoreCount;
+ DE_NULL // const VkSemaphore* pSignalSemaphores;
+ };
+
+ VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
+ VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
+ VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity */));
+
+ return verifyImage();
+}
+
+tcu::TestStatus ImageSamplingInstance::verifyImage (void)
+{
+ const tcu::TextureFormat colorFormat = mapVkFormat(m_colorFormat);
+ const tcu::TextureFormat depthStencilFormat = tcu::TextureFormat(); // Undefined depth/stencil format.
+ const tcu::Sampler sampler = mapVkSampler(m_samplerParams);
+ const tcu::UVec4 componentMapping = mapVkComponentMapping(m_componentMapping);
+ float samplerLod;
+ bool compareOk;
+ MovePtr<Program> program;
+ MovePtr<ReferenceRenderer> refRenderer;
+
+ // Set up LOD of reference sampler
+ if (m_samplerParams.mipmapMode == VK_SAMPLER_MIPMAP_MODE_BASE)
+ samplerLod = 0.0f;
+ else
+ samplerLod = de::max(m_samplerParams.minLod, de::min(m_samplerParams.maxLod, m_samplerParams.mipLodBias + m_samplerLod));
+
+ // Create reference program that uses image subresource range
+ program = createRefProgram(colorFormat, sampler, samplerLod, componentMapping, *m_texture, m_imageViewType, m_layerCount, m_subresourceRange);
+ const rr::Program referenceProgram = program->getReferenceProgram();
+
+ // Render reference image
+ refRenderer = MovePtr<ReferenceRenderer>(new ReferenceRenderer(m_renderSize.x(), m_renderSize.y(), 1, colorFormat, depthStencilFormat, &referenceProgram));
+ const rr::RenderState renderState(refRenderer->getViewportState());
+ refRenderer->draw(renderState, rr::PRIMITIVETYPE_TRIANGLES, m_vertices);
+
+ // Compare result with reference image
+ {
+ const DeviceInterface& vk = m_context.getDeviceInterface();
+ const VkDevice vkDevice = m_context.getDevice();
+ const VkQueue queue = m_context.getUniversalQueue();
+ const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
+ SimpleAllocator memAlloc (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
+ MovePtr<tcu::TextureLevel> result = readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, memAlloc, *m_colorImage, m_colorFormat, m_renderSize);
+
+ compareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
+ "IntImageCompare",
+ "Image comparison",
+ refRenderer->getAccess(),
+ result->getAccess(),
+ tcu::UVec4(4, 4, 4, 4),
+ tcu::IVec3(1, 1, 0),
+ true,
+ tcu::COMPARE_LOG_RESULT);
+ }
+
+ if (compareOk)
+ return tcu::TestStatus::pass("Result image matches reference");
+ else
+ return tcu::TestStatus::fail("Image mismatch");
+}
+
+} // pipeline
+} // vkt
--- /dev/null
+#ifndef _VKTPIPELINEIMAGESAMPLINGINSTANCE_HPP
+#define _VKTPIPELINEIMAGESAMPLINGINSTANCE_HPP
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Imagination Technologies Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by Khronos,
+ * at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Image sampling case
+ *//*--------------------------------------------------------------------*/
+
+#include "vkDefs.hpp"
+
+#include "vktTestCase.hpp"
+#include "vktTestCaseUtil.hpp"
+#include "vktPipelineImageUtil.hpp"
+#include "vktPipelineReferenceRenderer.hpp"
+#include "vktPipelineVertexUtil.hpp"
+#include "tcuVectorUtil.hpp"
+
+namespace vkt
+{
+namespace pipeline
+{
+
+class ImageSamplingInstance : public vkt::TestInstance
+{
+public:
+ ImageSamplingInstance (Context& context,
+ const tcu::IVec2& renderSize,
+ vk::VkImageViewType imageViewType,
+ vk::VkFormat imageFormat,
+ const tcu::IVec3& imageSize,
+ int layerCount,
+ const vk::VkComponentMapping& componentMapping,
+ const vk::VkImageSubresourceRange& subresourceRange,
+ const vk::VkSamplerCreateInfo& samplerParams,
+ float samplerLod,
+ const std::vector<Vertex4Tex4>& vertices);
+
+ virtual ~ImageSamplingInstance (void);
+
+ virtual tcu::TestStatus iterate (void);
+
+protected:
+ tcu::TestStatus verifyImage (void);
+
+private:
+ const vk::VkImageViewType m_imageViewType;
+ const tcu::IVec3 m_imageSize;
+ const int m_layerCount;
+
+ const vk::VkComponentMapping m_componentMapping;
+ const vk::VkImageSubresourceRange m_subresourceRange;
+ const vk::VkSamplerCreateInfo m_samplerParams;
+ const float m_samplerLod;
+
+ vk::Move<vk::VkImage> m_image;
+ de::MovePtr<vk::Allocation> m_imageAlloc;
+ vk::Move<vk::VkImageView> m_imageView;
+ vk::Move<vk::VkSampler> m_sampler;
+ de::MovePtr<TestTexture> m_texture;
+
+ const tcu::IVec2 m_renderSize;
+ const vk::VkFormat m_colorFormat;
+
+ vk::Move<vk::VkDescriptorPool> m_descriptorPool;
+ vk::Move<vk::VkDescriptorSetLayout> m_descriptorSetLayout;
+ vk::Move<vk::VkDescriptorSet> m_descriptorSet;
+
+ vk::Move<vk::VkImage> m_colorImage;
+ de::MovePtr<vk::Allocation> m_colorImageAlloc;
+ vk::Move<vk::VkImageView> m_colorAttachmentView;
+ vk::Move<vk::VkRenderPass> m_renderPass;
+ vk::Move<vk::VkFramebuffer> m_framebuffer;
+
+ vk::Move<vk::VkShaderModule> m_vertexShaderModule;
+ vk::Move<vk::VkShaderModule> m_fragmentShaderModule;
+
+ vk::Move<vk::VkBuffer> m_vertexBuffer;
+ std::vector<Vertex4Tex4> m_vertices;
+ de::MovePtr<vk::Allocation> m_vertexBufferAlloc;
+
+ vk::Move<vk::VkPipelineLayout> m_pipelineLayout;
+ vk::Move<vk::VkPipeline> m_graphicsPipeline;
+
+ vk::Move<vk::VkCommandPool> m_cmdPool;
+ vk::Move<vk::VkCommandBuffer> m_cmdBuffer;
+
+ vk::Move<vk::VkFence> m_fence;
+};
+
+} // pipeline
+} // vkt
+
+#endif // _VKTPIPELINEIMAGESAMPLINGINSTANCE_HPP
--- /dev/null
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Imagination Technologies Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by Khronos,
+ * at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Image Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktPipelineImageTests.hpp"
+#include "vktPipelineImageSamplingInstance.hpp"
+#include "vktPipelineImageUtil.hpp"
+#include "vktPipelineVertexUtil.hpp"
+#include "vktTestCase.hpp"
+#include "vkImageUtil.hpp"
+#include "vkPrograms.hpp"
+#include "tcuTextureUtil.hpp"
+#include "deStringUtil.hpp"
+
+#include <sstream>
+#include <vector>
+
+namespace vkt
+{
+namespace pipeline
+{
+
+using namespace vk;
+using de::MovePtr;
+
+namespace
+{
+
+class ImageTest : public vkt::TestCase
+{
+public:
+ ImageTest (tcu::TestContext& testContext,
+ const char* name,
+ const char* description,
+ VkImageViewType imageViewType,
+ VkFormat imageFormat,
+ const tcu::IVec3& imageSize,
+ int arraySize);
+
+ virtual void initPrograms (SourceCollections& sourceCollections) const;
+ virtual TestInstance* createInstance (Context& context) const;
+ static std::string getGlslSamplerType (const tcu::TextureFormat& format, VkImageViewType type);
+
+private:
+ VkImageViewType m_imageViewType;
+ VkFormat m_imageFormat;
+ tcu::IVec3 m_imageSize;
+ int m_arraySize;
+};
+
+ImageTest::ImageTest (tcu::TestContext& testContext,
+ const char* name,
+ const char* description,
+ VkImageViewType imageViewType,
+ VkFormat imageFormat,
+ const tcu::IVec3& imageSize,
+ int arraySize)
+
+ : vkt::TestCase (testContext, name, description)
+ , m_imageViewType (imageViewType)
+ , m_imageFormat (imageFormat)
+ , m_imageSize (imageSize)
+ , m_arraySize (arraySize)
+{
+}
+
+void ImageTest::initPrograms (SourceCollections& sourceCollections) const
+{
+ std::ostringstream vertexSrc;
+ std::ostringstream fragmentSrc;
+ const char* texCoordSwizzle = DE_NULL;
+ const tcu::TextureFormat format = (isCompressedFormat(m_imageFormat)) ? tcu::getUncompressedFormat(mapVkCompressedFormat(m_imageFormat))
+ : mapVkFormat(m_imageFormat);
+ const tcu::TextureFormatInfo formatInfo = tcu::getTextureFormatInfo(format);
+
+ switch (m_imageViewType)
+ {
+ case VK_IMAGE_VIEW_TYPE_1D:
+ texCoordSwizzle = "x";
+ break;
+ case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
+ case VK_IMAGE_VIEW_TYPE_2D:
+ texCoordSwizzle = "xy";
+ break;
+ case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
+ case VK_IMAGE_VIEW_TYPE_3D:
+ case VK_IMAGE_VIEW_TYPE_CUBE:
+ texCoordSwizzle = "xyz";
+ break;
+ case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
+ texCoordSwizzle = "xyzw";
+ break;
+ default:
+ DE_ASSERT(false);
+ break;
+ }
+
+ vertexSrc << "#version 440\n"
+ << "layout(location = 0) in vec4 position;\n"
+ << "layout(location = 1) in vec4 texCoords;\n"
+ << "layout(location = 0) out highp vec4 vtxTexCoords;\n"
+ << "out gl_PerVertex {\n"
+ << " vec4 gl_Position;\n"
+ << "};\n"
+ << "void main (void)\n"
+ << "{\n"
+ << " gl_Position = position;\n"
+ << " vtxTexCoords = texCoords;\n"
+ << "}\n";
+
+ fragmentSrc << "#version 440\n"
+ << "layout(set = 0, binding = 0) uniform highp " << getGlslSamplerType(format, m_imageViewType) << " texSampler;\n"
+ << "layout(location = 0) in highp vec4 vtxTexCoords;\n"
+ << "layout(location = 0) out highp vec4 fragColor;\n"
+ << "void main (void)\n"
+ << "{\n"
+ << " fragColor = (texture(texSampler, vtxTexCoords." << texCoordSwizzle << std::scientific << ") * vec4" << formatInfo.lookupScale << ") + vec4" << formatInfo.lookupBias << ";\n"
+ << "}\n";
+
+ sourceCollections.glslSources.add("tex_vert") << glu::VertexSource(vertexSrc.str());
+ sourceCollections.glslSources.add("tex_frag") << glu::FragmentSource(fragmentSrc.str());
+}
+
+TestInstance* ImageTest::createInstance (Context& context) const
+{
+ tcu::IVec2 renderSize;
+
+ if (m_imageViewType == VK_IMAGE_VIEW_TYPE_1D || m_imageViewType == VK_IMAGE_VIEW_TYPE_2D)
+ {
+ renderSize = tcu::IVec2(m_imageSize.x(), m_imageSize.y());
+ }
+ else
+ {
+ // Draw a 3x2 grid of texture layers
+ renderSize = tcu::IVec2(m_imageSize.x() * 3, m_imageSize.y() * 2);
+ }
+
+ const std::vector<Vertex4Tex4> vertices = createTestQuadMosaic(m_imageViewType);
+ const VkComponentMapping componentMapping = getFormatComponentMapping(m_imageFormat);
+ const VkImageSubresourceRange subresourceRange =
+ {
+ VK_IMAGE_ASPECT_COLOR_BIT,
+ 0u,
+ (deUint32)deLog2Floor32(deMax32(m_imageSize.x(), deMax32(m_imageSize.y(), m_imageSize.z()))) + 1,
+ 0u,
+ (deUint32)m_arraySize,
+ };
+
+ const VkSamplerCreateInfo samplerParams =
+ {
+ VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkSamplerCreateFlags flags;
+ VK_FILTER_NEAREST, // VkFilter magFilter;
+ VK_FILTER_NEAREST, // VkFilter minFilter;
+ VK_SAMPLER_MIPMAP_MODE_NEAREST, // VkSamplerMipmapMode mipmapMode;
+ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeU;
+ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeV;
+ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeW;
+ 0.0f, // float mipLodBias;
+ 1.0f, // float maxAnisotropy;
+ false, // VkBool32 compareEnable;
+ VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
+ 0.0f, // float minLod;
+ (float)(subresourceRange.levelCount - 1), // float maxLod;
+ getFormatBorderColor(BORDER_COLOR_TRANSPARENT_BLACK, m_imageFormat), // VkBorderColor borderColor;
+ false // VkBool32 unnormalizedCoordinates;
+ };
+
+ return new ImageSamplingInstance(context, renderSize, m_imageViewType, m_imageFormat, m_imageSize, m_arraySize, componentMapping, subresourceRange, samplerParams, 0.0f, vertices);
+}
+
+std::string ImageTest::getGlslSamplerType (const tcu::TextureFormat& format, VkImageViewType type)
+{
+ std::ostringstream samplerType;
+
+ if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
+ samplerType << "u";
+ else if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
+ samplerType << "i";
+
+ switch (type)
+ {
+ case VK_IMAGE_VIEW_TYPE_1D:
+ samplerType << "sampler1D";
+ break;
+
+ case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
+ samplerType << "sampler1DArray";
+ break;
+
+ case VK_IMAGE_VIEW_TYPE_2D:
+ samplerType << "sampler2D";
+ break;
+
+ case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
+ samplerType << "sampler2DArray";
+ break;
+
+ case VK_IMAGE_VIEW_TYPE_3D:
+ samplerType << "sampler3D";
+ break;
+
+ case VK_IMAGE_VIEW_TYPE_CUBE:
+ samplerType << "samplerCube";
+ break;
+
+ case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
+ samplerType << "samplerCubeArray";
+ break;
+
+ default:
+ DE_FATAL("Unknown image view type");
+ break;
+ }
+
+ return samplerType.str();
+}
+
+std::string getFormatCaseName (const VkFormat format)
+{
+ const std::string fullName = getFormatName(format);
+
+ DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_"));
+
+ return de::toLower(fullName.substr(10));
+}
+
+std::string getSizeName (VkImageViewType viewType, const tcu::IVec3& size, int arraySize)
+{
+ std::ostringstream caseName;
+
+ switch (viewType)
+ {
+ case VK_IMAGE_VIEW_TYPE_1D:
+ case VK_IMAGE_VIEW_TYPE_2D:
+ case VK_IMAGE_VIEW_TYPE_CUBE:
+ caseName << size.x() << "x" << size.y();
+ break;
+
+ case VK_IMAGE_VIEW_TYPE_3D:
+ caseName << size.x() << "x" << size.y() << "x" << size.z();
+ break;
+
+ case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
+ case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
+ case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
+ caseName << size.x() << "x" << size.y() << "_array_of_" << arraySize;
+ break;
+
+ default:
+ DE_ASSERT(false);
+ break;
+ }
+
+ return caseName.str();
+}
+
+de::MovePtr<tcu::TestCaseGroup> createImageSizeTests (tcu::TestContext& testCtx, VkImageViewType imageViewType, VkFormat imageFormat)
+{
+ using tcu::IVec3;
+
+ std::vector<IVec3> imageSizes;
+ std::vector<int> arraySizes;
+ de::MovePtr<tcu::TestCaseGroup> imageSizeTests (new tcu::TestCaseGroup(testCtx, "size", ""));
+
+ // Select image imageSizes
+ switch (imageViewType)
+ {
+ case VK_IMAGE_VIEW_TYPE_1D:
+ case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
+ // POT
+ imageSizes.push_back(IVec3(1, 1, 1));
+ imageSizes.push_back(IVec3(2, 1, 1));
+ imageSizes.push_back(IVec3(32, 1, 1));
+ imageSizes.push_back(IVec3(128, 1, 1));
+ imageSizes.push_back(IVec3(512, 1, 1));
+
+ // NPOT
+ imageSizes.push_back(IVec3(3, 1, 1));
+ imageSizes.push_back(IVec3(13, 1, 1));
+ imageSizes.push_back(IVec3(127, 1, 1));
+ imageSizes.push_back(IVec3(443, 1, 1));
+ break;
+
+ case VK_IMAGE_VIEW_TYPE_2D:
+ case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
+ // POT
+ imageSizes.push_back(IVec3(1, 1, 1));
+ imageSizes.push_back(IVec3(2, 2, 1));
+ imageSizes.push_back(IVec3(32, 32, 1));
+
+ // NPOT
+ imageSizes.push_back(IVec3(3, 3, 1));
+ imageSizes.push_back(IVec3(13, 13, 1));
+
+ // POT rectangular
+ imageSizes.push_back(IVec3(8, 16, 1));
+ imageSizes.push_back(IVec3(32, 16, 1));
+
+ // NPOT rectangular
+ imageSizes.push_back(IVec3(13, 23, 1));
+ imageSizes.push_back(IVec3(23, 8, 1));
+ break;
+
+ case VK_IMAGE_VIEW_TYPE_3D:
+ // POT cube
+ imageSizes.push_back(IVec3(1, 1, 1));
+ imageSizes.push_back(IVec3(2, 2, 2));
+ imageSizes.push_back(IVec3(16, 16, 16));
+
+ // POT non-cube
+ imageSizes.push_back(IVec3(32, 16, 8));
+ imageSizes.push_back(IVec3(8, 16, 32));
+ break;
+
+ case VK_IMAGE_VIEW_TYPE_CUBE:
+ case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
+ // POT
+ imageSizes.push_back(IVec3(32, 32, 1));
+
+ // NPOT
+ imageSizes.push_back(IVec3(13, 13, 1));
+ break;
+
+ default:
+ DE_ASSERT(false);
+ break;
+ }
+
+ // Select array sizes
+ switch (imageViewType)
+ {
+ case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
+ case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
+ arraySizes.push_back(3);
+ arraySizes.push_back(6);
+ break;
+
+ case VK_IMAGE_VIEW_TYPE_CUBE:
+ arraySizes.push_back(6);
+ break;
+
+ case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
+ arraySizes.push_back(6);
+ arraySizes.push_back(6 * 6);
+ break;
+
+ default:
+ arraySizes.push_back(1);
+ break;
+ }
+
+ for (size_t sizeNdx = 0; sizeNdx < imageSizes.size(); sizeNdx++)
+ {
+ for (size_t arraySizeNdx = 0; arraySizeNdx < arraySizes.size(); arraySizeNdx++)
+ {
+ imageSizeTests->addChild(new ImageTest(testCtx,
+ getSizeName(imageViewType, imageSizes[sizeNdx], arraySizes[arraySizeNdx]).c_str(),
+ "",
+ imageViewType,
+ imageFormat,
+ imageSizes[sizeNdx],
+ arraySizes[arraySizeNdx]));
+ }
+ }
+
+ return imageSizeTests;
+}
+
+} // anonymous
+
+tcu::TestCaseGroup* createImageTests (tcu::TestContext& testCtx)
+{
+ const struct
+ {
+ VkImageViewType type;
+ const char* name;
+ }
+ imageViewTypes[] =
+ {
+ { VK_IMAGE_VIEW_TYPE_1D, "1d" },
+ { VK_IMAGE_VIEW_TYPE_1D_ARRAY, "1d_array" },
+ { VK_IMAGE_VIEW_TYPE_2D, "2d" },
+ { VK_IMAGE_VIEW_TYPE_2D_ARRAY, "2d_array" },
+ { VK_IMAGE_VIEW_TYPE_3D, "3d" },
+ { VK_IMAGE_VIEW_TYPE_CUBE, "cube" },
+ { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, "cube_array" }
+ };
+
+ // All supported dEQP formats that are not intended for depth or stencil.
+ const VkFormat formats[] =
+ {
+ VK_FORMAT_R4G4_UNORM_PACK8,
+ VK_FORMAT_R4G4B4A4_UNORM_PACK16,
+ VK_FORMAT_R5G6B5_UNORM_PACK16,
+ VK_FORMAT_R5G5B5A1_UNORM_PACK16,
+ VK_FORMAT_R8_UNORM,
+ VK_FORMAT_R8_SNORM,
+ VK_FORMAT_R8_USCALED,
+ VK_FORMAT_R8_SSCALED,
+ VK_FORMAT_R8_UINT,
+ VK_FORMAT_R8_SINT,
+ VK_FORMAT_R8_SRGB,
+ VK_FORMAT_R8G8_UNORM,
+ VK_FORMAT_R8G8_SNORM,
+ VK_FORMAT_R8G8_USCALED,
+ VK_FORMAT_R8G8_SSCALED,
+ VK_FORMAT_R8G8_UINT,
+ VK_FORMAT_R8G8_SINT,
+ VK_FORMAT_R8G8_SRGB,
+ VK_FORMAT_R8G8B8_UNORM,
+ VK_FORMAT_R8G8B8_SNORM,
+ VK_FORMAT_R8G8B8_USCALED,
+ VK_FORMAT_R8G8B8_SSCALED,
+ VK_FORMAT_R8G8B8_UINT,
+ VK_FORMAT_R8G8B8_SINT,
+ VK_FORMAT_R8G8B8_SRGB,
+ VK_FORMAT_R8G8B8A8_UNORM,
+ VK_FORMAT_R8G8B8A8_SNORM,
+ VK_FORMAT_R8G8B8A8_USCALED,
+ VK_FORMAT_R8G8B8A8_SSCALED,
+ VK_FORMAT_R8G8B8A8_UINT,
+ VK_FORMAT_R8G8B8A8_SINT,
+ VK_FORMAT_R8G8B8A8_SRGB,
+ VK_FORMAT_A2R10G10B10_UNORM_PACK32,
+ VK_FORMAT_A2R10G10B10_UINT_PACK32,
+ VK_FORMAT_A2R10G10B10_USCALED_PACK32,
+ VK_FORMAT_R16_UNORM,
+ VK_FORMAT_R16_SNORM,
+ VK_FORMAT_R16_USCALED,
+ VK_FORMAT_R16_SSCALED,
+ VK_FORMAT_R16_UINT,
+ VK_FORMAT_R16_SINT,
+ VK_FORMAT_R16_SFLOAT,
+ VK_FORMAT_R16G16_UNORM,
+ VK_FORMAT_R16G16_SNORM,
+ VK_FORMAT_R16G16_USCALED,
+ VK_FORMAT_R16G16_SSCALED,
+ VK_FORMAT_R16G16_UINT,
+ VK_FORMAT_R16G16_SINT,
+ VK_FORMAT_R16G16_SFLOAT,
+ VK_FORMAT_R16G16B16_UNORM,
+ VK_FORMAT_R16G16B16_SNORM,
+ VK_FORMAT_R16G16B16_USCALED,
+ VK_FORMAT_R16G16B16_SSCALED,
+ VK_FORMAT_R16G16B16_UINT,
+ VK_FORMAT_R16G16B16_SINT,
+ VK_FORMAT_R16G16B16_SFLOAT,
+ VK_FORMAT_R16G16B16A16_UNORM,
+ VK_FORMAT_R16G16B16A16_SNORM,
+ VK_FORMAT_R16G16B16A16_USCALED,
+ VK_FORMAT_R16G16B16A16_SSCALED,
+ VK_FORMAT_R16G16B16A16_UINT,
+ VK_FORMAT_R16G16B16A16_SINT,
+ VK_FORMAT_R16G16B16A16_SFLOAT,
+ VK_FORMAT_R32_UINT,
+ VK_FORMAT_R32_SINT,
+ VK_FORMAT_R32_SFLOAT,
+ VK_FORMAT_R32G32_UINT,
+ VK_FORMAT_R32G32_SINT,
+ VK_FORMAT_R32G32_SFLOAT,
+ VK_FORMAT_R32G32B32_UINT,
+ VK_FORMAT_R32G32B32_SINT,
+ VK_FORMAT_R32G32B32_SFLOAT,
+ VK_FORMAT_R32G32B32A32_UINT,
+ VK_FORMAT_R32G32B32A32_SINT,
+ VK_FORMAT_R32G32B32A32_SFLOAT,
+ VK_FORMAT_B10G11R11_UFLOAT_PACK32,
+ VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
+ VK_FORMAT_B4G4R4A4_UNORM_PACK16,
+ VK_FORMAT_B5G5R5A1_UNORM_PACK16,
+
+ // Compressed formats
+ VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,
+ VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK,
+ VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK,
+ VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK,
+ VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK,
+ VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK,
+ VK_FORMAT_EAC_R11_UNORM_BLOCK,
+ VK_FORMAT_EAC_R11_SNORM_BLOCK,
+ VK_FORMAT_EAC_R11G11_UNORM_BLOCK,
+ VK_FORMAT_EAC_R11G11_SNORM_BLOCK,
+ VK_FORMAT_ASTC_4x4_UNORM_BLOCK,
+ VK_FORMAT_ASTC_4x4_SRGB_BLOCK,
+ VK_FORMAT_ASTC_5x4_UNORM_BLOCK,
+ VK_FORMAT_ASTC_5x4_SRGB_BLOCK,
+ VK_FORMAT_ASTC_5x5_UNORM_BLOCK,
+ VK_FORMAT_ASTC_5x5_SRGB_BLOCK,
+ VK_FORMAT_ASTC_6x5_UNORM_BLOCK,
+ VK_FORMAT_ASTC_6x5_SRGB_BLOCK,
+ VK_FORMAT_ASTC_6x6_UNORM_BLOCK,
+ VK_FORMAT_ASTC_6x6_SRGB_BLOCK,
+ VK_FORMAT_ASTC_8x5_UNORM_BLOCK,
+ VK_FORMAT_ASTC_8x5_SRGB_BLOCK,
+ VK_FORMAT_ASTC_8x6_UNORM_BLOCK,
+ VK_FORMAT_ASTC_8x6_SRGB_BLOCK,
+ VK_FORMAT_ASTC_8x8_UNORM_BLOCK,
+ VK_FORMAT_ASTC_8x8_SRGB_BLOCK,
+ VK_FORMAT_ASTC_10x5_UNORM_BLOCK,
+ VK_FORMAT_ASTC_10x5_SRGB_BLOCK,
+ VK_FORMAT_ASTC_10x6_UNORM_BLOCK,
+ VK_FORMAT_ASTC_10x6_SRGB_BLOCK,
+ VK_FORMAT_ASTC_10x8_UNORM_BLOCK,
+ VK_FORMAT_ASTC_10x8_SRGB_BLOCK,
+ VK_FORMAT_ASTC_10x10_UNORM_BLOCK,
+ VK_FORMAT_ASTC_10x10_SRGB_BLOCK,
+ VK_FORMAT_ASTC_12x10_UNORM_BLOCK,
+ VK_FORMAT_ASTC_12x10_SRGB_BLOCK,
+ VK_FORMAT_ASTC_12x12_UNORM_BLOCK,
+ VK_FORMAT_ASTC_12x12_SRGB_BLOCK,
+ };
+
+ de::MovePtr<tcu::TestCaseGroup> imageTests (new tcu::TestCaseGroup(testCtx, "image", "Image tests"));
+ de::MovePtr<tcu::TestCaseGroup> viewTypeTests (new tcu::TestCaseGroup(testCtx, "view_type", ""));
+
+ for (int viewTypeNdx = 0; viewTypeNdx < DE_LENGTH_OF_ARRAY(imageViewTypes); viewTypeNdx++)
+ {
+ const VkImageViewType viewType = imageViewTypes[viewTypeNdx].type;
+ de::MovePtr<tcu::TestCaseGroup> viewTypeGroup (new tcu::TestCaseGroup(testCtx, imageViewTypes[viewTypeNdx].name, (std::string("Uses a ") + imageViewTypes[viewTypeNdx].name + " view").c_str()));
+ de::MovePtr<tcu::TestCaseGroup> formatTests (new tcu::TestCaseGroup(testCtx, "format", "Tests samplable formats"));
+
+ for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
+ {
+ const VkFormat format = formats[formatNdx];
+
+ if (isCompressedFormat(format) && (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_1D_ARRAY))
+ {
+ break;
+ }
+
+ de::MovePtr<tcu::TestCaseGroup> formatGroup (new tcu::TestCaseGroup(testCtx,
+ getFormatCaseName(format).c_str(),
+ (std::string("Samples a texture of format ") + getFormatName(format)).c_str()));
+
+ de::MovePtr<tcu::TestCaseGroup> sizeTests = createImageSizeTests(testCtx, viewType, format);
+
+ formatGroup->addChild(sizeTests.release());
+ formatTests->addChild(formatGroup.release());
+ }
+
+ viewTypeGroup->addChild(formatTests.release());
+ viewTypeTests->addChild(viewTypeGroup.release());
+ }
+
+ imageTests->addChild(viewTypeTests.release());
+
+ return imageTests.release();
+}
+
+} // pipeline
+} // vkt
--- /dev/null
+#ifndef _VKTPIPELINEIMAGETESTS_HPP
+#define _VKTPIPELINEIMAGETESTS_HPP
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Imagination Technologies Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by Khronos,
+ * at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Image Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktTestCase.hpp"
+
+namespace vkt
+{
+namespace pipeline
+{
+
+tcu::TestCaseGroup* createImageTests (tcu::TestContext& testCtx);
+
+} // pipeline
+} // vkt
+
+#endif // _VKTPIPELINEIMAGETESTS_HPP
--- /dev/null
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Imagination Technologies Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by Khronos,
+ * at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Utilities for images.
+ *//*--------------------------------------------------------------------*/
+
+#include "vktPipelineImageUtil.hpp"
+#include "vkImageUtil.hpp"
+#include "vkMemUtil.hpp"
+#include "vkQueryUtil.hpp"
+#include "vkRefUtil.hpp"
+#include "tcuTextureUtil.hpp"
+#include "deRandom.hpp"
+
+namespace vkt
+{
+namespace pipeline
+{
+
+using namespace vk;
+
+/*! Gets the next multiple of M */
+template<deUint32 M>
+static int getNextMultiple(deUint32 value)
+{
+ if (value % M == 0)
+ {
+ return value;
+ }
+ return value + M - (value % M);
+}
+
+static int getNextMultiple (deUint32 M, deUint32 value)
+{
+ if (value % M == 0)
+ {
+ return value;
+ }
+ return value + M - (value % M);
+}
+
+
+bool isSupportedSamplableFormat (const InstanceInterface& instanceInterface, VkPhysicalDevice device, VkFormat format)
+{
+ if (isCompressedFormat(format))
+ {
+ VkPhysicalDeviceFeatures physicalFeatures;
+ const tcu::CompressedTexFormat compressedFormat = mapVkCompressedFormat(format);
+
+ instanceInterface.getPhysicalDeviceFeatures(device, &physicalFeatures);
+
+ if (tcu::isAstcFormat(compressedFormat))
+ {
+ if (!physicalFeatures.textureCompressionASTC_LDR)
+ return false;
+ }
+ else if (tcu::isEtcFormat(compressedFormat))
+ {
+ if (!physicalFeatures.textureCompressionETC2)
+ return false;
+ }
+ else
+ {
+ DE_FATAL("Unsupported compressed format");
+ }
+ }
+
+ VkFormatProperties formatProps;
+ instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
+
+ return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) != 0u;
+}
+
+VkBorderColor getFormatBorderColor (BorderColor color, VkFormat format)
+{
+ if (!isCompressedFormat(format) && (isIntFormat(format) || isUintFormat(format)))
+ {
+ switch (color)
+ {
+ case BORDER_COLOR_OPAQUE_BLACK: return VK_BORDER_COLOR_INT_OPAQUE_BLACK;
+ case BORDER_COLOR_OPAQUE_WHITE: return VK_BORDER_COLOR_INT_OPAQUE_WHITE;
+ case BORDER_COLOR_TRANSPARENT_BLACK: return VK_BORDER_COLOR_INT_TRANSPARENT_BLACK;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ switch (color)
+ {
+ case BORDER_COLOR_OPAQUE_BLACK: return VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK;
+ case BORDER_COLOR_OPAQUE_WHITE: return VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
+ case BORDER_COLOR_TRANSPARENT_BLACK: return VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
+ default:
+ break;
+ }
+ }
+
+ DE_ASSERT(false);
+ return VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
+}
+
+de::MovePtr<tcu::TextureLevel> readColorAttachment (const vk::DeviceInterface& vk,
+ vk::VkDevice device,
+ vk::VkQueue queue,
+ deUint32 queueFamilyIndex,
+ vk::Allocator& allocator,
+ vk::VkImage image,
+ vk::VkFormat format,
+ const tcu::IVec2& renderSize)
+{
+ Move<VkBuffer> buffer;
+ de::MovePtr<Allocation> bufferAlloc;
+ Move<VkCommandPool> cmdPool;
+ Move<VkCommandBuffer> cmdBuffer;
+ Move<VkFence> fence;
+ const tcu::TextureFormat tcuFormat = mapVkFormat(format);
+ const VkDeviceSize pixelDataSize = renderSize.x() * renderSize.y() * tcuFormat.getPixelSize();
+ de::MovePtr<tcu::TextureLevel> resultLevel (new tcu::TextureLevel(tcuFormat, renderSize.x(), renderSize.y()));
+
+ // Create destination buffer
+ {
+ const VkBufferCreateInfo bufferParams =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkBufferCreateFlags flags;
+ pixelDataSize, // VkDeviceSize size;
+ VK_BUFFER_USAGE_TRANSFER_DST_BIT, // VkBufferUsageFlags usage;
+ VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
+ 0u, // deUint32 queueFamilyIndexCount;
+ DE_NULL // const deUint32* pQueueFamilyIndices;
+ };
+
+ buffer = createBuffer(vk, device, &bufferParams);
+ bufferAlloc = allocator.allocate(getBufferMemoryRequirements(vk, device, *buffer), MemoryRequirement::HostVisible);
+ VK_CHECK(vk.bindBufferMemory(device, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset()));
+ }
+
+ // Create command pool and buffer
+ {
+ const VkCommandPoolCreateInfo cmdPoolParams =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // VkCmdPoolCreateFlags flags;
+ queueFamilyIndex, // deUint32 queueFamilyIndex;
+ };
+
+ cmdPool = createCommandPool(vk, device, &cmdPoolParams);
+
+ const VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ *cmdPool, // VkCommandPool commandPool;
+ VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
+ 1u // deUint32 bufferCount;
+ };
+
+ cmdBuffer = allocateCommandBuffer(vk, device, &cmdBufferAllocateInfo);
+ }
+
+ // Create fence
+ {
+ const VkFenceCreateInfo fenceParams =
+ {
+ VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u // VkFenceCreateFlags flags;
+ };
+
+ fence = createFence(vk, device, &fenceParams);
+ }
+
+ // Barriers for copying image to buffer
+
+ const VkImageMemoryBarrier imageBarrier =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask;
+ VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout;
+ VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
+ VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
+ image, // VkImage image;
+ { // VkImageSubresourceRange subresourceRange;
+ VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
+ 0u, // deUint32 baseMipLevel;
+ 1u, // deUint32 mipLevels;
+ 0u, // deUint32 baseArraySlice;
+ 1u // deUint32 arraySize;
+ }
+ };
+
+ const VkBufferMemoryBarrier bufferBarrier =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
+ VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
+ VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
+ VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
+ *buffer, // VkBuffer buffer;
+ 0u, // VkDeviceSize offset;
+ pixelDataSize // VkDeviceSize size;
+ };
+
+ const VkCommandBufferBeginInfo cmdBufferBeginInfo =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // VkCommandBufferUsageFlags flags;
+ DE_NULL, // VkRenderPass renderPass;
+ 0u, // deUint32 subpass;
+ DE_NULL, // VkFramebuffer framebuffer;
+ false, // VkBool32 occlusionQueryEnable;
+ 0u, // VkQueryControlFlags queryFlags;
+ 0u // VkQueryPipelineStatisticFlags pipelineStatistics;
+ };
+
+ const void* const imageBarrierPtr = &imageBarrier;
+ const void* const bufferBarrierPtr = &bufferBarrier;
+
+ // Copy image to buffer
+
+ const VkBufferImageCopy copyRegion =
+ {
+ 0u, // VkDeviceSize bufferOffset;
+ (deUint32)renderSize.x(), // deUint32 bufferRowLength;
+ (deUint32)renderSize.y(), // deUint32 bufferImageHeight;
+ { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u }, // VkImageSubresourceLayers imageSubresource;
+ { 0, 0, 0 }, // VkOffset3D imageOffset;
+ { renderSize.x(), renderSize.y(), 1 } // VkExtent3D imageExtent;
+ };
+
+ VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
+ vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_FALSE, 1, &imageBarrierPtr);
+ vk.cmdCopyImageToBuffer(*cmdBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *buffer, 1, ©Region);
+ vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_FALSE, 1, &bufferBarrierPtr);
+ VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
+
+ const VkSubmitInfo submitInfo =
+ {
+ VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // deUint32 waitSemaphoreCount;
+ DE_NULL, // const VkSemaphore* pWaitSemaphores;
+ 1u, // deUint32 commandBufferCount;
+ &cmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
+ 0u, // deUint32 signalSemaphoreCount;
+ DE_NULL // const VkSemaphore* pSignalSemaphores;
+ };
+
+ VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
+ VK_CHECK(vk.waitForFences(device, 1, &fence.get(), 0, ~(0ull) /* infinity */));
+
+ // Read buffer data
+ invalidateMappedMemoryRange(vk, device, bufferAlloc->getMemory(), bufferAlloc->getOffset(), pixelDataSize);
+ tcu::copy(*resultLevel, tcu::ConstPixelBufferAccess(resultLevel->getFormat(), resultLevel->getSize(), bufferAlloc->getHostPtr()));
+
+ return resultLevel;
+}
+
+void uploadTestTexture (const DeviceInterface& vk,
+ VkDevice device,
+ VkQueue queue,
+ deUint32 queueFamilyIndex,
+ Allocator& allocator,
+ const TestTexture& srcTexture,
+ VkImage destImage)
+{
+ deUint32 bufferSize;
+ Move<VkBuffer> buffer;
+ de::MovePtr<Allocation> bufferAlloc;
+ Move<VkCommandPool> cmdPool;
+ Move<VkCommandBuffer> cmdBuffer;
+ Move<VkFence> fence;
+ std::vector<deUint32> levelDataSizes;
+
+ // Calculate buffer size
+ bufferSize = (srcTexture.isCompressed())? srcTexture.getCompressedSize(): srcTexture.getSize();
+
+ // Create source buffer
+ {
+ const VkBufferCreateInfo bufferParams =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkBufferCreateFlags flags;
+ bufferSize, // VkDeviceSize size;
+ VK_BUFFER_USAGE_TRANSFER_SRC_BIT, // VkBufferUsageFlags usage;
+ VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
+ 0u, // deUint32 queueFamilyIndexCount;
+ DE_NULL, // const deUint32* pQueueFamilyIndices;
+ };
+
+ buffer = createBuffer(vk, device, &bufferParams);
+ bufferAlloc = allocator.allocate(getBufferMemoryRequirements(vk, device, *buffer), MemoryRequirement::HostVisible);
+ VK_CHECK(vk.bindBufferMemory(device, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset()));
+ }
+
+ // Create command pool and buffer
+ {
+ const VkCommandPoolCreateInfo cmdPoolParams =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // VkCommandPoolCreateFlags flags;
+ queueFamilyIndex, // deUint32 queueFamilyIndex;
+ };
+
+ cmdPool = createCommandPool(vk, device, &cmdPoolParams);
+
+ const VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ *cmdPool, // VkCommandPool commandPool;
+ VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
+ 1u, // deUint32 bufferCount;
+ };
+
+ cmdBuffer = allocateCommandBuffer(vk, device, &cmdBufferAllocateInfo);
+ }
+
+ // Create fence
+ {
+ const VkFenceCreateInfo fenceParams =
+ {
+ VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u // VkFenceCreateFlags flags;
+ };
+
+ fence = createFence(vk, device, &fenceParams);
+ }
+
+ // Barriers for copying buffer to image
+ const VkBufferMemoryBarrier preBufferBarrier =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ VK_ACCESS_HOST_WRITE_BIT, // VkAccessFlags srcAccessMask;
+ VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
+ VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
+ VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
+ *buffer, // VkBuffer buffer;
+ 0u, // VkDeviceSize offset;
+ bufferSize // VkDeviceSize size;
+ };
+
+ const VkImageMemoryBarrier preImageBarrier =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkAccessFlags srcAccessMask;
+ 0u, // VkAccessFlags dstAccessMask;
+ VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout;
+ VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
+ VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
+ destImage, // VkImage image;
+ { // VkImageSubresourceRange subresourceRange;
+ VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspect aspect;
+ 0u, // deUint32 baseMipLevel;
+ (deUint32)srcTexture.getNumLevels(), // deUint32 mipLevels;
+ 0u, // deUint32 baseArraySlice;
+ (deUint32)srcTexture.getArraySize(), // deUint32 arraySize;
+ }
+ };
+
+ const VkImageMemoryBarrier postImageBarrier =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
+ VK_ACCESS_SHADER_READ_BIT, // VkAccessFlags dstAccessMask;
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout;
+ VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout newLayout;
+ VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
+ VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
+ destImage, // VkImage image;
+ { // VkImageSubresourceRange subresourceRange;
+ VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspect aspect;
+ 0u, // deUint32 baseMipLevel;
+ (deUint32)srcTexture.getNumLevels(), // deUint32 mipLevels;
+ 0u, // deUint32 baseArraySlice;
+ (deUint32)srcTexture.getArraySize(), // deUint32 arraySize;
+ }
+ };
+
+ const VkCommandBufferBeginInfo cmdBufferBeginInfo =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // VkCommandBufferUsageFlags flags;
+ DE_NULL, // VkRenderPass renderPass;
+ 0u, // deUint32 subpass;
+ DE_NULL, // VkFramebuffer framebuffer;
+ false, // VkBool32 occlusionQueryEnable;
+ 0u, // VkQueryControlFlags queryFlags;
+ 0u // VkQueryPipelineStatisticFlags pipelineStatistics;
+ };
+
+ const void* preCopyBarriers[2] =
+ {
+ &preBufferBarrier,
+ &preImageBarrier
+ };
+
+ const void* const postCopyBarrier = &postImageBarrier;
+ const std::vector<VkBufferImageCopy> copyRegions = srcTexture.getBufferCopyRegions();
+
+ // Write buffer data
+ srcTexture.write(reinterpret_cast<deUint8*>(bufferAlloc->getHostPtr()));
+ flushMappedMemoryRange(vk, device, bufferAlloc->getMemory(), bufferAlloc->getOffset(), bufferSize);
+
+ // Copy buffer to image
+ VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
+ vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_FALSE, 2, preCopyBarriers);
+ vk.cmdCopyBufferToImage(*cmdBuffer, *buffer, destImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, (deUint32)copyRegions.size(), copyRegions.data());
+ vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_FALSE, 1, &postCopyBarrier);
+
+ VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
+
+ const VkSubmitInfo submitInfo =
+ {
+ VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // deUint32 waitSemaphoreCount;
+ DE_NULL, // const VkSemaphore* pWaitSemaphores;
+ 1u, // deUint32 commandBufferCount;
+ &cmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
+ 0u, // deUint32 signalSemaphoreCount;
+ DE_NULL // const VkSemaphore* pSignalSemaphores;
+ };
+
+ VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
+ VK_CHECK(vk.waitForFences(device, 1, &fence.get(), true, ~(0ull) /* infinity */));
+}
+
+
+// Utilities for test textures
+
+template<typename TcuTextureType>
+void allocateLevels (TcuTextureType& texture)
+{
+ for (int levelNdx = 0; levelNdx < texture.getNumLevels(); levelNdx++)
+ texture.allocLevel(levelNdx);
+}
+
+template<typename TcuTextureType>
+std::vector<tcu::PixelBufferAccess> getLevelsVector (const TcuTextureType& texture)
+{
+ std::vector<tcu::PixelBufferAccess> levels(texture.getNumLevels());
+
+ for (int levelNdx = 0; levelNdx < texture.getNumLevels(); levelNdx++)
+ levels[levelNdx] = *reinterpret_cast<const tcu::PixelBufferAccess*>(&texture.getLevel(levelNdx));
+
+ return levels;
+}
+
+
+// TestTexture
+
+TestTexture::TestTexture (const tcu::TextureFormat& format, int width, int height, int depth)
+{
+ DE_ASSERT(width >= 1);
+ DE_ASSERT(height >= 1);
+ DE_ASSERT(depth >= 1);
+
+ DE_UNREF(format);
+ DE_UNREF(width);
+ DE_UNREF(height);
+ DE_UNREF(depth);
+}
+
+TestTexture::TestTexture (const tcu::CompressedTexFormat& format, int width, int height, int depth)
+{
+ DE_ASSERT(width >= 1);
+ DE_ASSERT(height >= 1);
+ DE_ASSERT(depth >= 1);
+
+ DE_UNREF(format);
+ DE_UNREF(width);
+ DE_UNREF(height);
+ DE_UNREF(depth);
+}
+
+TestTexture::~TestTexture (void)
+{
+ for (size_t levelNdx = 0; levelNdx < m_compressedLevels.size(); levelNdx++)
+ delete m_compressedLevels[levelNdx];
+}
+
+deUint32 TestTexture::getSize (void) const
+{
+ deUint32 textureSize = 0;
+
+ for (int levelNdx = 0; levelNdx < getNumLevels(); levelNdx++)
+ {
+ for (int layerNdx = 0; layerNdx < getArraySize(); layerNdx++)
+ {
+ const tcu::ConstPixelBufferAccess level = getLevel(levelNdx, layerNdx);
+ textureSize = getNextMultiple<4>(textureSize);
+ textureSize += level.getWidth() * level.getHeight() * level.getDepth() * level.getFormat().getPixelSize();
+ }
+ }
+
+ return textureSize;
+}
+
+deUint32 TestTexture::getCompressedSize (void) const
+{
+ if (!isCompressed())
+ throw tcu::InternalError("Texture is not compressed");
+
+ deUint32 textureSize = 0;
+
+ for (int levelNdx = 0; levelNdx < getNumLevels(); levelNdx++)
+ {
+ for (int layerNdx = 0; layerNdx < getArraySize(); layerNdx++)
+ {
+ textureSize = getNextMultiple<4>(textureSize);
+ textureSize += getCompressedLevel(levelNdx, layerNdx).getDataSize();
+ }
+ }
+
+ return textureSize;
+}
+
+tcu::CompressedTexture& TestTexture::getCompressedLevel (int level, int layer)
+{
+ DE_ASSERT(level >= 0 && level < getNumLevels());
+ DE_ASSERT(layer >= 0 && layer < getArraySize());
+
+ return *m_compressedLevels[level * getArraySize() + layer];
+}
+
+const tcu::CompressedTexture& TestTexture::getCompressedLevel (int level, int layer) const
+{
+ DE_ASSERT(level >= 0 && level < getNumLevels());
+ DE_ASSERT(layer >= 0 && layer < getArraySize());
+
+ return *m_compressedLevels[level * getArraySize() + layer];
+}
+
+std::vector<VkBufferImageCopy> TestTexture::getBufferCopyRegions (void) const
+{
+ std::vector<VkBufferImageCopy> regions;
+ deUint32 layerDataOffset = 0;
+
+ if (isCompressed())
+ {
+ for (int levelNdx = 0; levelNdx < getNumLevels(); levelNdx++)
+ {
+ for (int layerNdx = 0; layerNdx < getArraySize(); layerNdx++)
+ {
+ const tcu::CompressedTexture& level = getCompressedLevel(levelNdx, layerNdx);
+ tcu::IVec3 blockPixelSize = getBlockPixelSize(level.getFormat());
+ layerDataOffset = getNextMultiple<4>(layerDataOffset);
+
+ const VkBufferImageCopy layerRegion =
+ {
+ layerDataOffset, // VkDeviceSize bufferOffset;
+ (deUint32)getNextMultiple(blockPixelSize.x(), level.getWidth()), // deUint32 bufferRowLength;
+ (deUint32)getNextMultiple(blockPixelSize.y(), level.getHeight()), // deUint32 bufferImageHeight;
+ { // VkImageSubresourceLayers imageSubresource;
+ VK_IMAGE_ASPECT_COLOR_BIT,
+ (deUint32)levelNdx,
+ (deUint32)layerNdx,
+ 1u
+ },
+ { 0u, 0u, 0u }, // VkOffset3D imageOffset;
+ { // VkExtent3D imageExtent;
+ level.getWidth(),
+ level.getHeight(),
+ level.getDepth()
+ }
+ };
+
+ regions.push_back(layerRegion);
+ layerDataOffset += level.getDataSize();
+ }
+ }
+ }
+ else
+ {
+ for (int levelNdx = 0; levelNdx < getNumLevels(); levelNdx++)
+ {
+ for (int layerNdx = 0; layerNdx < getArraySize(); layerNdx++)
+ {
+ const tcu::ConstPixelBufferAccess level = getLevel(levelNdx, layerNdx);
+
+ layerDataOffset = getNextMultiple<4>(layerDataOffset);
+
+ const VkBufferImageCopy layerRegion =
+ {
+ layerDataOffset, // VkDeviceSize bufferOffset;
+ (deUint32)level.getWidth(), // deUint32 bufferRowLength;
+ (deUint32)level.getHeight(), // deUint32 bufferImageHeight;
+ { // VkImageSubresourceLayers imageSubresource;
+ VK_IMAGE_ASPECT_COLOR_BIT,
+ (deUint32)levelNdx,
+ (deUint32)layerNdx,
+ 1u
+ },
+ { 0u, 0u, 0u }, // VkOffset3D imageOffset;
+ { // VkExtent3D imageExtent;
+ level.getWidth(),
+ level.getHeight(),
+ level.getDepth()
+ }
+ };
+
+ regions.push_back(layerRegion);
+ layerDataOffset += level.getWidth() * level.getHeight() * level.getDepth() * level.getFormat().getPixelSize();
+ }
+ }
+ }
+
+ return regions;
+}
+
+void TestTexture::write (deUint8* destPtr) const
+{
+ deUint32 levelOffset = 0;
+
+ if (isCompressed())
+ {
+ for (int levelNdx = 0; levelNdx < getNumLevels(); levelNdx++)
+ {
+ for (int layerNdx = 0; layerNdx < getArraySize(); layerNdx++)
+ {
+ levelOffset = getNextMultiple<4>(levelOffset);
+
+ const tcu::CompressedTexture& compressedTex = getCompressedLevel(levelNdx, layerNdx);
+
+ deMemcpy(destPtr + levelOffset, compressedTex.getData(), compressedTex.getDataSize());
+ levelOffset += compressedTex.getDataSize();
+ }
+ }
+ }
+ else
+ {
+ for (int levelNdx = 0; levelNdx < getNumLevels(); levelNdx++)
+ {
+ for (int layerNdx = 0; layerNdx < getArraySize(); layerNdx++)
+ {
+ levelOffset = getNextMultiple<4>(levelOffset);
+
+ const tcu::ConstPixelBufferAccess srcAccess = getLevel(levelNdx, layerNdx);
+ const tcu::PixelBufferAccess destAccess (srcAccess.getFormat(), srcAccess.getSize(), srcAccess.getPitch(), destPtr + levelOffset);
+
+ tcu::copy(destAccess, srcAccess);
+ levelOffset += srcAccess.getWidth() * srcAccess.getHeight() * srcAccess.getDepth() * srcAccess.getFormat().getPixelSize();
+ }
+ }
+ }
+}
+
+void TestTexture::populateLevels (const std::vector<tcu::PixelBufferAccess>& levels)
+{
+ for (size_t levelNdx = 0; levelNdx < levels.size(); levelNdx++)
+ TestTexture::fillWithGradient(levels[levelNdx]);
+}
+
+void TestTexture::populateCompressedLevels (const tcu::CompressedTexFormat& format, const std::vector<tcu::PixelBufferAccess>& decompressedLevels)
+{
+ // Generate random compressed data and update decompressed data
+
+ de::Random random(123);
+
+ for (size_t levelNdx = 0; levelNdx < decompressedLevels.size(); levelNdx++)
+ {
+ const tcu::PixelBufferAccess level = decompressedLevels[levelNdx];
+ tcu::CompressedTexture* compressedLevel = new tcu::CompressedTexture(format, level.getWidth(), level.getHeight(), level.getDepth());
+ deUint8* const compressedData = (deUint8*)compressedLevel->getData();
+
+ // Generate random compressed data
+ for (int byteNdx = 0; byteNdx < compressedLevel->getDataSize(); byteNdx++)
+ compressedData[byteNdx] = 0xFF & random.getUint32();
+
+ m_compressedLevels.push_back(compressedLevel);
+
+ // Store decompressed data
+ compressedLevel->decompress(level);
+ }
+}
+
+void TestTexture::fillWithGradient (const tcu::PixelBufferAccess& levelAccess)
+{
+ const tcu::TextureFormatInfo formatInfo = tcu::getTextureFormatInfo(levelAccess.getFormat());
+ tcu::fillWithComponentGradients(levelAccess, formatInfo.valueMin, formatInfo.valueMax);
+}
+
+// TestTexture1D
+
+TestTexture1D::TestTexture1D (const tcu::TextureFormat& format, int width)
+ : TestTexture (format, width, 1, 1)
+ , m_texture (format, width)
+{
+ allocateLevels(m_texture);
+ TestTexture::populateLevels(getLevelsVector(m_texture));
+}
+
+TestTexture1D::TestTexture1D (const tcu::CompressedTexFormat& format, int width)
+ : TestTexture (format, width, 1, 1)
+ , m_texture (tcu::getUncompressedFormat(format), width)
+{
+ allocateLevels(m_texture);
+ TestTexture::populateCompressedLevels(format, getLevelsVector(m_texture));
+}
+
+TestTexture1D::~TestTexture1D (void)
+{
+}
+
+int TestTexture1D::getNumLevels (void) const
+{
+ return m_texture.getNumLevels();
+}
+
+tcu::PixelBufferAccess TestTexture1D::getLevel (int level, int layer)
+{
+ DE_ASSERT(layer == 0);
+ return m_texture.getLevel(level);
+}
+
+const tcu::ConstPixelBufferAccess TestTexture1D::getLevel (int level, int layer) const
+{
+ DE_ASSERT(layer == 0);
+ return m_texture.getLevel(level);
+}
+
+const tcu::Texture1D& TestTexture1D::getTexture (void) const
+{
+ return m_texture;
+}
+
+
+// TestTexture1DArray
+
+TestTexture1DArray::TestTexture1DArray (const tcu::TextureFormat& format, int width, int arraySize)
+ : TestTexture (format, width, 1, arraySize)
+ , m_texture (format, width, arraySize)
+{
+ allocateLevels(m_texture);
+ TestTexture::populateLevels(getLevelsVector(m_texture));
+}
+
+TestTexture1DArray::TestTexture1DArray (const tcu::CompressedTexFormat& format, int width, int arraySize)
+ : TestTexture (format, width, 1, arraySize)
+ , m_texture (tcu::getUncompressedFormat(format), width, arraySize)
+{
+ allocateLevels(m_texture);
+
+ std::vector<tcu::PixelBufferAccess> layers;
+ for (int levelNdx = 0; levelNdx < m_texture.getNumLevels(); levelNdx++)
+ for (int layerNdx = 0; layerNdx < m_texture.getNumLayers(); layerNdx++)
+ layers.push_back(getLevel(levelNdx, layerNdx));
+
+ TestTexture::populateCompressedLevels(format, layers);
+}
+
+TestTexture1DArray::~TestTexture1DArray (void)
+{
+}
+
+int TestTexture1DArray::getNumLevels (void) const
+{
+ return m_texture.getNumLevels();
+}
+
+tcu::PixelBufferAccess TestTexture1DArray::getLevel (int level, int layer)
+{
+ const tcu::PixelBufferAccess levelLayers = m_texture.getLevel(level);
+ const deUint32 layerSize = levelLayers.getWidth() * levelLayers.getFormat().getPixelSize();
+ const deUint32 layerOffset = layerSize * layer;
+
+ return tcu::PixelBufferAccess(levelLayers.getFormat(), levelLayers.getWidth(), 1, 1, (deUint8*)levelLayers.getDataPtr() + layerOffset);
+}
+
+const tcu::ConstPixelBufferAccess TestTexture1DArray::getLevel (int level, int layer) const
+{
+ const tcu::ConstPixelBufferAccess levelLayers = m_texture.getLevel(level);
+ const deUint32 layerSize = levelLayers.getWidth() * levelLayers.getFormat().getPixelSize();
+ const deUint32 layerOffset = layerSize * layer;
+
+ return tcu::ConstPixelBufferAccess(levelLayers.getFormat(), levelLayers.getWidth(), 1, 1, (deUint8*)levelLayers.getDataPtr() + layerOffset);
+}
+
+const tcu::Texture1DArray& TestTexture1DArray::getTexture (void) const
+{
+ return m_texture;
+}
+
+int TestTexture1DArray::getArraySize (void) const
+{
+ return m_texture.getNumLayers();
+}
+
+
+// TestTexture2D
+
+TestTexture2D::TestTexture2D (const tcu::TextureFormat& format, int width, int height)
+ : TestTexture (format, width, height, 1)
+ , m_texture (format, width, height)
+{
+ allocateLevels(m_texture);
+ TestTexture::populateLevels(getLevelsVector(m_texture));
+}
+
+TestTexture2D::TestTexture2D (const tcu::CompressedTexFormat& format, int width, int height)
+ : TestTexture (format, width, height, 1)
+ , m_texture (tcu::getUncompressedFormat(format), width, height)
+{
+ allocateLevels(m_texture);
+ TestTexture::populateCompressedLevels(format, getLevelsVector(m_texture));
+}
+
+TestTexture2D::~TestTexture2D (void)
+{
+}
+
+int TestTexture2D::getNumLevels (void) const
+{
+ return m_texture.getNumLevels();
+}
+
+tcu::PixelBufferAccess TestTexture2D::getLevel (int level, int layer)
+{
+ DE_ASSERT(layer == 0);
+ return m_texture.getLevel(level);
+}
+
+const tcu::ConstPixelBufferAccess TestTexture2D::getLevel (int level, int layer) const
+{
+ DE_ASSERT(layer == 0);
+ return m_texture.getLevel(level);
+}
+
+const tcu::Texture2D& TestTexture2D::getTexture (void) const
+{
+ return m_texture;
+}
+
+
+// TestTexture2DArray
+
+TestTexture2DArray::TestTexture2DArray (const tcu::TextureFormat& format, int width, int height, int arraySize)
+ : TestTexture (format, width, height, arraySize)
+ , m_texture (format, width, height, arraySize)
+{
+ allocateLevels(m_texture);
+ TestTexture::populateLevels(getLevelsVector(m_texture));
+}
+
+TestTexture2DArray::TestTexture2DArray (const tcu::CompressedTexFormat& format, int width, int height, int arraySize)
+ : TestTexture (format, width, height, arraySize)
+ , m_texture (tcu::getUncompressedFormat(format), width, height, arraySize)
+{
+ allocateLevels(m_texture);
+
+ std::vector<tcu::PixelBufferAccess> layers;
+ for (int levelNdx = 0; levelNdx < m_texture.getNumLevels(); levelNdx++)
+ for (int layerNdx = 0; layerNdx < m_texture.getNumLayers(); layerNdx++)
+ layers.push_back(getLevel(levelNdx, layerNdx));
+
+ TestTexture::populateCompressedLevels(format, layers);
+}
+
+TestTexture2DArray::~TestTexture2DArray (void)
+{
+}
+
+int TestTexture2DArray::getNumLevels (void) const
+{
+ return m_texture.getNumLevels();
+}
+
+tcu::PixelBufferAccess TestTexture2DArray::getLevel (int level, int layer)
+{
+ const tcu::PixelBufferAccess levelLayers = m_texture.getLevel(level);
+ const deUint32 layerSize = levelLayers.getWidth() * levelLayers.getHeight() * levelLayers.getFormat().getPixelSize();
+ const deUint32 layerOffset = layerSize * layer;
+
+ return tcu::PixelBufferAccess(levelLayers.getFormat(), levelLayers.getWidth(), levelLayers.getHeight(), 1, (deUint8*)levelLayers.getDataPtr() + layerOffset);
+}
+
+const tcu::ConstPixelBufferAccess TestTexture2DArray::getLevel (int level, int layer) const
+{
+ const tcu::ConstPixelBufferAccess levelLayers = m_texture.getLevel(level);
+ const deUint32 layerSize = levelLayers.getWidth() * levelLayers.getHeight() * levelLayers.getFormat().getPixelSize();
+ const deUint32 layerOffset = layerSize * layer;
+
+ return tcu::ConstPixelBufferAccess(levelLayers.getFormat(), levelLayers.getWidth(), levelLayers.getHeight(), 1, (deUint8*)levelLayers.getDataPtr() + layerOffset);
+}
+
+const tcu::Texture2DArray& TestTexture2DArray::getTexture (void) const
+{
+ return m_texture;
+}
+
+int TestTexture2DArray::getArraySize (void) const
+{
+ return m_texture.getNumLayers();
+}
+
+
+// TestTexture3D
+
+TestTexture3D::TestTexture3D (const tcu::TextureFormat& format, int width, int height, int depth)
+ : TestTexture (format, width, height, depth)
+ , m_texture (format, width, height, depth)
+{
+ allocateLevels(m_texture);
+ TestTexture::populateLevels(getLevelsVector(m_texture));
+}
+
+TestTexture3D::TestTexture3D (const tcu::CompressedTexFormat& format, int width, int height, int depth)
+ : TestTexture (format, width, height, depth)
+ , m_texture (tcu::getUncompressedFormat(format), width, height, depth)
+{
+ allocateLevels(m_texture);
+ TestTexture::populateCompressedLevels(format, getLevelsVector(m_texture));
+}
+
+TestTexture3D::~TestTexture3D (void)
+{
+}
+
+int TestTexture3D::getNumLevels (void) const
+{
+ return m_texture.getNumLevels();
+}
+
+tcu::PixelBufferAccess TestTexture3D::getLevel (int level, int layer)
+{
+ DE_ASSERT(layer == 0);
+ return m_texture.getLevel(level);
+}
+
+const tcu::ConstPixelBufferAccess TestTexture3D::getLevel (int level, int layer) const
+{
+ DE_ASSERT(layer == 0);
+ return m_texture.getLevel(level);
+}
+
+const tcu::Texture3D& TestTexture3D::getTexture (void) const
+{
+ return m_texture;
+}
+
+
+// TestTextureCube
+
+const static tcu::CubeFace tcuFaceMapping[tcu::CUBEFACE_LAST] =
+{
+ tcu::CUBEFACE_POSITIVE_X,
+ tcu::CUBEFACE_NEGATIVE_X,
+ tcu::CUBEFACE_POSITIVE_Y,
+ tcu::CUBEFACE_NEGATIVE_Y,
+ tcu::CUBEFACE_POSITIVE_Z,
+ tcu::CUBEFACE_NEGATIVE_Z
+};
+
+TestTextureCube::TestTextureCube (const tcu::TextureFormat& format, int size)
+ : TestTexture (format, size, size, 1)
+ , m_texture (format, size)
+{
+ for (int levelNdx = 0; levelNdx < getNumLevels(); levelNdx++)
+ {
+ for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
+ {
+ m_texture.allocLevel(tcuFaceMapping[faceNdx], levelNdx);
+ TestTexture::fillWithGradient(m_texture.getLevelFace(levelNdx, tcuFaceMapping[faceNdx]));
+ }
+ }
+}
+
+TestTextureCube::TestTextureCube (const tcu::CompressedTexFormat& format, int size)
+ : TestTexture (format, size, size, 1)
+ , m_texture (tcu::getUncompressedFormat(format), size)
+{
+ std::vector<tcu::PixelBufferAccess> levels(m_texture.getNumLevels() * tcu::CUBEFACE_LAST);
+
+ for (int levelNdx = 0; levelNdx < getNumLevels(); levelNdx++)
+ {
+ for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
+ {
+ m_texture.allocLevel(tcuFaceMapping[faceNdx], levelNdx);
+ levels[levelNdx * tcu::CUBEFACE_LAST + faceNdx] = m_texture.getLevelFace(levelNdx, tcuFaceMapping[faceNdx]);
+ }
+ }
+
+ TestTexture::populateCompressedLevels(format, levels);
+}
+
+TestTextureCube::~TestTextureCube (void)
+{
+}
+
+int TestTextureCube::getNumLevels (void) const
+{
+ return m_texture.getNumLevels();
+}
+
+tcu::PixelBufferAccess TestTextureCube::getLevel (int level, int face)
+{
+ return m_texture.getLevelFace(level, (tcu::CubeFace)face);
+}
+
+const tcu::ConstPixelBufferAccess TestTextureCube::getLevel (int level, int face) const
+{
+ return m_texture.getLevelFace(level, (tcu::CubeFace)face);
+}
+
+int TestTextureCube::getArraySize (void) const
+{
+ return (int)tcu::CUBEFACE_LAST;
+}
+
+const tcu::TextureCube& TestTextureCube::getTexture (void) const
+{
+ return m_texture;
+}
+
+// TestTextureCubeArray
+
+TestTextureCubeArray::TestTextureCubeArray (const tcu::TextureFormat& format, int size, int arraySize)
+ : TestTexture (format, size, size, arraySize)
+ , m_texture (format, size, arraySize)
+{
+ allocateLevels(m_texture);
+ TestTexture::populateLevels(getLevelsVector(m_texture));
+}
+
+TestTextureCubeArray::TestTextureCubeArray (const tcu::CompressedTexFormat& format, int size, int arraySize)
+ : TestTexture (format, size, size, arraySize)
+ , m_texture (tcu::getUncompressedFormat(format), size, arraySize)
+{
+ DE_ASSERT(arraySize % 6 == 0);
+
+ allocateLevels(m_texture);
+
+ std::vector<tcu::PixelBufferAccess> layers;
+ for (int levelNdx = 0; levelNdx < m_texture.getNumLevels(); levelNdx++)
+ for (int layerNdx = 0; layerNdx < m_texture.getDepth(); layerNdx++)
+ layers.push_back(getLevel(levelNdx, layerNdx));
+
+ TestTexture::populateCompressedLevels(format, layers);
+}
+
+TestTextureCubeArray::~TestTextureCubeArray (void)
+{
+}
+
+int TestTextureCubeArray::getNumLevels (void) const
+{
+ return m_texture.getNumLevels();
+}
+
+tcu::PixelBufferAccess TestTextureCubeArray::getLevel (int level, int layer)
+{
+ const tcu::PixelBufferAccess levelLayers = m_texture.getLevel(level);
+ const deUint32 layerSize = levelLayers.getWidth() * levelLayers.getHeight() * levelLayers.getFormat().getPixelSize();
+ const deUint32 layerOffset = layerSize * layer;
+
+ return tcu::PixelBufferAccess(levelLayers.getFormat(), levelLayers.getWidth(), levelLayers.getHeight(), 1, (deUint8*)levelLayers.getDataPtr() + layerOffset);
+}
+
+const tcu::ConstPixelBufferAccess TestTextureCubeArray::getLevel (int level, int layer) const
+{
+ const tcu::ConstPixelBufferAccess levelLayers = m_texture.getLevel(level);
+ const deUint32 layerSize = levelLayers.getWidth() * levelLayers.getHeight() * levelLayers.getFormat().getPixelSize();
+ const deUint32 layerOffset = layerSize * layer;
+
+ return tcu::ConstPixelBufferAccess(levelLayers.getFormat(), levelLayers.getWidth(), levelLayers.getHeight(), 1, (deUint8*)levelLayers.getDataPtr() + layerOffset);
+}
+
+int TestTextureCubeArray::getArraySize (void) const
+{
+ return m_texture.getDepth();
+}
+
+const tcu::TextureCubeArray& TestTextureCubeArray::getTexture (void) const
+{
+ return m_texture;
+}
+
+} // pipeline
+} // vkt
--- /dev/null
+#ifndef _VKTPIPELINEIMAGEUTIL_HPP
+#define _VKTPIPELINEIMAGEUTIL_HPP
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Imagination Technologies Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by Khronos,
+ * at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Utilities for images.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "vkDefs.hpp"
+#include "vkDefs.hpp"
+#include "vkPlatform.hpp"
+#include "vkMemUtil.hpp"
+#include "vkRef.hpp"
+#include "tcuTexture.hpp"
+#include "tcuCompressedTexture.hpp"
+
+namespace vkt
+{
+namespace pipeline
+{
+
+class TestTexture;
+
+enum BorderColor
+{
+ BORDER_COLOR_OPAQUE_BLACK,
+ BORDER_COLOR_OPAQUE_WHITE,
+ BORDER_COLOR_TRANSPARENT_BLACK,
+
+ BORDER_COLOR_COUNT
+};
+
+bool isSupportedSamplableFormat (const vk::InstanceInterface& instanceInterface,
+ vk::VkPhysicalDevice device,
+ vk::VkFormat format);
+
+vk::VkBorderColor getFormatBorderColor (BorderColor color, vk::VkFormat format);
+
+/*--------------------------------------------------------------------*//*!
+ * Gets a tcu::TextureLevel initialized with data from a VK color
+ * attachment.
+ *
+ * The VkImage must be non-multisampled and able to be used as a source
+ * operand for transfer operations.
+ *//*--------------------------------------------------------------------*/
+de::MovePtr<tcu::TextureLevel> readColorAttachment (const vk::DeviceInterface& vk,
+ vk::VkDevice device,
+ vk::VkQueue queue,
+ deUint32 queueFamilyIndex,
+ vk::Allocator& allocator,
+ vk::VkImage image,
+ vk::VkFormat format,
+ const tcu::IVec2& renderSize);
+
+/*--------------------------------------------------------------------*//*!
+ * Uploads data from a test texture to a destination VK image.
+ *
+ * The VkImage must be non-multisampled and able to be used as a
+ * destination operand for transfer operations.
+ *//*--------------------------------------------------------------------*/
+void uploadTestTexture (const vk::DeviceInterface& vk,
+ vk::VkDevice device,
+ vk::VkQueue queue,
+ deUint32 queueFamilyIndex,
+ vk::Allocator& allocator,
+ const TestTexture& testTexture,
+ vk::VkImage destImage);
+
+class TestTexture
+{
+public:
+ TestTexture (const tcu::TextureFormat& format, int width, int height, int depth);
+ TestTexture (const tcu::CompressedTexFormat& format, int width, int height, int depth);
+ virtual ~TestTexture (void);
+
+ virtual int getNumLevels (void) const = 0;
+ virtual deUint32 getSize (void) const;
+ virtual int getArraySize (void) const { return 1; }
+
+ virtual bool isCompressed (void) const { return !m_compressedLevels.empty(); }
+ virtual deUint32 getCompressedSize (void) const;
+
+ virtual tcu::PixelBufferAccess getLevel (int level, int layer) = 0;
+ virtual const tcu::ConstPixelBufferAccess getLevel (int level, int layer) const = 0;
+
+ virtual tcu::CompressedTexture& getCompressedLevel (int level, int layer);
+ virtual const tcu::CompressedTexture& getCompressedLevel (int level, int layer) const;
+
+ virtual std::vector<vk::VkBufferImageCopy> getBufferCopyRegions (void) const;
+ virtual void write (deUint8* destPtr) const;
+
+protected:
+ void populateLevels (const std::vector<tcu::PixelBufferAccess>& levels);
+ void populateCompressedLevels (const tcu::CompressedTexFormat& format, const std::vector<tcu::PixelBufferAccess>& decompressedLevels);
+
+ static void fillWithGradient (const tcu::PixelBufferAccess& levelAccess);
+
+protected:
+ std::vector<tcu::CompressedTexture*> m_compressedLevels;
+};
+
+class TestTexture1D : public TestTexture
+{
+private:
+ tcu::Texture1D m_texture;
+
+public:
+ TestTexture1D (const tcu::TextureFormat& format, int width);
+ TestTexture1D (const tcu::CompressedTexFormat& format, int width);
+ virtual ~TestTexture1D (void);
+
+ virtual int getNumLevels (void) const;
+ virtual tcu::PixelBufferAccess getLevel (int level, int layer);
+ virtual const tcu::ConstPixelBufferAccess getLevel (int level, int layer) const;
+ virtual const tcu::Texture1D& getTexture (void) const;
+};
+
+class TestTexture1DArray : public TestTexture
+{
+private:
+ tcu::Texture1DArray m_texture;
+
+public:
+ TestTexture1DArray (const tcu::TextureFormat& format, int width, int arraySize);
+ TestTexture1DArray (const tcu::CompressedTexFormat& format, int width, int arraySize);
+ virtual ~TestTexture1DArray (void);
+
+ virtual int getNumLevels (void) const;
+ virtual tcu::PixelBufferAccess getLevel (int level, int layer);
+ virtual const tcu::ConstPixelBufferAccess getLevel (int level, int layer) const;
+ virtual const tcu::Texture1DArray& getTexture (void) const;
+ virtual int getArraySize (void) const;
+};
+
+class TestTexture2D : public TestTexture
+{
+private:
+ tcu::Texture2D m_texture;
+
+public:
+ TestTexture2D (const tcu::TextureFormat& format, int width, int height);
+ TestTexture2D (const tcu::CompressedTexFormat& format, int width, int height);
+ virtual ~TestTexture2D (void);
+
+ virtual int getNumLevels (void) const;
+ virtual tcu::PixelBufferAccess getLevel (int level, int layer);
+ virtual const tcu::ConstPixelBufferAccess getLevel (int level, int layer) const;
+ virtual const tcu::Texture2D& getTexture (void) const;
+};
+
+class TestTexture2DArray : public TestTexture
+{
+private:
+ tcu::Texture2DArray m_texture;
+
+public:
+ TestTexture2DArray (const tcu::TextureFormat& format, int width, int height, int arraySize);
+ TestTexture2DArray (const tcu::CompressedTexFormat& format, int width, int height, int arraySize);
+ virtual ~TestTexture2DArray (void);
+
+ virtual int getNumLevels (void) const;
+ virtual tcu::PixelBufferAccess getLevel (int level, int layer);
+ virtual const tcu::ConstPixelBufferAccess getLevel (int level, int layer) const;
+ virtual const tcu::Texture2DArray& getTexture (void) const;
+ virtual int getArraySize (void) const;
+};
+
+class TestTexture3D : public TestTexture
+{
+private:
+ tcu::Texture3D m_texture;
+
+public:
+ TestTexture3D (const tcu::TextureFormat& format, int width, int height, int depth);
+ TestTexture3D (const tcu::CompressedTexFormat& format, int width, int height, int depth);
+ virtual ~TestTexture3D (void);
+
+ virtual int getNumLevels (void) const;
+ virtual tcu::PixelBufferAccess getLevel (int level, int layer);
+ virtual const tcu::ConstPixelBufferAccess getLevel (int level, int layer) const;
+ virtual const tcu::Texture3D& getTexture (void) const;
+};
+
+class TestTextureCube : public TestTexture
+{
+private:
+ tcu::TextureCube m_texture;
+
+public:
+ TestTextureCube (const tcu::TextureFormat& format, int size);
+ TestTextureCube (const tcu::CompressedTexFormat& format, int size);
+ virtual ~TestTextureCube (void);
+
+ virtual int getNumLevels (void) const;
+ virtual tcu::PixelBufferAccess getLevel (int level, int layer);
+ virtual const tcu::ConstPixelBufferAccess getLevel (int level, int layer) const;
+ virtual int getArraySize (void) const;
+ virtual const tcu::TextureCube& getTexture (void) const;
+};
+
+class TestTextureCubeArray: public TestTexture
+{
+private:
+ tcu::TextureCubeArray m_texture;
+
+public:
+ TestTextureCubeArray (const tcu::TextureFormat& format, int size, int arraySize);
+ TestTextureCubeArray (const tcu::CompressedTexFormat& format, int size, int arraySize);
+ virtual ~TestTextureCubeArray (void);
+
+ virtual int getNumLevels (void) const;
+ virtual tcu::PixelBufferAccess getLevel (int level, int layer);
+ virtual const tcu::ConstPixelBufferAccess getLevel (int level, int layer) const;
+ virtual int getArraySize (void) const;
+ virtual const tcu::TextureCubeArray& getTexture (void) const;
+};
+
+} // pipeline
+} // vkt
+
+#endif // _VKTPIPELINEIMAGEUTIL_HPP
--- /dev/null
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Imagination Technologies Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by Khronos,
+ * at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Image View Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktPipelineImageViewTests.hpp"
+#include "vktPipelineImageSamplingInstance.hpp"
+#include "vktPipelineImageUtil.hpp"
+#include "vktPipelineVertexUtil.hpp"
+#include "vktTestCase.hpp"
+#include "vkImageUtil.hpp"
+#include "vkPrograms.hpp"
+#include "tcuPlatform.hpp"
+#include "tcuTextureUtil.hpp"
+#include "deStringUtil.hpp"
+#include "deMemory.h"
+
+#include <sstream>
+#include <vector>
+
+namespace vkt
+{
+namespace pipeline
+{
+
+using namespace vk;
+using de::MovePtr;
+
+namespace
+{
+
+
+class ImageViewTest : public vkt::TestCase
+{
+public:
+ ImageViewTest (tcu::TestContext& testContext,
+ const char* name,
+ const char* description,
+ VkImageViewType imageViewType,
+ VkFormat imageFormat,
+ float samplerLod,
+ const VkComponentMapping& componentMapping,
+ const VkImageSubresourceRange& subresourceRange);
+ virtual ~ImageViewTest (void) {}
+
+ virtual void initPrograms (SourceCollections& sourceCollections) const;
+ virtual TestInstance* createInstance (Context& context) const;
+ static std::string getGlslSamplerType (const tcu::TextureFormat& format, VkImageViewType type);
+ static tcu::IVec2 getRenderSize (VkImageViewType viewType);
+ static tcu::IVec3 getImageSize (VkImageViewType viewType);
+ static int getArraySize (VkImageViewType viewType);
+ static int getNumLevels (VkImageViewType viewType);
+private:
+ VkImageViewType m_imageViewType;
+ VkFormat m_imageFormat;
+ float m_samplerLod;
+ VkComponentMapping m_componentMapping;
+ VkImageSubresourceRange m_subresourceRange;
+};
+
+ImageViewTest::ImageViewTest (tcu::TestContext& testContext,
+ const char* name,
+ const char* description,
+ VkImageViewType imageViewType,
+ VkFormat imageFormat,
+ float samplerLod,
+ const VkComponentMapping& componentMapping,
+ const VkImageSubresourceRange& subresourceRange)
+
+ : vkt::TestCase (testContext, name, description)
+ , m_imageViewType (imageViewType)
+ , m_imageFormat (imageFormat)
+ , m_samplerLod (samplerLod)
+ , m_componentMapping (componentMapping)
+ , m_subresourceRange (subresourceRange)
+{
+}
+
+void ImageViewTest::initPrograms (SourceCollections& sourceCollections) const
+{
+ std::ostringstream vertexSrc;
+ std::ostringstream fragmentSrc;
+ const char* texCoordSwizzle = DE_NULL;
+ const tcu::TextureFormat format = (isCompressedFormat(m_imageFormat)) ? tcu::getUncompressedFormat(mapVkCompressedFormat(m_imageFormat))
+ : mapVkFormat(m_imageFormat);
+ const tcu::TextureFormatInfo formatInfo = tcu::getTextureFormatInfo(format);
+
+ switch (m_imageViewType)
+ {
+ case VK_IMAGE_VIEW_TYPE_1D:
+ texCoordSwizzle = "x";
+ break;
+ case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
+ case VK_IMAGE_VIEW_TYPE_2D:
+ texCoordSwizzle = "xy";
+ break;
+ case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
+ case VK_IMAGE_VIEW_TYPE_3D:
+ case VK_IMAGE_VIEW_TYPE_CUBE:
+ texCoordSwizzle = "xyz";
+ break;
+ case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
+ texCoordSwizzle = "xyzw";
+ break;
+ default:
+ DE_ASSERT(false);
+ break;
+ }
+
+ vertexSrc << "#version 440\n"
+ << "layout(location = 0) in vec4 position;\n"
+ << "layout(location = 1) in vec4 texCoords;\n"
+ << "layout(location = 0) out highp vec4 vtxTexCoords;\n"
+ << "out gl_PerVertex {\n"
+ << " vec4 gl_Position;\n"
+ << "};\n"
+ << "void main (void)\n"
+ << "{\n"
+ << " gl_Position = position;\n"
+ << " vtxTexCoords = texCoords;\n"
+ << "}\n";
+
+ fragmentSrc << "#version 440\n"
+ << "layout(set = 0, binding = 0) uniform highp " << getGlslSamplerType(format, m_imageViewType) << " texSampler;\n"
+ << "layout(location = 0) in highp vec4 vtxTexCoords;\n"
+ << "layout(location = 0) out highp vec4 fragColor;\n"
+ << "void main (void)\n"
+ << "{\n"
+ << " fragColor = ";
+
+ if (m_samplerLod > 0.0f)
+ fragmentSrc << "textureLod(texSampler, vtxTexCoords." << texCoordSwizzle << ", " << std::fixed << m_samplerLod << ")";
+ else
+ fragmentSrc << "texture(texSampler, vtxTexCoords." << texCoordSwizzle << ")" << std::fixed;
+
+ fragmentSrc << " * vec4" << std::scientific << formatInfo.lookupScale << " + vec4" << formatInfo.lookupBias << ";\n"
+ << "}\n";
+
+ sourceCollections.glslSources.add("tex_vert") << glu::VertexSource(vertexSrc.str());
+ sourceCollections.glslSources.add("tex_frag") << glu::FragmentSource(fragmentSrc.str());
+}
+
+TestInstance* ImageViewTest::createInstance (Context& context) const
+{
+ tcu::IVec2 renderSize = getRenderSize(m_imageViewType);
+ const tcu::IVec3 imageSize = getImageSize(m_imageViewType);
+ const int arraySize = getArraySize(m_imageViewType);
+ const std::vector<Vertex4Tex4> vertices = createTestQuadMosaic(m_imageViewType);
+
+ const VkSamplerCreateInfo samplerParams =
+ {
+ VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkSamplerCreateFlags flags;
+ VK_FILTER_NEAREST, // VkFilter magFilter;
+ VK_FILTER_NEAREST, // VkFilter minFilter;
+ VK_SAMPLER_MIPMAP_MODE_NEAREST, // VkSamplerMipmapMode mipmapMode;
+ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeU;
+ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeV;
+ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeW;
+ 0.0f, // float mipLodBias;
+ 1.0f, // float maxAnisotropy;
+ false, // VkBool32 compareEnable;
+ VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
+ 0.0f, // float minLod;
+ (float)(m_subresourceRange.levelCount - 1), // float maxLod;
+ getFormatBorderColor(BORDER_COLOR_TRANSPARENT_BLACK, m_imageFormat), // VkBorderColor borderColor;
+ false // VkBool32 unnormalizedCoordinates;
+ };
+
+ return new ImageSamplingInstance(context, renderSize, m_imageViewType, m_imageFormat, imageSize, arraySize, m_componentMapping, m_subresourceRange, samplerParams, m_samplerLod, vertices);
+}
+
+std::string ImageViewTest::getGlslSamplerType (const tcu::TextureFormat& format, VkImageViewType type)
+{
+ std::ostringstream samplerType;
+
+ if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
+ samplerType << "u";
+ else if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
+ samplerType << "i";
+
+ switch (type)
+ {
+ case VK_IMAGE_VIEW_TYPE_1D:
+ samplerType << "sampler1D";
+ break;
+
+ case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
+ samplerType << "sampler1DArray";
+ break;
+
+ case VK_IMAGE_VIEW_TYPE_2D:
+ samplerType << "sampler2D";
+ break;
+
+ case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
+ samplerType << "sampler2DArray";
+ break;
+
+ case VK_IMAGE_VIEW_TYPE_3D:
+ samplerType << "sampler3D";
+ break;
+
+ case VK_IMAGE_VIEW_TYPE_CUBE:
+ samplerType << "samplerCube";
+ break;
+
+ case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
+ samplerType << "samplerCubeArray";
+ break;
+
+ default:
+ DE_FATAL("Unknown image view type");
+ break;
+ }
+
+ return samplerType.str();
+}
+
+tcu::IVec2 ImageViewTest::getRenderSize (VkImageViewType viewType)
+{
+ if (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_2D)
+ return tcu::IVec2(16, 16);
+ else
+ return tcu::IVec2(16 * 3, 16 * 2);
+}
+
+tcu::IVec3 ImageViewTest::getImageSize (VkImageViewType viewType)
+{
+ switch (viewType)
+ {
+ case VK_IMAGE_VIEW_TYPE_1D:
+ case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
+ return tcu::IVec3(16, 1, 1);
+
+ case VK_IMAGE_VIEW_TYPE_3D:
+ return tcu::IVec3(16);
+
+ default:
+ break;
+ }
+
+ return tcu::IVec3(16, 16, 1);
+}
+
+int ImageViewTest::getArraySize (VkImageViewType viewType)
+{
+ switch (viewType)
+ {
+ case VK_IMAGE_VIEW_TYPE_3D:
+ return 1;
+
+ case VK_IMAGE_VIEW_TYPE_CUBE:
+ case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
+ return 18;
+
+ default:
+ break;
+ }
+
+ return 6;
+}
+
+int ImageViewTest::getNumLevels (VkImageViewType viewType)
+{
+ const tcu::IVec3 imageSize = getImageSize(viewType);
+
+ return deLog2Floor32(deMax32(imageSize.x(), deMax32(imageSize.y(), imageSize.z()))) + 1;
+}
+
+static std::string getFormatCaseName (const VkFormat format)
+{
+ const std::string fullName = getFormatName(format);
+
+ DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_"));
+
+ return de::toLower(fullName.substr(10));
+}
+
+static de::MovePtr<tcu::TestCaseGroup> createSubresourceRangeTests(tcu::TestContext& testCtx, VkImageViewType viewType, VkFormat imageFormat)
+{
+ struct TestCaseConfig
+ {
+ const char* name;
+ float samplerLod;
+ VkImageSubresourceRange subresourceRange;
+ };
+
+ const deUint32 numLevels = ImageViewTest::getNumLevels(viewType);
+ const deUint32 arraySize = ImageViewTest::getArraySize(viewType);
+ const VkImageAspectFlags imageAspectFlags = VK_IMAGE_ASPECT_COLOR_BIT;
+ const VkComponentMapping componentMapping = getFormatComponentMapping(imageFormat);
+
+ de::MovePtr<tcu::TestCaseGroup> rangeTests (new tcu::TestCaseGroup(testCtx, "subresource_range", ""));
+
+#define ADD_SUBRESOURCE_RANGE_TESTS(TEST_CASES) \
+ do { \
+ for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(TEST_CASES); configNdx++) \
+ { \
+ std::ostringstream desc; \
+ const TestCaseConfig config = TEST_CASES[configNdx]; \
+ desc << "Samples level " << config.samplerLod << " with :\n" << config.subresourceRange; \
+ rangeTests->addChild(new ImageViewTest(testCtx, config.name, desc.str().c_str(), viewType, \
+ imageFormat, config.samplerLod, componentMapping, \
+ config.subresourceRange)); \
+ } \
+ } while (0)
+
+ if (viewType == VK_IMAGE_VIEW_TYPE_1D_ARRAY || viewType == VK_IMAGE_VIEW_TYPE_2D_ARRAY)
+ {
+ const TestCaseConfig mipLevelRangeCases[] =
+ {
+ // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
+ { "lod_base_mip_level", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 0u, arraySize } },
+ { "lod_mip_levels", 4.0f, { imageAspectFlags, 0u, 3u, 0u, arraySize } },
+ };
+
+ const TestCaseConfig arrayRangeCases[] =
+ {
+ // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
+ { "base_array_layer", 0.0f, { imageAspectFlags, 0u, numLevels, 1u, arraySize - 1u } },
+ { "array_size", 0.0f, { imageAspectFlags, 0u, numLevels, 0u, 4u } },
+ { "array_base_and_size", 0.0f, { imageAspectFlags, 0u, numLevels, 2u, 3u } },
+ };
+
+ const TestCaseConfig mipLevelAndArrayRangeCases[] =
+ {
+ // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
+ { "lod_base_mip_level_base_array_layer", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 1u, 5u } },
+ { "lod_mip_levels_base_array_layer", 4.0f, { imageAspectFlags, 0u, 3u, 1u, 5u } },
+
+ { "lod_base_mip_level_array_size", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 0u, 4u } },
+ { "lod_mip_levels_array_size", 4.0f, { imageAspectFlags, 0u, 3u, 0u, 4u } },
+
+ { "lod_base_mip_level_array_base_and_size", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 2u, 3u } },
+ { "lod_mip_levels_array_base_and_size", 4.0f, { imageAspectFlags, 0u, 3u, 2u, 3u } },
+ };
+
+ ADD_SUBRESOURCE_RANGE_TESTS(mipLevelRangeCases);
+ ADD_SUBRESOURCE_RANGE_TESTS(arrayRangeCases);
+ ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRangeCases);
+ }
+ else if (viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
+ {
+ const TestCaseConfig mipLevelRangeCases[] =
+ {
+ // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
+ { "lod_base_mip_level", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 0u, arraySize } },
+ { "lod_mip_levels", 4.0f, { imageAspectFlags, 0u, 3u, 0u, arraySize } },
+ };
+
+ const TestCaseConfig arrayRangeCases[] =
+ {
+ // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
+ { "base_array_layer", 0.0f, { imageAspectFlags, 0u, numLevels, 6u, arraySize - 6u } },
+ { "array_size", 0.0f, { imageAspectFlags, 0u, numLevels, 0u, 6u } },
+ { "array_base_and_size", 0.0f, { imageAspectFlags, 0u, numLevels, 12u, 6u } },
+ };
+
+ const TestCaseConfig mipLevelAndArrayRangeCases[] =
+ {
+ // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
+ { "lod_base_mip_level_base_array_layer", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 6u, arraySize - 6u } },
+ { "lod_mip_levels_base_array_layer", 4.0f, { imageAspectFlags, 0u, 3u, 6u, arraySize - 6u } },
+
+ { "lod_base_mip_level_array_size", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 0u, 6u } },
+ { "lod_mip_levels_array_size", 4.0f, { imageAspectFlags, 0u, 3u, 0u, 6u } },
+
+ { "lod_base_mip_level_array_base_and_size", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 12u, 6u } },
+ { "lod_mip_levels_array_base_and_size", 4.0f, { imageAspectFlags, 0u, 3u, 12u, 6u } },
+ };
+
+ ADD_SUBRESOURCE_RANGE_TESTS(mipLevelRangeCases);
+ ADD_SUBRESOURCE_RANGE_TESTS(arrayRangeCases);
+ ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRangeCases);
+ }
+ else if (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_2D)
+ {
+ const TestCaseConfig mipLevelRangeCases[] =
+ {
+ // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
+ { "lod_base_mip_level", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 0u, 1u } },
+ { "lod_mip_levels", 4.0f, { imageAspectFlags, 0u, 3u, 0u, 1u } },
+ };
+
+ const TestCaseConfig arrayRangeCases[] =
+ {
+ // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
+ { "array_layer_second", 0.0f, { imageAspectFlags, 0u, numLevels, 1u, 1u } },
+ { "array_layer_last", 0.0f, { imageAspectFlags, 0u, numLevels, arraySize - 1u, 1u } },
+ };
+
+ const TestCaseConfig mipLevelAndArrayRangeCases[] =
+ {
+ // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
+ { "lod_base_mip_level_array_layer_second", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 1u, 1u } },
+ { "lod_mip_levels_array_layer_second", 4.0f, { imageAspectFlags, 0u, 3u, arraySize - 1u, 1u } },
+
+ { "lod_base_mip_level_array_layer_last", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 5u, 1u } },
+ { "lod_mip_levels_array_layer_last", 4.0f, { imageAspectFlags, 0u, 3u, arraySize - 1u, 1u } },
+ };
+
+ ADD_SUBRESOURCE_RANGE_TESTS(mipLevelRangeCases);
+ ADD_SUBRESOURCE_RANGE_TESTS(arrayRangeCases);
+ ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRangeCases);
+ }
+ else if (viewType == VK_IMAGE_VIEW_TYPE_CUBE)
+ {
+ const TestCaseConfig mipLevelRangeCases[] =
+ {
+ // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
+ { "lod_base_mip_level", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 0u, 6u } },
+ { "lod_mip_levels", 4.0f, { imageAspectFlags, 0u, 3u, 0u, 6u } },
+ };
+
+ const TestCaseConfig arrayRangeCases[] =
+ {
+ // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
+ { "array_layer_second", 0.0f, { imageAspectFlags, 0u, numLevels, 6u, 6u } },
+ { "array_layer_last", 0.0f, { imageAspectFlags, 0u, numLevels, arraySize - 6u, 6u } },
+ };
+
+ const TestCaseConfig mipLevelAndArrayRangeCases[] =
+ {
+ // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
+ { "lod_base_mip_level_array_layer_second", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 6u, 6u } },
+ { "lod_mip_levels_array_layer_second", 4.0f, { imageAspectFlags, 0u, 3u, 6u, 6u } },
+
+ { "lod_base_mip_level_array_layer_last", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, arraySize - 6u, 6u } },
+ { "lod_mip_levels_array_layer_last", 4.0f, { imageAspectFlags, 0u, 3u, arraySize - 6u, 6u } },
+ };
+
+ ADD_SUBRESOURCE_RANGE_TESTS(mipLevelRangeCases);
+ ADD_SUBRESOURCE_RANGE_TESTS(arrayRangeCases);
+ ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRangeCases);
+ }
+ else if (viewType == VK_IMAGE_VIEW_TYPE_3D)
+ {
+ const TestCaseConfig mipLevelRangeCases[] =
+ {
+ // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
+ { "lod_base_mip_level", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 0u, arraySize } },
+ { "lod_mip_levels", 4.0f, { imageAspectFlags, 0u, 3u, 0u, arraySize } },
+ };
+ ADD_SUBRESOURCE_RANGE_TESTS(mipLevelRangeCases);
+ }
+
+#undef ADD_SUBRESOURCE_RANGE_TESTS
+
+ return rangeTests;
+}
+
+static std::vector<VkComponentMapping> getComponentMappingPermutations (const VkComponentMapping& componentMapping)
+{
+ std::vector<VkComponentMapping> mappings;
+
+ const VkComponentSwizzle channelSwizzles[4] = { componentMapping.r, componentMapping.g, componentMapping.b, componentMapping.a };
+
+ // Rearranges the channels by shifting their positions.
+ for (int firstChannelNdx = 0; firstChannelNdx < 4; firstChannelNdx++)
+ {
+ VkComponentSwizzle currentChannel[4];
+
+ for (int channelNdx = 0; channelNdx < 4; channelNdx++)
+ currentChannel[channelNdx] = channelSwizzles[(firstChannelNdx + channelNdx) % 4];
+
+ const VkComponentMapping mappingPermutation =
+ {
+ currentChannel[0],
+ currentChannel[1],
+ currentChannel[2],
+ currentChannel[3]
+ };
+
+ mappings.push_back(mappingPermutation);
+ }
+
+ return mappings;
+}
+
+static std::string getComponentSwizzleCaseName (VkComponentSwizzle componentSwizzle)
+{
+ const std::string fullName = getComponentSwizzleName(componentSwizzle);
+
+ DE_ASSERT(de::beginsWith(fullName, "VK_COMPONENT_SWIZZLE_"));
+
+ return de::toLower(fullName.substr(21));
+}
+
+static std::string getComponentMappingCaseName (const VkComponentMapping& componentMapping)
+{
+ std::ostringstream name;
+
+ name << getComponentSwizzleCaseName(componentMapping.r) << "_"
+ << getComponentSwizzleCaseName(componentMapping.g) << "_"
+ << getComponentSwizzleCaseName(componentMapping.b) << "_"
+ << getComponentSwizzleCaseName(componentMapping.a);
+
+ return name.str();
+}
+
+static de::MovePtr<tcu::TestCaseGroup> createComponentSwizzleTests (tcu::TestContext& testCtx, VkImageViewType viewType, VkFormat imageFormat)
+{
+ deUint32 arraySize = 0;
+
+ switch (viewType)
+ {
+ case VK_IMAGE_VIEW_TYPE_1D:
+ case VK_IMAGE_VIEW_TYPE_2D:
+ case VK_IMAGE_VIEW_TYPE_3D:
+ arraySize = 1;
+ break;
+
+ case VK_IMAGE_VIEW_TYPE_CUBE:
+ arraySize = 6;
+ break;
+
+ case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
+ case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
+ case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
+ arraySize = ImageViewTest::getArraySize(viewType);
+ break;
+
+ default:
+ break;
+ }
+
+ const VkImageSubresourceRange subresourceRange =
+ {
+ VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
+ 0u, // deUint32 baseMipLevel;
+ (deUint32)ImageViewTest::getNumLevels(viewType), // deUint32 mipLevels;
+ 0u, // deUint32 baseArrayLayer;
+ arraySize, // deUint32 arraySize;
+ };
+
+ const std::vector<VkComponentMapping> componentMappings = getComponentMappingPermutations(getFormatComponentMapping(imageFormat));
+ de::MovePtr<tcu::TestCaseGroup> swizzleTests (new tcu::TestCaseGroup(testCtx, "component_swizzle", ""));
+
+ for (size_t mappingNdx = 0; mappingNdx < componentMappings.size(); mappingNdx++)
+ {
+ swizzleTests->addChild(new ImageViewTest(testCtx,
+ getComponentMappingCaseName(componentMappings[mappingNdx]).c_str(),
+ "",
+ viewType,
+ imageFormat,
+ 0.0f,
+ componentMappings[mappingNdx],
+ subresourceRange));
+ }
+
+ return swizzleTests;
+}
+
+} // anonymous
+
+tcu::TestCaseGroup* createImageViewTests (tcu::TestContext& testCtx)
+{
+ const struct
+ {
+ VkImageViewType type;
+ const char* name;
+ }
+ imageViewTypes[] =
+ {
+ { VK_IMAGE_VIEW_TYPE_1D, "1d" },
+ { VK_IMAGE_VIEW_TYPE_1D_ARRAY, "1d_array" },
+ { VK_IMAGE_VIEW_TYPE_2D, "2d" },
+ { VK_IMAGE_VIEW_TYPE_2D_ARRAY, "2d_array" },
+ { VK_IMAGE_VIEW_TYPE_3D, "3d" },
+ { VK_IMAGE_VIEW_TYPE_CUBE, "cube" },
+ { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, "cube_array" }
+ };
+
+ const VkFormat formats[] =
+ {
+ VK_FORMAT_R4G4_UNORM_PACK8,
+ VK_FORMAT_R4G4B4A4_UNORM_PACK16,
+ VK_FORMAT_R5G6B5_UNORM_PACK16,
+ VK_FORMAT_R5G5B5A1_UNORM_PACK16,
+ VK_FORMAT_R8_UNORM,
+ VK_FORMAT_R8_SNORM,
+ VK_FORMAT_R8_USCALED,
+ VK_FORMAT_R8_SSCALED,
+ VK_FORMAT_R8_UINT,
+ VK_FORMAT_R8_SINT,
+ VK_FORMAT_R8_SRGB,
+ VK_FORMAT_R8G8_UNORM,
+ VK_FORMAT_R8G8_SNORM,
+ VK_FORMAT_R8G8_USCALED,
+ VK_FORMAT_R8G8_SSCALED,
+ VK_FORMAT_R8G8_UINT,
+ VK_FORMAT_R8G8_SINT,
+ VK_FORMAT_R8G8_SRGB,
+ VK_FORMAT_R8G8B8_UNORM,
+ VK_FORMAT_R8G8B8_SNORM,
+ VK_FORMAT_R8G8B8_USCALED,
+ VK_FORMAT_R8G8B8_SSCALED,
+ VK_FORMAT_R8G8B8_UINT,
+ VK_FORMAT_R8G8B8_SINT,
+ VK_FORMAT_R8G8B8_SRGB,
+ VK_FORMAT_R8G8B8A8_UNORM,
+ VK_FORMAT_R8G8B8A8_SNORM,
+ VK_FORMAT_R8G8B8A8_USCALED,
+ VK_FORMAT_R8G8B8A8_SSCALED,
+ VK_FORMAT_R8G8B8A8_UINT,
+ VK_FORMAT_R8G8B8A8_SINT,
+ VK_FORMAT_R8G8B8A8_SRGB,
+ VK_FORMAT_A2R10G10B10_UNORM_PACK32,
+ VK_FORMAT_A2R10G10B10_UINT_PACK32,
+ VK_FORMAT_A2B10G10R10_USCALED_PACK32,
+ VK_FORMAT_R16_UNORM,
+ VK_FORMAT_R16_SNORM,
+ VK_FORMAT_R16_USCALED,
+ VK_FORMAT_R16_SSCALED,
+ VK_FORMAT_R16_UINT,
+ VK_FORMAT_R16_SINT,
+ VK_FORMAT_R16_SFLOAT,
+ VK_FORMAT_R16G16_UNORM,
+ VK_FORMAT_R16G16_SNORM,
+ VK_FORMAT_R16G16_USCALED,
+ VK_FORMAT_R16G16_SSCALED,
+ VK_FORMAT_R16G16_UINT,
+ VK_FORMAT_R16G16_SINT,
+ VK_FORMAT_R16G16_SFLOAT,
+ VK_FORMAT_R16G16B16_UNORM,
+ VK_FORMAT_R16G16B16_SNORM,
+ VK_FORMAT_R16G16B16_USCALED,
+ VK_FORMAT_R16G16B16_SSCALED,
+ VK_FORMAT_R16G16B16_UINT,
+ VK_FORMAT_R16G16B16_SINT,
+ VK_FORMAT_R16G16B16_SFLOAT,
+ VK_FORMAT_R16G16B16A16_UNORM,
+ VK_FORMAT_R16G16B16A16_SNORM,
+ VK_FORMAT_R16G16B16A16_USCALED,
+ VK_FORMAT_R16G16B16A16_SSCALED,
+ VK_FORMAT_R16G16B16A16_UINT,
+ VK_FORMAT_R16G16B16A16_SINT,
+ VK_FORMAT_R16G16B16A16_SFLOAT,
+ VK_FORMAT_R32_UINT,
+ VK_FORMAT_R32_SINT,
+ VK_FORMAT_R32_SFLOAT,
+ VK_FORMAT_R32G32_UINT,
+ VK_FORMAT_R32G32_SINT,
+ VK_FORMAT_R32G32_SFLOAT,
+ VK_FORMAT_R32G32B32_UINT,
+ VK_FORMAT_R32G32B32_SINT,
+ VK_FORMAT_R32G32B32_SFLOAT,
+ VK_FORMAT_R32G32B32A32_UINT,
+ VK_FORMAT_R32G32B32A32_SINT,
+ VK_FORMAT_R32G32B32A32_SFLOAT,
+ VK_FORMAT_B10G11R11_UFLOAT_PACK32,
+ VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
+ VK_FORMAT_B4G4R4A4_UNORM_PACK16,
+ VK_FORMAT_B5G5R5A1_UNORM_PACK16,
+
+ // Compressed formats
+ VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,
+ VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK,
+ VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK,
+ VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK,
+ VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK,
+ VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK,
+ VK_FORMAT_EAC_R11_UNORM_BLOCK,
+ VK_FORMAT_EAC_R11_SNORM_BLOCK,
+ VK_FORMAT_EAC_R11G11_UNORM_BLOCK,
+ VK_FORMAT_EAC_R11G11_SNORM_BLOCK,
+ VK_FORMAT_ASTC_4x4_UNORM_BLOCK,
+ VK_FORMAT_ASTC_4x4_SRGB_BLOCK,
+ VK_FORMAT_ASTC_5x4_UNORM_BLOCK,
+ VK_FORMAT_ASTC_5x4_SRGB_BLOCK,
+ VK_FORMAT_ASTC_5x5_UNORM_BLOCK,
+ VK_FORMAT_ASTC_5x5_SRGB_BLOCK,
+ VK_FORMAT_ASTC_6x5_UNORM_BLOCK,
+ VK_FORMAT_ASTC_6x5_SRGB_BLOCK,
+ VK_FORMAT_ASTC_6x6_UNORM_BLOCK,
+ VK_FORMAT_ASTC_6x6_SRGB_BLOCK,
+ VK_FORMAT_ASTC_8x5_UNORM_BLOCK,
+ VK_FORMAT_ASTC_8x5_SRGB_BLOCK,
+ VK_FORMAT_ASTC_8x6_UNORM_BLOCK,
+ VK_FORMAT_ASTC_8x6_SRGB_BLOCK,
+ VK_FORMAT_ASTC_8x8_UNORM_BLOCK,
+ VK_FORMAT_ASTC_8x8_SRGB_BLOCK,
+ VK_FORMAT_ASTC_10x5_UNORM_BLOCK,
+ VK_FORMAT_ASTC_10x5_SRGB_BLOCK,
+ VK_FORMAT_ASTC_10x6_UNORM_BLOCK,
+ VK_FORMAT_ASTC_10x6_SRGB_BLOCK,
+ VK_FORMAT_ASTC_10x8_UNORM_BLOCK,
+ VK_FORMAT_ASTC_10x8_SRGB_BLOCK,
+ VK_FORMAT_ASTC_10x10_UNORM_BLOCK,
+ VK_FORMAT_ASTC_10x10_SRGB_BLOCK,
+ VK_FORMAT_ASTC_12x10_UNORM_BLOCK,
+ VK_FORMAT_ASTC_12x10_SRGB_BLOCK,
+ VK_FORMAT_ASTC_12x12_UNORM_BLOCK,
+ VK_FORMAT_ASTC_12x12_SRGB_BLOCK,
+ };
+
+ de::MovePtr<tcu::TestCaseGroup> imageTests (new tcu::TestCaseGroup(testCtx, "image_view", "Image tests"));
+ de::MovePtr<tcu::TestCaseGroup> viewTypeTests (new tcu::TestCaseGroup(testCtx, "view_type", ""));
+
+ for (int viewTypeNdx = 0; viewTypeNdx < DE_LENGTH_OF_ARRAY(imageViewTypes); viewTypeNdx++)
+ {
+ const VkImageViewType viewType = imageViewTypes[viewTypeNdx].type;
+ de::MovePtr<tcu::TestCaseGroup> viewTypeGroup (new tcu::TestCaseGroup(testCtx, imageViewTypes[viewTypeNdx].name, (std::string("Uses a ") + imageViewTypes[viewTypeNdx].name + " view").c_str()));
+ de::MovePtr<tcu::TestCaseGroup> formatTests (new tcu::TestCaseGroup(testCtx, "format", "Uses samplable formats"));
+
+ for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
+ {
+ const VkFormat format = formats[formatNdx];
+
+ if (isCompressedFormat(format) && (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_1D_ARRAY))
+ {
+ break;
+ }
+
+ de::MovePtr<tcu::TestCaseGroup> formatGroup (new tcu::TestCaseGroup(testCtx,
+ getFormatCaseName(format).c_str(),
+ (std::string("Samples a texture of format ") + getFormatName(format)).c_str()));
+
+ de::MovePtr<tcu::TestCaseGroup> subresourceRangeTests = createSubresourceRangeTests(testCtx, viewType, format);
+ de::MovePtr<tcu::TestCaseGroup> componentSwizzleTests = createComponentSwizzleTests(testCtx, viewType, format);
+
+ formatGroup->addChild(componentSwizzleTests.release());
+ formatGroup->addChild(subresourceRangeTests.release());
+ formatTests->addChild(formatGroup.release());
+ }
+
+ viewTypeGroup->addChild(formatTests.release());
+ viewTypeTests->addChild(viewTypeGroup.release());
+ }
+
+ imageTests->addChild(viewTypeTests.release());
+
+ return imageTests.release();
+}
+
+} // pipeline
+} // vkt
--- /dev/null
+#ifndef _VKTPIPELINEIMAGEVIEWTESTS_HPP
+#define _VKTPIPELINEIMAGEVIEWTESTS_HPP
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Imagination Technologies Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by Khronos,
+ * at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Image View Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktTestCase.hpp"
+
+namespace vkt
+{
+namespace pipeline
+{
+
+tcu::TestCaseGroup* createImageViewTests (tcu::TestContext& testCtx);
+
+} // pipeline
+} // vkt
+
+#endif // _VKTPIPELINEIMAGEVIEWTESTS_HPP
--- /dev/null
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Imagination Technologies Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by Khronos,
+ * at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Reference renderer.
+ *//*--------------------------------------------------------------------*/
+
+#include "vktPipelineReferenceRenderer.hpp"
+#include "vktPipelineClearUtil.hpp"
+#include "rrShadingContext.hpp"
+#include "rrVertexAttrib.hpp"
+
+namespace vkt
+{
+namespace pipeline
+{
+
+using namespace vk;
+
+rr::BlendFunc mapVkBlendFactor (VkBlendFactor blend)
+{
+ switch (blend)
+ {
+ case VK_BLEND_FACTOR_ZERO: return rr::BLENDFUNC_ZERO;
+ case VK_BLEND_FACTOR_ONE: return rr::BLENDFUNC_ONE;
+ case VK_BLEND_FACTOR_SRC_COLOR: return rr::BLENDFUNC_SRC_COLOR;
+ case VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR: return rr::BLENDFUNC_ONE_MINUS_SRC_COLOR;
+ case VK_BLEND_FACTOR_DST_COLOR: return rr::BLENDFUNC_DST_COLOR;
+ case VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR: return rr::BLENDFUNC_ONE_MINUS_DST_COLOR;
+ case VK_BLEND_FACTOR_SRC_ALPHA: return rr::BLENDFUNC_SRC_ALPHA;
+ case VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA: return rr::BLENDFUNC_ONE_MINUS_SRC_ALPHA;
+ case VK_BLEND_FACTOR_DST_ALPHA: return rr::BLENDFUNC_DST_ALPHA;
+ case VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA: return rr::BLENDFUNC_ONE_MINUS_DST_ALPHA;
+ case VK_BLEND_FACTOR_CONSTANT_COLOR: return rr::BLENDFUNC_CONSTANT_COLOR;
+ case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR: return rr::BLENDFUNC_ONE_MINUS_CONSTANT_COLOR;
+ case VK_BLEND_FACTOR_CONSTANT_ALPHA: return rr::BLENDFUNC_CONSTANT_ALPHA;
+ case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA: return rr::BLENDFUNC_ONE_MINUS_CONSTANT_ALPHA;
+ case VK_BLEND_FACTOR_SRC_ALPHA_SATURATE: return rr::BLENDFUNC_SRC_ALPHA_SATURATE;
+ case VK_BLEND_FACTOR_SRC1_COLOR: return rr::BLENDFUNC_SRC1_COLOR;
+ case VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR: return rr::BLENDFUNC_ONE_MINUS_SRC1_COLOR;
+ case VK_BLEND_FACTOR_SRC1_ALPHA: return rr::BLENDFUNC_SRC1_ALPHA;
+ case VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA: return rr::BLENDFUNC_ONE_MINUS_SRC1_ALPHA;
+ default:
+ DE_ASSERT(false);
+ }
+ return rr::BLENDFUNC_LAST;
+}
+
+rr::BlendEquation mapVkBlendOp (VkBlendOp blendOp)
+{
+ switch (blendOp)
+ {
+ case VK_BLEND_OP_ADD: return rr::BLENDEQUATION_ADD;
+ case VK_BLEND_OP_SUBTRACT: return rr::BLENDEQUATION_SUBTRACT;
+ case VK_BLEND_OP_REVERSE_SUBTRACT: return rr::BLENDEQUATION_REVERSE_SUBTRACT;
+ case VK_BLEND_OP_MIN: return rr::BLENDEQUATION_MIN;
+ case VK_BLEND_OP_MAX: return rr::BLENDEQUATION_MAX;
+ default:
+ DE_ASSERT(false);
+ }
+ return rr::BLENDEQUATION_LAST;
+}
+
+tcu::BVec4 mapVkColorComponentFlags (VkColorComponentFlags flags)
+{
+ return tcu::BVec4((flags & VK_COLOR_COMPONENT_R_BIT) != 0,
+ (flags & VK_COLOR_COMPONENT_G_BIT) != 0,
+ (flags & VK_COLOR_COMPONENT_B_BIT) != 0,
+ (flags & VK_COLOR_COMPONENT_A_BIT) != 0);
+}
+
+rr::TestFunc mapVkCompareOp (VkCompareOp compareFunc)
+{
+ switch (compareFunc)
+ {
+ case VK_COMPARE_OP_NEVER: return rr::TESTFUNC_NEVER;
+ case VK_COMPARE_OP_LESS: return rr::TESTFUNC_LESS;
+ case VK_COMPARE_OP_EQUAL: return rr::TESTFUNC_EQUAL;
+ case VK_COMPARE_OP_LESS_OR_EQUAL: return rr::TESTFUNC_LEQUAL;
+ case VK_COMPARE_OP_GREATER: return rr::TESTFUNC_GREATER;
+ case VK_COMPARE_OP_NOT_EQUAL: return rr::TESTFUNC_NOTEQUAL;
+ case VK_COMPARE_OP_GREATER_OR_EQUAL: return rr::TESTFUNC_GEQUAL;
+ case VK_COMPARE_OP_ALWAYS: return rr::TESTFUNC_ALWAYS;
+ default:
+ DE_ASSERT(false);
+ }
+ return rr::TESTFUNC_LAST;
+}
+
+rr::PrimitiveType mapVkPrimitiveTopology (VkPrimitiveTopology primitiveTopology)
+{
+ switch (primitiveTopology)
+ {
+ case VK_PRIMITIVE_TOPOLOGY_POINT_LIST: return rr::PRIMITIVETYPE_POINTS;
+ case VK_PRIMITIVE_TOPOLOGY_LINE_LIST: return rr::PRIMITIVETYPE_LINES;
+ case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: return rr::PRIMITIVETYPE_LINE_STRIP;
+ case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: return rr::PRIMITIVETYPE_TRIANGLES;
+ case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: return rr::PRIMITIVETYPE_TRIANGLE_FAN;
+ case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: return rr::PRIMITIVETYPE_TRIANGLE_STRIP;
+ case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY: return rr::PRIMITIVETYPE_LINES_ADJACENCY;
+ case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY: return rr::PRIMITIVETYPE_LINE_STRIP_ADJACENCY;
+ case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: return rr::PRIMITIVETYPE_TRIANGLES_ADJACENCY;
+ case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: return rr::PRIMITIVETYPE_TRIANGLE_STRIP_ADJACENCY;
+ default:
+ DE_ASSERT(false);
+ }
+ return rr::PRIMITIVETYPE_LAST;
+}
+
+rr::StencilOp mapVkStencilOp (vk::VkStencilOp stencilOp)
+{
+ switch (stencilOp)
+ {
+ case VK_STENCIL_OP_KEEP: return rr::STENCILOP_KEEP;
+ case VK_STENCIL_OP_ZERO: return rr::STENCILOP_ZERO;
+ case VK_STENCIL_OP_REPLACE: return rr::STENCILOP_REPLACE;
+ case VK_STENCIL_OP_INCREMENT_AND_CLAMP: return rr::STENCILOP_INCR;
+ case VK_STENCIL_OP_DECREMENT_AND_CLAMP: return rr::STENCILOP_DECR;
+ case VK_STENCIL_OP_INVERT: return rr::STENCILOP_INVERT;
+ case VK_STENCIL_OP_INCREMENT_AND_WRAP: return rr::STENCILOP_INCR_WRAP;
+ case VK_STENCIL_OP_DECREMENT_AND_WRAP: return rr::STENCILOP_DECR_WRAP;
+ default:
+ DE_ASSERT(false);
+ }
+ return rr::STENCILOP_LAST;
+}
+
+tcu::Vec4 swizzle (const tcu::Vec4& color, const tcu::UVec4& swizzle)
+{
+ const float channelValues[] =
+ {
+ 0.0f,
+ 1.0f,
+ color.x(),
+ color.y(),
+ color.z(),
+ color.w()
+ };
+
+ return tcu::Vec4(channelValues[swizzle.x()],
+ channelValues[swizzle.y()],
+ channelValues[swizzle.z()],
+ channelValues[swizzle.w()]);
+}
+
+ReferenceRenderer::ReferenceRenderer(int surfaceWidth,
+ int surfaceHeight,
+ int numSamples,
+ const tcu::TextureFormat& colorFormat,
+ const tcu::TextureFormat& depthStencilFormat,
+ const rr::Program* const program)
+ : m_surfaceWidth (surfaceWidth)
+ , m_surfaceHeight (surfaceHeight)
+ , m_numSamples (numSamples)
+ , m_colorFormat (colorFormat)
+ , m_depthStencilFormat (depthStencilFormat)
+ , m_program (program)
+{
+ const tcu::TextureChannelClass formatClass = tcu::getTextureChannelClass(colorFormat.type);
+ const bool hasDepthStencil = (m_depthStencilFormat.order != tcu::TextureFormat::CHANNELORDER_LAST);
+ const bool hasDepthBufferOnly = (m_depthStencilFormat.order == tcu::TextureFormat::D);
+ const bool hasStencilBufferOnly = (m_depthStencilFormat.order == tcu::TextureFormat::S);
+ const int actualSamples = (formatClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER || formatClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)? 1: m_numSamples;
+
+ m_colorBuffer.setStorage(m_colorFormat, actualSamples, m_surfaceWidth, m_surfaceHeight);
+ m_resolveColorBuffer.setStorage(m_colorFormat, m_surfaceWidth, m_surfaceHeight);
+
+ if (formatClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
+ {
+ tcu::clear(m_colorBuffer.getAccess(), defaultClearColorInt(m_colorFormat));
+ tcu::clear(m_resolveColorBuffer.getAccess(), defaultClearColorInt(m_colorFormat));
+ }
+ else if (formatClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
+ {
+ tcu::clear(m_colorBuffer.getAccess(), defaultClearColorUint(m_colorFormat));
+ tcu::clear(m_resolveColorBuffer.getAccess(), defaultClearColorUint(m_colorFormat));
+ }
+ else
+ {
+ tcu::Vec4 clearColor = defaultClearColor(m_colorFormat);
+
+ if (isSRGB(m_colorFormat))
+ clearColor = tcu::linearToSRGB(clearColor);
+
+ tcu::clear(m_colorBuffer.getAccess(), clearColor);
+ tcu::clear(m_resolveColorBuffer.getAccess(), clearColor);
+ }
+
+ if (hasDepthStencil)
+ {
+ if (hasDepthBufferOnly)
+ {
+ m_depthStencilBuffer.setStorage(m_depthStencilFormat, actualSamples, surfaceWidth, surfaceHeight);
+ tcu::clearDepth(m_depthStencilBuffer.getAccess(), defaultClearDepth());
+
+ m_renderTarget = new rr::RenderTarget(rr::MultisamplePixelBufferAccess::fromMultisampleAccess(m_colorBuffer.getAccess()),
+ rr::MultisamplePixelBufferAccess::fromMultisampleAccess(m_depthStencilBuffer.getAccess()));
+ }
+ else if (hasStencilBufferOnly)
+ {
+ m_depthStencilBuffer.setStorage(m_depthStencilFormat, actualSamples, surfaceWidth, surfaceHeight);
+ tcu::clearStencil(m_depthStencilBuffer.getAccess(), defaultClearStencil());
+
+ m_renderTarget = new rr::RenderTarget(rr::MultisamplePixelBufferAccess::fromMultisampleAccess(m_colorBuffer.getAccess()),
+ rr::MultisamplePixelBufferAccess(),
+ rr::MultisamplePixelBufferAccess::fromMultisampleAccess(m_depthStencilBuffer.getAccess()));
+ }
+ else
+ {
+ m_depthStencilBuffer.setStorage(m_depthStencilFormat, actualSamples, surfaceWidth, surfaceHeight);
+
+ tcu::clearDepth(m_depthStencilBuffer.getAccess(), defaultClearDepth());
+ tcu::clearStencil(m_depthStencilBuffer.getAccess(), defaultClearStencil());
+
+ m_renderTarget = new rr::RenderTarget(rr::MultisamplePixelBufferAccess::fromMultisampleAccess(m_colorBuffer.getAccess()),
+ rr::MultisamplePixelBufferAccess::fromMultisampleAccess(m_depthStencilBuffer.getAccess()),
+ rr::MultisamplePixelBufferAccess::fromMultisampleAccess(m_depthStencilBuffer.getAccess()));
+ }
+ }
+ else
+ {
+ m_renderTarget = new rr::RenderTarget(rr::MultisamplePixelBufferAccess::fromMultisampleAccess(m_colorBuffer.getAccess()));
+ }
+}
+
+ReferenceRenderer::~ReferenceRenderer (void)
+{
+ delete m_renderTarget;
+}
+
+void ReferenceRenderer::draw (const rr::RenderState& renderState,
+ const rr::PrimitiveType primitive,
+ const std::vector<Vertex4RGBA>& vertexBuffer)
+{
+ const rr::PrimitiveList primitives(primitive, (int)vertexBuffer.size(), 0);
+
+ std::vector<tcu::Vec4> positions;
+ std::vector<tcu::Vec4> colors;
+
+ for (size_t vertexNdx = 0; vertexNdx < vertexBuffer.size(); vertexNdx++)
+ {
+ const Vertex4RGBA& v = vertexBuffer[vertexNdx];
+ positions.push_back(v.position);
+ colors.push_back(v.color);
+ }
+
+ rr::VertexAttrib vertexAttribs[2];
+
+ // Position attribute
+ vertexAttribs[0].type = rr::VERTEXATTRIBTYPE_FLOAT;
+ vertexAttribs[0].size = 4;
+ vertexAttribs[0].pointer = positions.data();
+ // UV attribute
+ vertexAttribs[1].type = rr::VERTEXATTRIBTYPE_FLOAT;
+ vertexAttribs[1].size = 4;
+ vertexAttribs[1].pointer = colors.data();
+
+ rr::DrawCommand drawQuadCommand(renderState, *m_renderTarget, *m_program, 2, vertexAttribs, primitives);
+
+ m_renderer.draw(drawQuadCommand);
+}
+
+void ReferenceRenderer::draw (const rr::RenderState& renderState,
+ const rr::PrimitiveType primitive,
+ const std::vector<Vertex4Tex4>& vertexBuffer)
+{
+ const rr::PrimitiveList primitives(primitive, (int)vertexBuffer.size(), 0);
+
+ std::vector<tcu::Vec4> positions;
+ std::vector<tcu::Vec4> texCoords;
+
+ for (size_t vertexNdx = 0; vertexNdx < vertexBuffer.size(); vertexNdx++)
+ {
+ const Vertex4Tex4& v = vertexBuffer[vertexNdx];
+ positions.push_back(v.position);
+ texCoords.push_back(v.texCoord);
+ }
+
+ rr::VertexAttrib vertexAttribs[2];
+
+ // Position attribute
+ vertexAttribs[0].type = rr::VERTEXATTRIBTYPE_FLOAT;
+ vertexAttribs[0].size = 4;
+ vertexAttribs[0].pointer = positions.data();
+ // UV attribute
+ vertexAttribs[1].type = rr::VERTEXATTRIBTYPE_FLOAT;
+ vertexAttribs[1].size = 4;
+ vertexAttribs[1].pointer = texCoords.data();
+
+ rr::DrawCommand drawQuadCommand(renderState, *m_renderTarget, *m_program, 2, vertexAttribs, primitives);
+
+ m_renderer.draw(drawQuadCommand);
+}
+
+tcu::PixelBufferAccess ReferenceRenderer::getAccess (void)
+{
+ rr::MultisampleConstPixelBufferAccess multiSampleAccess = rr::MultisampleConstPixelBufferAccess::fromMultisampleAccess(m_colorBuffer.getAccess());
+ rr::resolveMultisampleColorBuffer(m_resolveColorBuffer.getAccess(), multiSampleAccess);
+
+ return m_resolveColorBuffer.getAccess();
+}
+
+const rr::ViewportState ReferenceRenderer::getViewportState (void) const
+{
+ return rr::ViewportState(rr::WindowRectangle(0, 0, m_surfaceWidth, m_surfaceHeight));
+}
+
+} // pipeline
+} // vkt
--- /dev/null
+#ifndef _VKTPIPELINEREFERENCERENDERER_HPP
+#define _VKTPIPELINEREFERENCERENDERER_HPP
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Imagination Technologies Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by Khronos,
+ * at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Reference renderer.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkDefs.hpp"
+#include "vktPipelineVertexUtil.hpp"
+#include "tcuVector.hpp"
+#include "tcuVectorType.hpp"
+#include "tcuTexture.hpp"
+#include "tcuTextureUtil.hpp"
+#include "rrRenderState.hpp"
+#include "rrRenderer.hpp"
+#include <cstring>
+
+namespace vkt
+{
+
+namespace pipeline
+{
+
+tcu::Vec4 swizzle (const tcu::Vec4& color, const tcu::UVec4& swizzle);
+
+class ColorVertexShader : public rr::VertexShader
+{
+public:
+ ColorVertexShader (void) : rr::VertexShader(2, 2)
+ {
+ m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
+ m_inputs[1].type = rr::GENERICVECTYPE_FLOAT;
+
+ m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
+ m_outputs[1].type = rr::GENERICVECTYPE_FLOAT;
+ }
+
+ virtual ~ColorVertexShader (void) {}
+
+ virtual void shadeVertices (const rr::VertexAttrib* inputs,
+ rr::VertexPacket* const* packets,
+ const int numPackets) const
+ {
+ tcu::Vec4 position;
+ tcu::Vec4 color;
+
+ for (int packetNdx = 0; packetNdx < numPackets; packetNdx++)
+ {
+ rr::VertexPacket* const packet = packets[packetNdx];
+
+ readVertexAttrib(position, inputs[0], packet->instanceNdx, packet->vertexNdx);
+ readVertexAttrib(color, inputs[1], packet->instanceNdx, packet->vertexNdx);
+
+ packet->outputs[0] = position;
+ packet->outputs[1] = color;
+ packet->position = position;
+ }
+ }
+};
+
+class TexCoordVertexShader : public rr::VertexShader
+{
+public:
+ TexCoordVertexShader (void) : rr::VertexShader(2, 2)
+ {
+ m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
+ m_inputs[1].type = rr::GENERICVECTYPE_FLOAT;
+
+ m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
+ m_outputs[1].type = rr::GENERICVECTYPE_FLOAT;
+ }
+
+ virtual ~TexCoordVertexShader (void) {}
+
+ virtual void shadeVertices (const rr::VertexAttrib* inputs,
+ rr::VertexPacket* const* packets,
+ const int numPackets) const
+ {
+ tcu::Vec4 position;
+ tcu::Vec4 texCoord;
+
+ for (int packetNdx = 0; packetNdx < numPackets; packetNdx++)
+ {
+ rr::VertexPacket* const packet = packets[packetNdx];
+
+ readVertexAttrib(position, inputs[0], packet->instanceNdx, packet->vertexNdx);
+ readVertexAttrib(texCoord, inputs[1], packet->instanceNdx, packet->vertexNdx);
+
+ packet->outputs[0] = position;
+ packet->outputs[1] = texCoord;
+ packet->position = position;
+ }
+ }
+};
+
+class ColorFragmentShader : public rr::FragmentShader
+{
+private:
+ const tcu::TextureFormat m_colorFormat;
+ const tcu::TextureFormat m_depthStencilFormat;
+
+public:
+ ColorFragmentShader (const tcu::TextureFormat& colorFormat,
+ const tcu::TextureFormat& depthStencilFormat)
+ : rr::FragmentShader (2, 1)
+ , m_colorFormat (colorFormat)
+ , m_depthStencilFormat (depthStencilFormat)
+ {
+ const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(m_colorFormat.type);
+
+ m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
+ m_inputs[1].type = rr::GENERICVECTYPE_FLOAT;
+ m_outputs[0].type = (channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)? rr::GENERICVECTYPE_INT32 :
+ (channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)? rr::GENERICVECTYPE_UINT32
+ : rr::GENERICVECTYPE_FLOAT;
+ }
+
+ virtual ~ColorFragmentShader (void) {}
+
+ virtual void shadeFragments (rr::FragmentPacket* packets,
+ const int numPackets,
+ const rr::FragmentShadingContext& context) const
+ {
+ for (int packetNdx = 0; packetNdx < numPackets; packetNdx++)
+ {
+ const rr::FragmentPacket& packet = packets[packetNdx];
+
+ if (m_depthStencilFormat.order == tcu::TextureFormat::D || m_depthStencilFormat.order == tcu::TextureFormat::DS)
+ {
+ for (int fragNdx = 0; fragNdx < 4; fragNdx++)
+ {
+ const tcu::Vec4 vtxPosition = rr::readVarying<float>(packet, context, 0, fragNdx);
+ rr::writeFragmentDepth(context, packetNdx, fragNdx, 0, vtxPosition.z());
+ }
+ }
+
+ for (int fragNdx = 0; fragNdx < 4; fragNdx++)
+ {
+ const tcu::Vec4 vtxColor = rr::readVarying<float>(packet, context, 1, fragNdx);
+ rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, vtxColor);
+ }
+ }
+ }
+};
+
+template<typename TextureType>
+class SamplerFragmentShader : public rr::FragmentShader
+{
+private:
+ const tcu::TextureFormat m_colorFormat;
+ const tcu::TextureFormatInfo m_colorFormatInfo;
+ const TextureType m_texture;
+ const tcu::TextureFormatInfo m_textureFormatInfo;
+ const tcu::Sampler m_sampler;
+ const float m_lod;
+ const tcu::UVec4 m_swizzle;
+
+public:
+ SamplerFragmentShader (const tcu::TextureFormat& colorFormat, const TextureType& texture, const tcu::Sampler& sampler, float lod, const tcu::UVec4& swizzle)
+ : rr::FragmentShader (2, 1)
+ , m_colorFormat (colorFormat)
+ , m_colorFormatInfo (tcu::getTextureFormatInfo(m_colorFormat))
+ , m_texture (texture)
+ , m_textureFormatInfo (tcu::getTextureFormatInfo(m_texture.getFormat()))
+ , m_sampler (sampler)
+ , m_lod (lod)
+ , m_swizzle (swizzle)
+ {
+ const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(m_colorFormat.type);
+ m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
+ m_inputs[1].type = rr::GENERICVECTYPE_FLOAT;
+ m_outputs[0].type = (channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)? rr::GENERICVECTYPE_INT32 :
+ (channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)? rr::GENERICVECTYPE_UINT32
+ : rr::GENERICVECTYPE_FLOAT;
+ }
+
+ virtual ~SamplerFragmentShader (void)
+ {
+ }
+
+ static tcu::Vec4 sampleTexture (const tcu::Texture1D& texture, const tcu::Sampler& sampler, const tcu::Vec4& texCoord, float lod)
+ {
+ return texture.sample(sampler, texCoord.x(), lod);
+ }
+
+ static tcu::Vec4 sampleTexture (const tcu::Texture1DArray& texture, const tcu::Sampler& sampler, const tcu::Vec4& texCoord, float lod)
+ {
+ return texture.sample(sampler, texCoord.x(), texCoord.y(), lod);
+ }
+
+ static tcu::Vec4 sampleTexture (const tcu::Texture2D& texture, const tcu::Sampler& sampler, const tcu::Vec4& texCoord, float lod)
+ {
+ return texture.sample(sampler, texCoord.x(), texCoord.y(), lod);
+ }
+
+ static tcu::Vec4 sampleTexture (const tcu::Texture2DArray& texture, const tcu::Sampler& sampler, const tcu::Vec4& texCoord, float lod)
+ {
+ return texture.sample(sampler, texCoord.x(), texCoord.y(), texCoord.z(), lod);
+ }
+
+ static tcu::Vec4 sampleTexture (const tcu::Texture3D& texture, const tcu::Sampler& sampler, const tcu::Vec4& texCoord, float lod)
+ {
+ return texture.sample(sampler, texCoord.x(), texCoord.y(), texCoord.z(), lod);
+ }
+
+ static tcu::Vec4 sampleTexture (const tcu::TextureCube& texture, const tcu::Sampler& sampler, const tcu::Vec4& texCoord, float lod)
+ {
+ return texture.sample(sampler, texCoord.x(), texCoord.y(), texCoord.z(), lod);
+ }
+
+ static tcu::Vec4 sampleTexture (const tcu::TextureCubeArray& texture, const tcu::Sampler& sampler, const tcu::Vec4& texCoord, float lod)
+ {
+ return texture.sample(sampler, texCoord.x(), texCoord.y(), texCoord.z(), texCoord.w(), lod);
+ }
+
+ virtual void shadeFragments (rr::FragmentPacket* packets,
+ const int numPackets,
+ const rr::FragmentShadingContext& context) const
+ {
+ for (int packetNdx = 0; packetNdx < numPackets; packetNdx++)
+ {
+ const rr::FragmentPacket& packet = packets[packetNdx];
+
+ for (int fragNdx = 0; fragNdx < 4; fragNdx++)
+ {
+ const tcu::Vec4 vtxTexCoord = rr::readVarying<float>(packet, context, 1, fragNdx);
+ const tcu::Vec4 texColor = sampleTexture(m_texture, m_sampler, vtxTexCoord, m_lod);
+ const tcu::Vec4 normColor = texColor * m_textureFormatInfo.lookupScale + m_textureFormatInfo.lookupBias;
+ const tcu::Vec4 color = (normColor - m_colorFormatInfo.lookupBias) / m_colorFormatInfo.lookupScale;
+ const tcu::Vec4 outColor = swizzle(color, m_swizzle);
+
+ rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, outColor);
+ }
+ }
+ }
+};
+
+class Program
+{
+public:
+ virtual ~Program (void) { }
+
+ virtual rr::Program getReferenceProgram (void) const = 0;
+};
+
+template<typename TextureType>
+class SamplerProgram: public Program
+{
+private:
+ TexCoordVertexShader m_vertexShader;
+ SamplerFragmentShader<TextureType> m_fragmentShader;
+public:
+ SamplerProgram (const tcu::TextureFormat& colorFormat, const TextureType& texture, const tcu::Sampler& sampler, float lod, const tcu::UVec4& swizzle)
+ : m_vertexShader ()
+ , m_fragmentShader (colorFormat, texture, sampler, lod, swizzle)
+ {
+ }
+
+ virtual ~SamplerProgram (void) { }
+
+ virtual rr::Program getReferenceProgram (void) const
+ {
+ return rr::Program(&m_vertexShader, &m_fragmentShader);
+ }
+};
+
+class ReferenceRenderer
+{
+public:
+ ReferenceRenderer (int surfaceWidth,
+ int surfaceHeight,
+ int numSamples,
+ const tcu::TextureFormat& colorFormat,
+ const tcu::TextureFormat& depthStencilFormat,
+ const rr::Program* const program);
+
+ virtual ~ReferenceRenderer (void);
+
+ void draw (const rr::RenderState& renderState,
+ const rr::PrimitiveType primitive,
+ const std::vector<Vertex4RGBA>& vertexBuffer);
+
+ void draw (const rr::RenderState& renderState,
+ const rr::PrimitiveType primitive,
+ const std::vector<Vertex4Tex4>& vertexBuffer);
+
+ tcu::PixelBufferAccess getAccess (void);
+ const rr::ViewportState getViewportState (void) const;
+
+private:
+ rr::Renderer m_renderer;
+
+ const int m_surfaceWidth;
+ const int m_surfaceHeight;
+ const int m_numSamples;
+
+ const tcu::TextureFormat m_colorFormat;
+ const tcu::TextureFormat m_depthStencilFormat;
+
+ tcu::TextureLevel m_colorBuffer;
+ tcu::TextureLevel m_resolveColorBuffer;
+ tcu::TextureLevel m_depthStencilBuffer;
+
+ rr::RenderTarget* m_renderTarget;
+ const rr::Program* m_program;
+};
+
+rr::TestFunc mapVkCompareOp (vk::VkCompareOp compareFunc);
+rr::PrimitiveType mapVkPrimitiveTopology (vk::VkPrimitiveTopology primitiveTopology);
+rr::BlendFunc mapVkBlendFactor (vk::VkBlendFactor blendFactor);
+rr::BlendEquation mapVkBlendOp (vk::VkBlendOp blendOp);
+tcu::BVec4 mapVkColorComponentFlags (vk::VkColorComponentFlags flags);
+rr::StencilOp mapVkStencilOp (vk::VkStencilOp stencilOp);
+
+} // pipeline
+} // vkt
+
+#endif // _VKTPIPELINEREFERENCERENDERER_HPP
--- /dev/null
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Imagination Technologies Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by Khronos,
+ * at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Sampler Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktPipelineSamplerTests.hpp"
+#include "vktPipelineImageSamplingInstance.hpp"
+#include "vktPipelineImageUtil.hpp"
+#include "vktPipelineVertexUtil.hpp"
+#include "vktTestCase.hpp"
+#include "vkImageUtil.hpp"
+#include "vkPrograms.hpp"
+#include "tcuPlatform.hpp"
+#include "tcuTextureUtil.hpp"
+#include "deStringUtil.hpp"
+#include "deMemory.h"
+
+#include <iomanip>
+#include <sstream>
+#include <vector>
+
+namespace vkt
+{
+namespace pipeline
+{
+
+using namespace vk;
+using de::MovePtr;
+
+namespace
+{
+
+class SamplerTest : public vkt::TestCase
+{
+public:
+ SamplerTest (tcu::TestContext& testContext,
+ const char* name,
+ const char* description,
+ VkImageViewType imageViewType,
+ VkFormat imageFormat,
+ int imageSize,
+ float samplerLod);
+ virtual ~SamplerTest (void) {}
+
+ virtual void initPrograms (SourceCollections& sourceCollections) const;
+ virtual TestInstance* createInstance (Context& context) const;
+ virtual tcu::IVec2 getRenderSize (VkImageViewType viewType) const;
+ virtual std::vector<Vertex4Tex4> createVertices (void) const;
+ virtual VkSamplerCreateInfo getSamplerCreateInfo (void) const;
+
+ static std::string getGlslSamplerType (const tcu::TextureFormat& format, VkImageViewType type);
+ static tcu::IVec3 getImageSize (VkImageViewType viewType, int size);
+ static int getArraySize (VkImageViewType viewType);
+
+protected:
+ VkImageViewType m_imageViewType;
+ VkFormat m_imageFormat;
+ int m_imageSize;
+ VkImageViewCreateInfo m_imageViewParams;
+ VkSamplerCreateInfo m_samplerParams;
+ float m_samplerLod;
+};
+
+class SamplerMagFilterTest : public SamplerTest
+{
+public:
+ SamplerMagFilterTest (tcu::TestContext& testContext,
+ const char* name,
+ const char* description,
+ VkImageViewType imageViewType,
+ VkFormat imageFormat,
+ VkFilter magFilter);
+ virtual ~SamplerMagFilterTest (void) {}
+ virtual VkSamplerCreateInfo getSamplerCreateInfo (void) const;
+
+private:
+ VkFilter m_magFilter;
+};
+
+class SamplerMinFilterTest : public SamplerTest
+{
+public:
+ SamplerMinFilterTest (tcu::TestContext& testContext,
+ const char* name,
+ const char* description,
+ VkImageViewType imageViewType,
+ VkFormat imageFormat,
+ VkFilter minFilter);
+ virtual ~SamplerMinFilterTest (void) {}
+ virtual VkSamplerCreateInfo getSamplerCreateInfo (void) const;
+
+private:
+ VkFilter m_minFilter;
+};
+
+class SamplerLodTest : public SamplerTest
+{
+public:
+ SamplerLodTest (tcu::TestContext& testContext,
+ const char* name,
+ const char* description,
+ VkImageViewType imageViewType,
+ VkFormat imageFormat,
+ VkSamplerMipmapMode mipmapMode,
+ float minLod,
+ float maxLod,
+ float mipLodBias,
+ float samplerLod);
+ virtual ~SamplerLodTest (void) {}
+ virtual VkSamplerCreateInfo getSamplerCreateInfo (void) const;
+
+private:
+ VkSamplerMipmapMode m_mipmapMode;
+ float m_minLod;
+ float m_maxLod;
+ float m_mipLodBias;
+};
+
+class SamplerAddressModesTest : public SamplerTest
+{
+public:
+ SamplerAddressModesTest (tcu::TestContext& testContext,
+ const char* name,
+ const char* description,
+ VkImageViewType imageViewType,
+ VkFormat imageFormat,
+ VkSamplerAddressMode addressU,
+ VkSamplerAddressMode addressV,
+ VkSamplerAddressMode addressW,
+ VkBorderColor borderColor);
+ virtual ~SamplerAddressModesTest (void) {}
+ virtual tcu::IVec2 getRenderSize (VkImageViewType viewType) const;
+ virtual std::vector<Vertex4Tex4> createVertices (void) const;
+ virtual VkSamplerCreateInfo getSamplerCreateInfo (void) const;
+
+private:
+ VkSamplerAddressMode m_addressU;
+ VkSamplerAddressMode m_addressV;
+ VkSamplerAddressMode m_addressW;
+ VkBorderColor m_borderColor;
+};
+
+
+// SamplerTest
+
+SamplerTest::SamplerTest (tcu::TestContext& testContext,
+ const char* name,
+ const char* description,
+ VkImageViewType imageViewType,
+ VkFormat imageFormat,
+ int imageSize,
+ float samplerLod)
+ : vkt::TestCase (testContext, name, description)
+ , m_imageViewType (imageViewType)
+ , m_imageFormat (imageFormat)
+ , m_imageSize (imageSize)
+ , m_samplerLod (samplerLod)
+{
+}
+
+void SamplerTest::initPrograms (SourceCollections& sourceCollections) const
+{
+ std::ostringstream vertexSrc;
+ std::ostringstream fragmentSrc;
+ const char* texCoordSwizzle = DE_NULL;
+ tcu::TextureFormat format = (isCompressedFormat(m_imageFormat)) ? tcu::getUncompressedFormat(mapVkCompressedFormat(m_imageFormat))
+ : mapVkFormat(m_imageFormat);
+ const tcu::TextureFormatInfo formatInfo = tcu::getTextureFormatInfo(format);
+
+ switch (m_imageViewType)
+ {
+ case VK_IMAGE_VIEW_TYPE_1D:
+ texCoordSwizzle = "x";
+ break;
+ case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
+ case VK_IMAGE_VIEW_TYPE_2D:
+ texCoordSwizzle = "xy";
+ break;
+ case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
+ case VK_IMAGE_VIEW_TYPE_3D:
+ case VK_IMAGE_VIEW_TYPE_CUBE:
+ texCoordSwizzle = "xyz";
+ break;
+ case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
+ texCoordSwizzle = "xyzw";
+ break;
+ default:
+ DE_ASSERT(false);
+ break;
+ }
+
+ vertexSrc << "#version 440\n"
+ << "layout(location = 0) in vec4 position;\n"
+ << "layout(location = 1) in vec4 texCoords;\n"
+ << "layout(location = 0) out highp vec4 vtxTexCoords;\n"
+ << "out gl_PerVertex {\n"
+ << " vec4 gl_Position;\n"
+ << "};\n"
+ << "void main (void)\n"
+ << "{\n"
+ << " gl_Position = position;\n"
+ << " vtxTexCoords = texCoords;\n"
+ << "}\n";
+
+ fragmentSrc << "#version 440\n"
+ << "layout(set = 0, binding = 0) uniform highp " << getGlslSamplerType(format, m_imageViewType) << " texSampler;\n"
+ << "layout(location = 0) in highp vec4 vtxTexCoords;\n"
+ << "layout(location = 0) out highp vec4 fragColor;\n"
+ << "void main (void)\n"
+ << "{\n"
+ << " fragColor = ";
+
+ if (m_samplerLod > 0.0f)
+ fragmentSrc << "textureLod(texSampler, vtxTexCoords." << texCoordSwizzle << ", " << std::fixed << m_samplerLod << ")";
+ else
+ fragmentSrc << "texture(texSampler, vtxTexCoords." << texCoordSwizzle << ")" << std::fixed;
+
+ fragmentSrc << " * vec4" << std::scientific << formatInfo.lookupScale << " + vec4" << formatInfo.lookupBias << ";\n"
+ << "}\n";
+
+ sourceCollections.glslSources.add("tex_vert") << glu::VertexSource(vertexSrc.str());
+ sourceCollections.glslSources.add("tex_frag") << glu::FragmentSource(fragmentSrc.str());
+}
+
+TestInstance* SamplerTest::createInstance (Context& context) const
+{
+ const tcu::IVec2 renderSize = getRenderSize(m_imageViewType);
+ const std::vector<Vertex4Tex4> vertices = createVertices();
+ const VkSamplerCreateInfo samplerParams = getSamplerCreateInfo();
+ const VkComponentMapping componentMapping = getFormatComponentMapping(m_imageFormat);
+ const VkImageSubresourceRange subresourceRange =
+ {
+ VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
+ 0u, // deUint32 baseMipLevel;
+ (deUint32)deLog2Floor32(m_imageSize) + 1, // deUint32 mipLevels;
+ 0u, // deUint32 baseArrayLayer;
+ (deUint32)SamplerTest::getArraySize(m_imageViewType) // deUint32 arraySize;
+ };
+
+
+
+ return new ImageSamplingInstance(context, renderSize, m_imageViewType, m_imageFormat,
+ getImageSize(m_imageViewType, m_imageSize),
+ getArraySize(m_imageViewType),
+ componentMapping, subresourceRange,
+ samplerParams, m_samplerLod,vertices);
+}
+
+tcu::IVec2 SamplerTest::getRenderSize (VkImageViewType viewType) const
+{
+ if (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_2D)
+ {
+ return tcu::IVec2(16, 16);
+ }
+ else
+ {
+ return tcu::IVec2(16 * 3, 16 * 2);
+ }
+}
+
+std::vector<Vertex4Tex4> SamplerTest::createVertices (void) const
+{
+ return createTestQuadMosaic(m_imageViewType);
+}
+
+VkSamplerCreateInfo SamplerTest::getSamplerCreateInfo (void) const
+{
+ const VkSamplerCreateInfo defaultSamplerParams =
+ {
+ VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkSamplerCreateFlags flags;
+ VK_FILTER_NEAREST, // VkFilter magFilter;
+ VK_FILTER_NEAREST, // VkFilter minFilter;
+ VK_SAMPLER_MIPMAP_MODE_BASE, // VkSamplerMipmapMode mipmapMode;
+ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeU;
+ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeV;
+ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeW;
+ 0.0f, // float mipLodBias;
+ 1.0f, // float maxAnisotropy;
+ false, // VkBool32 compareEnable;
+ VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
+ 0.0f, // float minLod;
+ (float)deLog2Floor32(m_imageSize) + 1, // float maxLod;
+ getFormatBorderColor(BORDER_COLOR_TRANSPARENT_BLACK, m_imageFormat), // VkBorderColor borderColor;
+ false // VkBool32 unnormalizedCoordinates;
+ };
+
+ return defaultSamplerParams;
+}
+
+std::string SamplerTest::getGlslSamplerType (const tcu::TextureFormat& format, VkImageViewType type)
+{
+ std::ostringstream samplerType;
+
+ if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
+ samplerType << "u";
+ else if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
+ samplerType << "i";
+
+ switch (type)
+ {
+ case VK_IMAGE_VIEW_TYPE_1D:
+ samplerType << "sampler1D";
+ break;
+
+ case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
+ samplerType << "sampler1DArray";
+ break;
+
+ case VK_IMAGE_VIEW_TYPE_2D:
+ samplerType << "sampler2D";
+ break;
+
+ case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
+ samplerType << "sampler2DArray";
+ break;
+
+ case VK_IMAGE_VIEW_TYPE_3D:
+ samplerType << "sampler3D";
+ break;
+
+ case VK_IMAGE_VIEW_TYPE_CUBE:
+ samplerType << "samplerCube";
+ break;
+
+ case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
+ samplerType << "samplerCubeArray";
+ break;
+
+ default:
+ DE_FATAL("Unknown image view type");
+ break;
+ }
+
+ return samplerType.str();
+}
+
+tcu::IVec3 SamplerTest::getImageSize (VkImageViewType viewType, int size)
+{
+ switch (viewType)
+ {
+ case VK_IMAGE_VIEW_TYPE_1D:
+ case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
+ return tcu::IVec3(size, 1, 1);
+
+ case VK_IMAGE_VIEW_TYPE_3D:
+ return tcu::IVec3(size, size, 4);
+
+ default:
+ break;
+ }
+
+ return tcu::IVec3(size, size, 1);
+}
+
+int SamplerTest::getArraySize (VkImageViewType viewType)
+{
+ switch (viewType)
+ {
+ case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
+ case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
+ case VK_IMAGE_VIEW_TYPE_CUBE:
+ return 6;
+
+ case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
+ return 36;
+
+ default:
+ break;
+ }
+
+ return 1;
+}
+
+
+// SamplerMagFilterTest
+
+SamplerMagFilterTest::SamplerMagFilterTest (tcu::TestContext& testContext,
+ const char* name,
+ const char* description,
+ VkImageViewType imageViewType,
+ VkFormat imageFormat,
+ VkFilter magFilter)
+ : SamplerTest (testContext, name, description, imageViewType, imageFormat, 8, 0.0f)
+ , m_magFilter (magFilter)
+{
+}
+
+VkSamplerCreateInfo SamplerMagFilterTest::getSamplerCreateInfo (void) const
+{
+ VkSamplerCreateInfo samplerParams = SamplerTest::getSamplerCreateInfo();
+ samplerParams.magFilter = m_magFilter;
+
+ return samplerParams;
+}
+
+
+// SamplerMinFilterTest
+
+SamplerMinFilterTest::SamplerMinFilterTest (tcu::TestContext& testContext,
+ const char* name,
+ const char* description,
+ VkImageViewType imageViewType,
+ VkFormat imageFormat,
+ VkFilter minFilter)
+ : SamplerTest (testContext, name, description, imageViewType, imageFormat, 32, 0.0f)
+ , m_minFilter (minFilter)
+{
+}
+
+VkSamplerCreateInfo SamplerMinFilterTest::getSamplerCreateInfo (void) const
+{
+ VkSamplerCreateInfo samplerParams = SamplerTest::getSamplerCreateInfo();
+ samplerParams.minFilter = m_minFilter;
+
+ return samplerParams;
+}
+
+
+// SamplerLodTest
+
+SamplerLodTest::SamplerLodTest (tcu::TestContext& testContext,
+ const char* name,
+ const char* description,
+ VkImageViewType imageViewType,
+ VkFormat imageFormat,
+ VkSamplerMipmapMode mipmapMode,
+ float minLod,
+ float maxLod,
+ float mipLodBias,
+ float samplerLod)
+ : SamplerTest (testContext, name, description, imageViewType, imageFormat, 32, samplerLod)
+ , m_mipmapMode (mipmapMode)
+ , m_minLod (minLod)
+ , m_maxLod (maxLod)
+ , m_mipLodBias (mipLodBias)
+{
+}
+
+VkSamplerCreateInfo SamplerLodTest::getSamplerCreateInfo (void) const
+{
+ VkSamplerCreateInfo samplerParams = SamplerTest::getSamplerCreateInfo();
+
+ samplerParams.mipmapMode = m_mipmapMode;
+ samplerParams.minLod = m_minLod;
+ samplerParams.maxLod = m_maxLod;
+ samplerParams.mipLodBias = m_mipLodBias;
+
+ return samplerParams;
+}
+
+
+// SamplerAddressModesTest
+
+SamplerAddressModesTest::SamplerAddressModesTest (tcu::TestContext& testContext,
+ const char* name,
+ const char* description,
+ VkImageViewType imageViewType,
+ VkFormat imageFormat,
+ VkSamplerAddressMode addressU,
+ VkSamplerAddressMode addressV,
+ VkSamplerAddressMode addressW,
+ VkBorderColor borderColor)
+ : SamplerTest (testContext, name, description, imageViewType, imageFormat, 8, 0.0f)
+ , m_addressU (addressU)
+ , m_addressV (addressV)
+ , m_addressW (addressW)
+ , m_borderColor (borderColor)
+{
+}
+
+tcu::IVec2 SamplerAddressModesTest::getRenderSize (VkImageViewType viewType) const
+{
+ return 4 * SamplerTest::getRenderSize(viewType);
+}
+
+std::vector<Vertex4Tex4> SamplerAddressModesTest::createVertices (void) const
+{
+ std::vector<Vertex4Tex4> vertices = SamplerTest::createVertices();
+
+ switch (m_imageViewType)
+ {
+ case VK_IMAGE_VIEW_TYPE_1D: case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
+ for (size_t vertexNdx = 0; vertexNdx < vertices.size(); vertexNdx++)
+ vertices[vertexNdx].texCoord.x() = (vertices[vertexNdx].texCoord.x() - 0.5f) * 4.0f;
+
+ break;
+
+ case VK_IMAGE_VIEW_TYPE_2D:
+ case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
+ for (size_t vertexNdx = 0; vertexNdx < vertices.size(); vertexNdx++)
+ vertices[vertexNdx].texCoord.xy() = (vertices[vertexNdx].texCoord.swizzle(0, 1) - tcu::Vec2(0.5f)) * 4.0f;
+
+ break;
+
+ case VK_IMAGE_VIEW_TYPE_3D:
+ for (size_t vertexNdx = 0; vertexNdx < vertices.size(); vertexNdx++)
+ vertices[vertexNdx].texCoord.xyz() = (vertices[vertexNdx].texCoord.swizzle(0, 1, 2) - tcu::Vec3(0.5f)) * 4.0f;
+
+ break;
+
+ case VK_IMAGE_VIEW_TYPE_CUBE:
+ case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
+ break;
+
+ default:
+ DE_ASSERT(false);
+ }
+
+ return vertices;
+}
+
+VkSamplerCreateInfo SamplerAddressModesTest::getSamplerCreateInfo (void) const
+{
+ VkSamplerCreateInfo samplerParams = SamplerTest::getSamplerCreateInfo();
+ samplerParams.addressModeU = m_addressU;
+ samplerParams.addressModeV = m_addressV;
+ samplerParams.addressModeW = m_addressW;
+ samplerParams.borderColor = m_borderColor;
+
+ return samplerParams;
+}
+
+
+// Utilities to create test nodes
+
+std::string getFormatCaseName (const VkFormat format)
+{
+ const std::string fullName = getFormatName(format);
+
+ DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_"));
+
+ return de::toLower(fullName.substr(10));
+}
+
+MovePtr<tcu::TestCaseGroup> createSamplerMagFilterTests (tcu::TestContext& testCtx, VkImageViewType imageViewType, VkFormat imageFormat)
+{
+ MovePtr<tcu::TestCaseGroup> samplerMagFilterTests (new tcu::TestCaseGroup(testCtx, "mag_filter", "Tests for magnification filter"));
+
+ samplerMagFilterTests->addChild(new SamplerMagFilterTest(testCtx, "linear", "Magnifies image using VK_TEX_FILTER_LINEAR", imageViewType, imageFormat, VK_FILTER_LINEAR));
+ samplerMagFilterTests->addChild(new SamplerMagFilterTest(testCtx, "nearest", "Magnifies image using VK_TEX_FILTER_NEAREST", imageViewType, imageFormat, VK_FILTER_NEAREST));
+
+ return samplerMagFilterTests;
+}
+
+MovePtr<tcu::TestCaseGroup> createSamplerMinFilterTests (tcu::TestContext& testCtx, VkImageViewType imageViewType, VkFormat imageFormat)
+{
+ MovePtr<tcu::TestCaseGroup> samplerMinFilterTests (new tcu::TestCaseGroup(testCtx, "min_filter", "Tests for minification filter"));
+
+ samplerMinFilterTests->addChild(new SamplerMinFilterTest(testCtx, "linear", "Minifies image using VK_TEX_FILTER_LINEAR", imageViewType, imageFormat, VK_FILTER_LINEAR));
+ samplerMinFilterTests->addChild(new SamplerMinFilterTest(testCtx, "nearest", "Minifies image using VK_TEX_FILTER_NEAREST", imageViewType, imageFormat, VK_FILTER_NEAREST));
+
+ return samplerMinFilterTests;
+}
+
+MovePtr<tcu::TestCaseGroup> createSamplerLodTests (tcu::TestContext& testCtx, VkImageViewType imageViewType, VkFormat imageFormat, VkSamplerMipmapMode mipmapMode)
+{
+ struct TestCaseConfig
+ {
+ const char* name;
+ const char* description;
+ float minLod;
+ float maxLod;
+ float mipLodBias;
+ float lod;
+ };
+
+ TestCaseConfig testCaseConfigs [] =
+ {
+ { "equal_min_3_max_3", "minLod = 3, maxLod = 3, mipLodBias = 0, lod = 0", 3.0f, 3.0f, 0.0f, 0.0f },
+ { "select_min_1", "minLod = 1, maxLod = 5, mipLodBias = 0, lod = 0", 1.0f, 5.0f, 0.0f, 0.0f },
+ { "select_max_4", "minLod = 0, maxLod = 4, mipLodBias = 0, lod = 5", 0.0f, 4.0f, 0.0f, 5.0f },
+ { "select_bias_2_1", "minLod = 0, maxLod = 2.1, mipLodBias = 5.0, lod = 0", 0.0f, 2.1f, 5.0f, 0.0f },
+ { "select_bias_2_5", "minLod = 0, maxLod = 5, mipLodBias = 2.5, lod = 0", 0.0f, 5.0f, 2.5f, 0.00001f },
+ { "select_bias_3_1", "minLod = 0, maxLod = 5, mipLodBias = -0.9, lod = 4.0", 0.0f, 5.0f, -0.9f, 4.0f },
+ { "select_bias_3_7", "minLod = 0, maxLod = 5, mipLodBias = 3.0, lod = 0.7", 0.0f, 5.0f, 3.0f, 0.7f },
+ };
+
+ MovePtr<tcu::TestCaseGroup> samplerLodTests (new tcu::TestCaseGroup(testCtx, "lod", "Tests for sampler LOD"));
+
+ for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(testCaseConfigs); configNdx++)
+ {
+ const TestCaseConfig& config = testCaseConfigs[configNdx];
+
+ samplerLodTests->addChild(new SamplerLodTest(testCtx, config.name, config.description, imageViewType, imageFormat, mipmapMode, config.minLod, config.maxLod, config.mipLodBias, config.lod));
+ }
+
+ return samplerLodTests;
+}
+
+MovePtr<tcu::TestCaseGroup> createSamplerMipmapTests (tcu::TestContext& testCtx, VkImageViewType imageViewType, VkFormat imageFormat)
+{
+ MovePtr<tcu::TestCaseGroup> samplerMipmapTests (new tcu::TestCaseGroup(testCtx, "mipmap", "Tests for mipmap modes"));
+
+ // Mipmap mode: nearest
+ MovePtr<tcu::TestCaseGroup> mipmapNearestTests (new tcu::TestCaseGroup(testCtx, "nearest", "Uses VK_TEX_MIPMAP_MODE_NEAREST"));
+ mipmapNearestTests->addChild(createSamplerLodTests(testCtx, imageViewType, imageFormat, VK_SAMPLER_MIPMAP_MODE_NEAREST).release());
+ samplerMipmapTests->addChild(mipmapNearestTests.release());
+
+ // Mipmap mode: linear
+ MovePtr<tcu::TestCaseGroup> mipmapLinearTests (new tcu::TestCaseGroup(testCtx, "linear", "Uses VK_TEX_MIPMAP_MODE_LINEAR"));
+ mipmapLinearTests->addChild(createSamplerLodTests(testCtx, imageViewType, imageFormat, VK_SAMPLER_MIPMAP_MODE_LINEAR).release());
+ samplerMipmapTests->addChild(mipmapLinearTests.release());
+
+ return samplerMipmapTests;
+}
+
+std::string getAddressModesCaseName (VkSamplerAddressMode u, VkSamplerAddressMode v, VkSamplerAddressMode w, BorderColor border)
+{
+ static const char* borderColorNames[BORDER_COLOR_COUNT] =
+ {
+ "opaque_black",
+ "opaque_white",
+ "transparent_black",
+ };
+
+ std::ostringstream caseName;
+
+ if (u == v && v == w)
+ {
+ const std::string fullName = getSamplerAddressModeName(u);
+ DE_ASSERT(de::beginsWith(fullName, "VK_SAMPLER_ADDRESS_"));
+
+ caseName << "all_";
+ caseName << de::toLower(fullName.substr(19));
+
+ if (u == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER)
+ {
+ caseName << "_" << borderColorNames[border];
+ }
+ }
+ else
+ {
+ const std::string fullNameU = getSamplerAddressModeName(u);
+ const std::string fullNameV = getSamplerAddressModeName(v);
+ const std::string fullNameW = getSamplerAddressModeName(w);
+
+ DE_ASSERT(de::beginsWith(fullNameU, "VK_SAMPLER_ADDRESS_"));
+ DE_ASSERT(de::beginsWith(fullNameV, "VK_SAMPLER_ADDRESS_"));
+ DE_ASSERT(de::beginsWith(fullNameW, "VK_SAMPLER_ADDRESS_"));
+
+ caseName << "uvw"
+ << "_" << de::toLower(fullNameU.substr(19))
+ << "_" << de::toLower(fullNameV.substr(19))
+ << "_" << de::toLower(fullNameW.substr(19));
+ }
+
+ return caseName.str();
+}
+
+MovePtr<tcu::TestCaseGroup> createSamplerAddressModesTests (tcu::TestContext& testCtx, VkImageViewType imageViewType, VkFormat imageFormat)
+{
+ struct TestCaseConfig
+ {
+ VkSamplerAddressMode u;
+ VkSamplerAddressMode v;
+ VkSamplerAddressMode w;
+ BorderColor border;
+ };
+
+ const TestCaseConfig testCaseConfigs[] =
+ {
+ // All address modes equal
+ { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, BORDER_COLOR_TRANSPARENT_BLACK },
+ { VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, BORDER_COLOR_TRANSPARENT_BLACK },
+ { VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, BORDER_COLOR_TRANSPARENT_BLACK },
+ { VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, BORDER_COLOR_TRANSPARENT_BLACK },
+
+ // All address modes equal using border color
+ { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_TRANSPARENT_BLACK },
+ { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_OPAQUE_BLACK },
+ { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_OPAQUE_WHITE },
+
+ // Pairwise combinations of address modes not covered by previous tests
+ { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_REPEAT, BORDER_COLOR_OPAQUE_WHITE},
+ { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE },
+ { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, BORDER_COLOR_OPAQUE_WHITE },
+ { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE },
+ { VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, BORDER_COLOR_OPAQUE_WHITE },
+ { VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_OPAQUE_WHITE },
+ { VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, BORDER_COLOR_OPAQUE_WHITE },
+ { VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE },
+ { VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE },
+ { VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE },
+ { VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE },
+ { VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_OPAQUE_WHITE },
+ { VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_REPEAT, BORDER_COLOR_OPAQUE_WHITE },
+ { VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE },
+ { VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_OPAQUE_WHITE },
+ { VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, BORDER_COLOR_OPAQUE_WHITE },
+ { VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE },
+ { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_OPAQUE_WHITE },
+ { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_REPEAT, BORDER_COLOR_OPAQUE_WHITE },
+ { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE },
+ { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE },
+ { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, BORDER_COLOR_OPAQUE_WHITE },
+ };
+
+ MovePtr<tcu::TestCaseGroup> samplerAddressModesTests (new tcu::TestCaseGroup(testCtx, "address_modes", "Tests for address modes"));
+
+ for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(testCaseConfigs); configNdx++)
+ {
+ const TestCaseConfig& config = testCaseConfigs[configNdx];
+
+ samplerAddressModesTests->addChild(new SamplerAddressModesTest(testCtx,
+ getAddressModesCaseName(config.u, config.v, config.w, config.border).c_str(),
+ "",
+ imageViewType,
+ imageFormat,
+ config.u, config.v, config.w,
+ getFormatBorderColor(config.border, imageFormat)));
+ }
+
+ return samplerAddressModesTests;
+}
+
+} // anonymous
+
+tcu::TestCaseGroup* createSamplerTests (tcu::TestContext& testCtx)
+{
+ const struct
+ {
+ VkImageViewType type;
+ const char* name;
+ }
+ imageViewTypes[] =
+ {
+ { VK_IMAGE_VIEW_TYPE_1D, "1d" },
+ { VK_IMAGE_VIEW_TYPE_1D_ARRAY, "1d_array" },
+ { VK_IMAGE_VIEW_TYPE_2D, "2d" },
+ { VK_IMAGE_VIEW_TYPE_2D_ARRAY, "2d_array" },
+ { VK_IMAGE_VIEW_TYPE_3D, "3d" },
+ { VK_IMAGE_VIEW_TYPE_CUBE, "cube" },
+ { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, "cube_array" }
+ };
+
+ const VkFormat formats[] =
+ {
+ // Packed formats
+ VK_FORMAT_R4G4_UNORM_PACK8,
+ VK_FORMAT_R4G4B4A4_UNORM_PACK16,
+ VK_FORMAT_R5G6B5_UNORM_PACK16,
+ VK_FORMAT_R5G5B5A1_UNORM_PACK16,
+ VK_FORMAT_A2B10G10R10_UNORM_PACK32,
+ VK_FORMAT_A2R10G10B10_UINT_PACK32,
+ VK_FORMAT_B10G11R11_UFLOAT_PACK32,
+ VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
+ VK_FORMAT_B4G4R4A4_UNORM_PACK16,
+ VK_FORMAT_B5G5R5A1_UNORM_PACK16,
+
+ // Pairwise combinations of 8-bit channel formats, UNORM/SNORM/SINT/UINT/SRGB type x 1-to-4 channels x RGBA/BGRA order
+ VK_FORMAT_R8_SRGB,
+ VK_FORMAT_R8G8B8_UINT,
+ VK_FORMAT_B8G8R8A8_SINT,
+ VK_FORMAT_R8G8_UNORM,
+ VK_FORMAT_B8G8R8_SNORM,
+ VK_FORMAT_R8G8B8A8_SNORM,
+ VK_FORMAT_R8G8_UINT,
+ VK_FORMAT_R8_SINT,
+ VK_FORMAT_R8G8B8A8_SRGB,
+ VK_FORMAT_R8G8B8A8_UNORM,
+ VK_FORMAT_B8G8R8A8_UNORM,
+ VK_FORMAT_B8G8R8_SRGB,
+ VK_FORMAT_R8G8_SRGB,
+ VK_FORMAT_R8_UINT,
+ VK_FORMAT_R8G8B8A8_UINT,
+ VK_FORMAT_R8G8_SINT,
+ VK_FORMAT_R8_SNORM,
+ VK_FORMAT_B8G8R8_SINT,
+ VK_FORMAT_R8G8_SNORM,
+ VK_FORMAT_B8G8R8_UNORM,
+ VK_FORMAT_R8_UNORM,
+
+ // Pairwise combinations of 16/32-bit channel formats x SINT/UINT/SFLOAT type x 1-to-4 channels
+ VK_FORMAT_R32G32_SFLOAT,
+ VK_FORMAT_R32G32B32_UINT,
+ VK_FORMAT_R16G16B16A16_SFLOAT,
+ VK_FORMAT_R16G16_UINT,
+ VK_FORMAT_R32G32B32A32_SINT,
+ VK_FORMAT_R16G16B16_SINT,
+ VK_FORMAT_R16_SFLOAT,
+ VK_FORMAT_R32_SINT,
+ VK_FORMAT_R32_UINT,
+ VK_FORMAT_R16G16B16_SFLOAT,
+ VK_FORMAT_R16G16_SINT,
+
+ // Scaled formats
+ VK_FORMAT_R8G8B8A8_SSCALED,
+ VK_FORMAT_A2R10G10B10_USCALED_PACK32,
+
+ // Compressed formats
+ VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,
+ VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK,
+ VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK,
+ VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK,
+ VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK,
+ VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK,
+ VK_FORMAT_EAC_R11_UNORM_BLOCK,
+ VK_FORMAT_EAC_R11_SNORM_BLOCK,
+ VK_FORMAT_EAC_R11G11_UNORM_BLOCK,
+ VK_FORMAT_EAC_R11G11_SNORM_BLOCK,
+ VK_FORMAT_ASTC_4x4_UNORM_BLOCK,
+ VK_FORMAT_ASTC_5x4_SRGB_BLOCK,
+ VK_FORMAT_ASTC_6x5_UNORM_BLOCK,
+ VK_FORMAT_ASTC_6x6_SRGB_BLOCK,
+ VK_FORMAT_ASTC_8x6_UNORM_BLOCK,
+ VK_FORMAT_ASTC_8x8_SRGB_BLOCK,
+ VK_FORMAT_ASTC_10x6_UNORM_BLOCK,
+ VK_FORMAT_ASTC_10x8_SRGB_BLOCK,
+ VK_FORMAT_ASTC_12x10_UNORM_BLOCK,
+ VK_FORMAT_ASTC_12x12_SRGB_BLOCK,
+ };
+
+ de::MovePtr<tcu::TestCaseGroup> samplerTests (new tcu::TestCaseGroup(testCtx, "sampler", "Sampler tests"));
+ de::MovePtr<tcu::TestCaseGroup> viewTypeTests (new tcu::TestCaseGroup(testCtx, "view_type", ""));
+
+ for (int viewTypeNdx = 0; viewTypeNdx < DE_LENGTH_OF_ARRAY(imageViewTypes); viewTypeNdx++)
+ {
+ const VkImageViewType viewType = imageViewTypes[viewTypeNdx].type;
+ de::MovePtr<tcu::TestCaseGroup> viewTypeGroup (new tcu::TestCaseGroup(testCtx, imageViewTypes[viewTypeNdx].name, (std::string("Uses a ") + imageViewTypes[viewTypeNdx].name + " view").c_str()));
+ de::MovePtr<tcu::TestCaseGroup> formatTests (new tcu::TestCaseGroup(testCtx, "format", "Tests samplable formats"));
+
+ for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
+ {
+ const VkFormat format = formats[formatNdx];
+ const bool isCompressed = isCompressedFormat(format);
+
+ if (isCompressed && (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_1D_ARRAY))
+ {
+ // Do not use compressed formats with 1D and 1D array textures.
+ break;
+ }
+
+ de::MovePtr<tcu::TestCaseGroup> formatGroup (new tcu::TestCaseGroup(testCtx,
+ getFormatCaseName(format).c_str(),
+ (std::string("Samples a texture of format ") + getFormatName(format)).c_str()));
+
+ if (!isCompressed)
+ {
+ // Do not include minFilter tests with compressed formats.
+ // Randomly generated compressed textures are too noisy and will derive in false positives.
+ de::MovePtr<tcu::TestCaseGroup> minFilterTests = createSamplerMinFilterTests(testCtx, viewType, format);
+ formatGroup->addChild(minFilterTests.release());
+ }
+
+ de::MovePtr<tcu::TestCaseGroup> magFilterTests = createSamplerMagFilterTests(testCtx, viewType, format);
+ de::MovePtr<tcu::TestCaseGroup> mipmapTests = createSamplerMipmapTests(testCtx, viewType, format);
+
+ formatGroup->addChild(magFilterTests.release());
+ formatGroup->addChild(mipmapTests.release());
+
+ if (viewType != VK_IMAGE_VIEW_TYPE_CUBE && viewType != VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
+ {
+ de::MovePtr<tcu::TestCaseGroup> addressModesTests = createSamplerAddressModesTests(testCtx, viewType, format);
+ formatGroup->addChild(addressModesTests.release());
+ }
+
+ formatTests->addChild(formatGroup.release());
+ }
+
+ viewTypeGroup->addChild(formatTests.release());
+ viewTypeTests->addChild(viewTypeGroup.release());
+ }
+
+ samplerTests->addChild(viewTypeTests.release());
+
+ return samplerTests.release();
+}
+
+} // pipeline
+} // vkt
--- /dev/null
+#ifndef _VKTPIPELINESAMPLERTESTS_HPP
+#define _VKTPIPELINESAMPLERTESTS_HPP
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Imagination Technologies Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by Khronos,
+ * at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Sampler Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktTestCase.hpp"
+
+namespace vkt
+{
+namespace pipeline
+{
+
+tcu::TestCaseGroup* createSamplerTests (tcu::TestContext& testCtx);
+
+} // pipeline
+} // vkt
+
+#endif // _VKTPIPELINESAMPLERTESTS_HPP
--- /dev/null
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Imagination Technologies Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by Khronos,
+ * at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Stencil Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktPipelineStencilTests.hpp"
+#include "vktPipelineClearUtil.hpp"
+#include "vktPipelineImageUtil.hpp"
+#include "vktPipelineVertexUtil.hpp"
+#include "vktPipelineReferenceRenderer.hpp"
+#include "vktPipelineUniqueRandomIterator.hpp"
+#include "vktTestCase.hpp"
+#include "vkImageUtil.hpp"
+#include "vkMemUtil.hpp"
+#include "vkPrograms.hpp"
+#include "vkQueryUtil.hpp"
+#include "vkRef.hpp"
+#include "vkRefUtil.hpp"
+#include "tcuImageCompare.hpp"
+#include "deMemory.h"
+#include "deRandom.hpp"
+#include "deStringUtil.hpp"
+#include "deUniquePtr.hpp"
+
+#include <algorithm>
+#include <sstream>
+#include <vector>
+
+namespace vkt
+{
+namespace pipeline
+{
+
+using namespace vk;
+
+namespace
+{
+
+bool isSupportedDepthStencilFormat (const InstanceInterface& instanceInterface, VkPhysicalDevice device, VkFormat format)
+{
+ VkFormatProperties formatProps;
+
+ instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
+
+ return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0;
+}
+
+class StencilOpStateUniqueRandomIterator : public UniqueRandomIterator<VkStencilOpState>
+{
+public:
+ StencilOpStateUniqueRandomIterator (int seed);
+ virtual ~StencilOpStateUniqueRandomIterator (void) {}
+ virtual VkStencilOpState getIndexedValue (deUint32 index);
+
+private:
+ const static VkStencilOp m_stencilOps[];
+ const static VkCompareOp m_compareOps[];
+
+ // Pre-calculated constants
+ const static deUint32 m_stencilOpsLength;
+ const static deUint32 m_stencilOpsLength2;
+ const static deUint32 m_stencilOpsLength3;
+ const static deUint32 m_compareOpsLength;
+
+ // Total number of cross-combinations of (stencilFailOp x stencilPassOp x stencilDepthFailOp x stencilCompareOp)
+ const static deUint32 m_totalStencilOpStates;
+};
+
+
+class StencilTest : public vkt::TestCase
+{
+public:
+ enum
+ {
+ QUAD_COUNT = 4
+ };
+
+ struct StencilStateConfig
+ {
+ deUint32 frontReadMask;
+ deUint32 frontWriteMask;
+ deUint32 frontRef;
+
+ deUint32 backReadMask;
+ deUint32 backWriteMask;
+ deUint32 backRef;
+ };
+
+ const static StencilStateConfig s_stencilStateConfigs[QUAD_COUNT];
+ const static float s_quadDepths[QUAD_COUNT];
+
+
+ StencilTest (tcu::TestContext& testContext,
+ const std::string& name,
+ const std::string& description,
+ VkFormat stencilFormat,
+ const VkStencilOpState& stencilOpStateFront,
+ const VkStencilOpState& stencilOpStateBack);
+ virtual ~StencilTest (void);
+ virtual void initPrograms (SourceCollections& sourceCollections) const;
+ virtual TestInstance* createInstance (Context& context) const;
+
+private:
+ VkFormat m_stencilFormat;
+ const VkStencilOpState m_stencilOpStateFront;
+ const VkStencilOpState m_stencilOpStateBack;
+};
+
+class StencilTestInstance : public vkt::TestInstance
+{
+public:
+ StencilTestInstance (Context& context,
+ VkFormat stencilFormat,
+ const VkStencilOpState& stencilOpStatesFront,
+ const VkStencilOpState& stencilOpStatesBack);
+ virtual ~StencilTestInstance (void);
+ virtual tcu::TestStatus iterate (void);
+
+private:
+ tcu::TestStatus verifyImage (void);
+
+ VkStencilOpState m_stencilOpStateFront;
+ VkStencilOpState m_stencilOpStateBack;
+ const tcu::IVec2 m_renderSize;
+ const VkFormat m_colorFormat;
+ const VkFormat m_stencilFormat;
+
+ VkImageCreateInfo m_colorImageCreateInfo;
+ Move<VkImage> m_colorImage;
+ de::MovePtr<Allocation> m_colorImageAlloc;
+ Move<VkImage> m_stencilImage;
+ de::MovePtr<Allocation> m_stencilImageAlloc;
+ Move<VkImageView> m_colorAttachmentView;
+ Move<VkImageView> m_stencilAttachmentView;
+ Move<VkRenderPass> m_renderPass;
+ Move<VkFramebuffer> m_framebuffer;
+
+ Move<VkShaderModule> m_vertexShaderModule;
+ Move<VkShaderModule> m_fragmentShaderModule;
+
+ Move<VkBuffer> m_vertexBuffer;
+ std::vector<Vertex4RGBA> m_vertices;
+ de::MovePtr<Allocation> m_vertexBufferAlloc;
+
+ Move<VkPipelineLayout> m_pipelineLayout;
+ Move<VkPipeline> m_graphicsPipelines[StencilTest::QUAD_COUNT];
+
+ Move<VkCommandPool> m_cmdPool;
+ Move<VkCommandBuffer> m_cmdBuffer;
+
+ Move<VkFence> m_fence;
+};
+
+
+// StencilOpStateUniqueRandomIterator
+
+const VkStencilOp StencilOpStateUniqueRandomIterator::m_stencilOps[] =
+{
+ VK_STENCIL_OP_KEEP,
+ VK_STENCIL_OP_ZERO,
+ VK_STENCIL_OP_REPLACE,
+ VK_STENCIL_OP_INCREMENT_AND_CLAMP,
+ VK_STENCIL_OP_DECREMENT_AND_CLAMP,
+ VK_STENCIL_OP_INVERT,
+ VK_STENCIL_OP_INCREMENT_AND_WRAP,
+ VK_STENCIL_OP_DECREMENT_AND_WRAP
+};
+
+const VkCompareOp StencilOpStateUniqueRandomIterator::m_compareOps[] =
+{
+ VK_COMPARE_OP_NEVER,
+ VK_COMPARE_OP_LESS,
+ VK_COMPARE_OP_EQUAL,
+ VK_COMPARE_OP_LESS_OR_EQUAL,
+ VK_COMPARE_OP_GREATER,
+ VK_COMPARE_OP_NOT_EQUAL,
+ VK_COMPARE_OP_GREATER_OR_EQUAL,
+ VK_COMPARE_OP_ALWAYS
+};
+
+const deUint32 StencilOpStateUniqueRandomIterator::m_stencilOpsLength = DE_LENGTH_OF_ARRAY(m_stencilOps);
+const deUint32 StencilOpStateUniqueRandomIterator::m_stencilOpsLength2 = m_stencilOpsLength * m_stencilOpsLength;
+const deUint32 StencilOpStateUniqueRandomIterator::m_stencilOpsLength3 = m_stencilOpsLength2 * m_stencilOpsLength;
+const deUint32 StencilOpStateUniqueRandomIterator::m_compareOpsLength = DE_LENGTH_OF_ARRAY(m_compareOps);
+const deUint32 StencilOpStateUniqueRandomIterator::m_totalStencilOpStates = m_stencilOpsLength3 * m_compareOpsLength;
+
+StencilOpStateUniqueRandomIterator::StencilOpStateUniqueRandomIterator (int seed)
+ : UniqueRandomIterator<VkStencilOpState>(m_totalStencilOpStates, m_totalStencilOpStates, seed)
+{
+}
+
+VkStencilOpState StencilOpStateUniqueRandomIterator::getIndexedValue (deUint32 index)
+{
+ const deUint32 stencilCompareOpIndex = index / m_stencilOpsLength3;
+ const deUint32 stencilCompareOpSeqIndex = stencilCompareOpIndex * m_stencilOpsLength3;
+
+ const deUint32 stencilDepthFailOpIndex = (index - stencilCompareOpSeqIndex) / m_stencilOpsLength2;
+ const deUint32 stencilDepthFailOpSeqIndex = stencilDepthFailOpIndex * m_stencilOpsLength2;
+
+ const deUint32 stencilPassOpIndex = (index - stencilCompareOpSeqIndex - stencilDepthFailOpSeqIndex) / m_stencilOpsLength;
+ const deUint32 stencilPassOpSeqIndex = stencilPassOpIndex * m_stencilOpsLength;
+
+ const deUint32 stencilFailOpIndex = index - stencilCompareOpSeqIndex - stencilDepthFailOpSeqIndex - stencilPassOpSeqIndex;
+
+ const VkStencilOpState stencilOpState =
+ {
+ m_stencilOps[stencilFailOpIndex], // VkStencilOp failOp;
+ m_stencilOps[stencilPassOpIndex], // VkStencilOp passOp;
+ m_stencilOps[stencilDepthFailOpIndex], // VkStencilOp depthFailOp;
+ m_compareOps[stencilCompareOpIndex], // VkCompareOp compareOp;
+ 0x0, // deUint32 compareMask;
+ 0x0, // deUint32 writeMask;
+ 0x0 // deUint32 reference;
+ };
+
+ return stencilOpState;
+}
+
+
+// StencilTest
+
+const StencilTest::StencilStateConfig StencilTest::s_stencilStateConfigs[QUAD_COUNT] =
+{
+ // frontReadMask frontWriteMask frontRef backReadMask backWriteMask backRef
+ { 0xFF, 0xFF, 0xAB, 0xF0, 0xFF, 0xFF },
+ { 0xFF, 0xF0, 0xCD, 0xF0, 0xF0, 0xEF },
+ { 0xF0, 0x0F, 0xEF, 0xFF, 0x0F, 0xCD },
+ { 0xF0, 0x01, 0xFF, 0xFF, 0x01, 0xAB }
+};
+
+const float StencilTest::s_quadDepths[QUAD_COUNT] =
+{
+ 0.1f,
+ 0.0f,
+ 0.3f,
+ 0.2f
+};
+
+StencilTest::StencilTest (tcu::TestContext& testContext,
+ const std::string& name,
+ const std::string& description,
+ VkFormat stencilFormat,
+ const VkStencilOpState& stencilOpStateFront,
+ const VkStencilOpState& stencilOpStateBack)
+ : vkt::TestCase (testContext, name, description)
+ , m_stencilFormat (stencilFormat)
+ , m_stencilOpStateFront (stencilOpStateFront)
+ , m_stencilOpStateBack (stencilOpStateBack)
+{
+}
+
+StencilTest::~StencilTest (void)
+{
+}
+
+TestInstance* StencilTest::createInstance (Context& context) const
+{
+ return new StencilTestInstance(context, m_stencilFormat, m_stencilOpStateFront, m_stencilOpStateBack);
+}
+
+void StencilTest::initPrograms (SourceCollections& sourceCollections) const
+{
+ sourceCollections.glslSources.add("color_vert") << glu::VertexSource(
+ "#version 310 es\n"
+ "layout(location = 0) in vec4 position;\n"
+ "layout(location = 1) in vec4 color;\n"
+ "layout(location = 0) out highp vec4 vtxColor;\n"
+ "void main (void)\n"
+ "{\n"
+ " gl_Position = position;\n"
+ " vtxColor = color;\n"
+ "}\n");
+
+ sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(
+ "#version 310 es\n"
+ "layout(location = 0) in highp vec4 vtxColor;\n"
+ "layout(location = 0) out highp vec4 fragColor;\n"
+ "void main (void)\n"
+ "{\n"
+ " fragColor = vtxColor;\n"
+ "}\n");
+}
+
+
+// StencilTestInstance
+
+StencilTestInstance::StencilTestInstance (Context& context,
+ VkFormat stencilFormat,
+ const VkStencilOpState& stencilOpStateFront,
+ const VkStencilOpState& stencilOpStateBack)
+ : vkt::TestInstance (context)
+ , m_stencilOpStateFront (stencilOpStateFront)
+ , m_stencilOpStateBack (stencilOpStateBack)
+ , m_renderSize (32, 32)
+ , m_colorFormat (VK_FORMAT_R8G8B8A8_UNORM)
+ , m_stencilFormat (stencilFormat)
+{
+ const DeviceInterface& vk = context.getDeviceInterface();
+ const VkDevice vkDevice = context.getDevice();
+ const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
+ SimpleAllocator memAlloc (vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
+ const VkComponentMapping componentMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
+
+ // Create color image
+ {
+ const VkImageCreateInfo colorImageParams =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkImageCreateFlags flags;
+ VK_IMAGE_TYPE_2D, // VkImageType imageType;
+ m_colorFormat, // VkFormat format;
+ { m_renderSize.x(), m_renderSize.y(), 1u }, // VkExtent3D extent;
+ 1u, // deUint32 mipLevels;
+ 1u, // deUint32 arrayLayers;
+ VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
+ VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
+ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
+ VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
+ 1u, // deUint32 queueFamilyIndexCount;
+ &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
+ VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
+ };
+
+ m_colorImageCreateInfo = colorImageParams;
+ m_colorImage = createImage(vk, vkDevice, &m_colorImageCreateInfo);
+
+ // Allocate and bind color image memory
+ m_colorImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
+ VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
+ }
+
+ // Create stencil image
+ {
+ // Check format support
+ if (!isSupportedDepthStencilFormat(context.getInstanceInterface(), context.getPhysicalDevice(), m_stencilFormat))
+ throw tcu::NotSupportedError(std::string("Unsupported depth/stencil format: ") + getFormatName(m_stencilFormat));
+
+ const VkImageCreateInfo stencilImageParams =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkImageCreateFlags flags;
+ VK_IMAGE_TYPE_2D, // VkImageType imageType;
+ m_stencilFormat, // VkFormat format;
+ { m_renderSize.x(), m_renderSize.y(), 1u }, // VkExtent3D extent;
+ 1u, // deUint32 mipLevels;
+ 1u, // deUint32 arrayLayers;
+ VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
+ VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
+ VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, // VkImageUsageFlags usage;
+ VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
+ 1u, // deUint32 queueFamilyIndexCount;
+ &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
+ VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
+ };
+
+ m_stencilImage = createImage(vk, vkDevice, &stencilImageParams);
+
+ // Allocate and bind stencil image memory
+ m_stencilImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_stencilImage), MemoryRequirement::Any);
+ VK_CHECK(vk.bindImageMemory(vkDevice, *m_stencilImage, m_stencilImageAlloc->getMemory(), m_stencilImageAlloc->getOffset()));
+ }
+
+ // Create color attachment view
+ {
+ const VkImageViewCreateInfo colorAttachmentViewParams =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkImageViewCreateFlags flags;
+ *m_colorImage, // VkImage image;
+ VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
+ m_colorFormat, // VkFormat format;
+ componentMappingRGBA, // VkComponentMapping components;
+ { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange;
+ };
+
+ m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
+ }
+
+ // Create stencil attachment view
+ {
+ const VkImageViewCreateInfo stencilAttachmentViewParams =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkImageViewCreateFlags flags;
+ *m_stencilImage, // VkImage image;
+ VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
+ m_stencilFormat, // VkFormat format;
+ componentMappingRGBA, // VkComponentMapping components;
+ { VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 1u, 0u, 1u }, // VkImageSubresourceRange subresourceRange;
+ };
+
+ m_stencilAttachmentView = createImageView(vk, vkDevice, &stencilAttachmentViewParams);
+ }
+
+ // Create render pass
+ {
+ const VkAttachmentDescription colorAttachmentDescription =
+ {
+ 0u, // VkAttachmentDescriptionFlags flags;
+ m_colorFormat, // VkFormat format;
+ VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
+ VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
+ VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
+ VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
+ VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout;
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
+ };
+
+ const VkAttachmentDescription stencilAttachmentDescription =
+ {
+ 0u, // VkAttachmentDescriptionFlags flags;
+ m_stencilFormat, // VkFormat format;
+ VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
+ VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
+ VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp storeOp;
+ VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp stencilLoadOp;
+ VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout;
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
+ };
+
+ const VkAttachmentDescription attachments[2] =
+ {
+ colorAttachmentDescription,
+ stencilAttachmentDescription
+ };
+
+ const VkAttachmentReference colorAttachmentReference =
+ {
+ 0u, // deUint32 attachment;
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
+ };
+
+ const VkAttachmentReference stencilAttachmentReference =
+ {
+ 1u, // deUint32 attachment;
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL // VkImageLayout layout;
+ };
+
+ const VkSubpassDescription subpassDescription =
+ {
+ 0u, // VkSubpassDescriptionFlags flags;
+ VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
+ 0u, // deUint32 inputAttachmentCount;
+ DE_NULL, // const VkAttachmentReference* pInputAttachments;
+ 1u, // deUint32 colorAttachmentCount;
+ &colorAttachmentReference, // const VkAttachmentReference* pColorAttachments;
+ DE_NULL, // const VkAttachmentReference* pResolveAttachments;
+ &stencilAttachmentReference, // const VkAttachmentReference* pDepthStencilAttachment;
+ 0u, // deUint32 preserveAttachmentCount;
+ DE_NULL // const VkAttachmentReference* pPreserveAttachments;
+ };
+
+ const VkRenderPassCreateInfo renderPassParams =
+ {
+ VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkRenderPassCreateFlags flags;
+ 2u, // deUint32 attachmentCount;
+ attachments, // const VkAttachmentDescription* pAttachments;
+ 1u, // deUint32 subpassCount;
+ &subpassDescription, // const VkSubpassDescription* pSubpasses;
+ 0u, // deUint32 dependencyCount;
+ DE_NULL // const VkSubpassDependency* pDependencies;
+ };
+
+ m_renderPass = createRenderPass(vk, vkDevice, &renderPassParams);
+ }
+
+ // Create framebuffer
+ {
+ const VkImageView attachmentBindInfos[2] = { *m_colorAttachmentView, *m_stencilAttachmentView };
+
+ const VkFramebufferCreateInfo framebufferParams =
+ {
+ VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkFramebufferCreateFlags flags;
+ *m_renderPass, // VkRenderPass renderPass;
+ 2u, // deUint32 attachmentCount;
+ attachmentBindInfos, // const VkImageView* pAttachments;
+ (deUint32)m_renderSize.x(), // deUint32 width;
+ (deUint32)m_renderSize.y(), // deUint32 height;
+ 1u // deUint32 layers;
+ };
+
+ m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
+ }
+
+ // Create pipeline layout
+ {
+ const VkPipelineLayoutCreateInfo pipelineLayoutParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineLayoutCreateFlags flags;
+ 0u, // deUint32 setLayoutCount;
+ DE_NULL, // const VkDescriptorSetLayout* pSetLayouts;
+ 0u, // deUint32 pushConstantRangeCount;
+ DE_NULL // const VkPushConstantRange* pPushConstantRanges;
+ };
+
+ m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
+ }
+
+ m_vertexShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0);
+ m_fragmentShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag"), 0);
+
+ // Create pipeline
+ {
+ const VkPipelineShaderStageCreateInfo shaderStages[2] =
+ {
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineShaderStageCreateFlags flags;
+ VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage;
+ *m_vertexShaderModule, // VkShaderModule module;
+ "main", // const char* pName;
+ DE_NULL // const VkSpecializationInfo* pSpecializationInfo;
+ },
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineShaderStageCreateFlags flags;
+ VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage;
+ *m_fragmentShaderModule, // VkShaderModule module;
+ "main", // const char* pName;
+ DE_NULL // const VkSpecializationInfo* pSpecializationInfo;
+ }
+ };
+
+ const VkVertexInputBindingDescription vertexInputBindingDescription =
+ {
+ 0u, // deUint32 binding;
+ sizeof(Vertex4RGBA), // deUint32 strideInBytes;
+ VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate inputRate;
+ };
+
+ const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
+ {
+ {
+ 0u, // deUint32 location;
+ 0u, // deUint32 binding;
+ VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
+ 0u // deUint32 offsetInBytes;
+ },
+ {
+ 1u, // deUint32 location;
+ 0u, // deUint32 binding;
+ VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
+ DE_OFFSET_OF(Vertex4RGBA, color), // deUint32 offsetInBytes;
+ }
+ };
+
+ const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineVertexInputStateCreateFlags flags;
+ 1u, // deUint32 vertexBindingDescriptionCount;
+ &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
+ 2u, // deUint32 vertexAttributeDescriptionCount;
+ vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
+ };
+
+ const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineInputAssemblyStateCreateFlags flags;
+ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology topology;
+ false // VkBool32 primitiveRestartEnable;
+ };
+
+ const VkViewport viewport =
+ {
+ 0.0f, // float x;
+ 0.0f, // float y;
+ (float)m_renderSize.x(), // float width;
+ (float)m_renderSize.y(), // float height;
+ 0.0f, // float minDepth;
+ 1.0f // float maxDepth;
+ };
+
+ const VkRect2D scissor = { { 0, 0 }, { m_renderSize.x(), m_renderSize.y() } };
+
+ const VkPipelineViewportStateCreateInfo viewportStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineViewportStateCreateFlags flags;
+ 1u, // deUint32 viewportCount;
+ &viewport, // const VkViewport* pViewports;
+ 1u, // deUint32 scissorCount;
+ &scissor, // const VkRect2D* pScissors;
+ };
+
+ const VkPipelineRasterizationStateCreateInfo rasterStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineRasterizationStateCreateFlags flags;
+ false, // VkBool32 depthClampEnable;
+ false, // VkBool32 rasterizerDiscardEnable;
+ VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
+ VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
+ VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
+ false, // VkBool32 depthBiasEnable;
+ 0.0f, // float depthBiasConstantFactor;
+ 0.0f, // float depthBiasClamp;
+ 0.0f, // float depthBiasSlopeFactor;
+ 1.0f // float lineWidth;
+ };
+
+ const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
+ {
+ false, // VkBool32 blendEnable;
+ VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
+ VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
+ VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
+ VK_BLEND_FACTOR_ONE, // VKBLENDFACTOR SRCALPHABLENDFACTOR;
+ VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
+ VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
+ VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | // VkColorComponentFlags colorWriteMask;
+ VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
+ };
+
+ const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineColorBlendStateCreateFlags flags;
+ false, // VkBool32 logicOpEnable;
+ VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
+ 1u, // deUint32 attachmentCount;
+ &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
+ { 0.0f, 0.0f, 0.0f, 0.0f } // float blendConstants[4];
+ };
+
+ const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineMultisampleStateCreateFlags flags;
+ VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
+ false, // VkBool32 sampleShadingEnable;
+ 0.0f, // float minSampleShading;
+ DE_NULL, // const VkSampleMask* pSampleMask;
+ false, // VkBool32 alphaToCoverageEnable;
+ false // VkBool32 alphaToOneEnable;
+ };
+
+ const bool isDepthEnabled = (vk::mapVkFormat(m_stencilFormat).order != tcu::TextureFormat::S);
+
+ VkPipelineDepthStencilStateCreateInfo depthStencilStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineDepthStencilStateCreateFlags flags;
+ isDepthEnabled, // VkBool32 depthTestEnable;
+ isDepthEnabled, // VkBool32 depthWriteEnable;
+ VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp;
+ false, // VkBool32 depthBoundsTestEnable;
+ true, // VkBool32 stencilTestEnable;
+ m_stencilOpStateFront, // VkStencilOpState front;
+ m_stencilOpStateBack, // VkStencilOpState back;
+ -1.0f, // float minDepthBounds;
+ +1.0f // float maxDepthBounds;
+ };
+
+ const VkPipelineDynamicStateCreateInfo dynamicStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineDynamicStateCreateFlags flags;
+ 0u, // deUint32 dynamicStateCount;
+ DE_NULL // const VkDynamicState* pDynamicStates;
+ };
+
+ const VkGraphicsPipelineCreateInfo graphicsPipelineParams =
+ {
+ VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineCreateFlags flags;
+ 2u, // deUint32 stageCount;
+ shaderStages, // const VkPipelineShaderStageCreateInfo* pStages;
+ &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
+ &inputAssemblyStateParams, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
+ DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
+ &viewportStateParams, // const VkPipelineViewportStateCreateInfo* pViewportState;
+ &rasterStateParams, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
+ &multisampleStateParams, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
+ &depthStencilStateParams, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
+ &colorBlendStateParams, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
+ &dynamicStateParams, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
+ *m_pipelineLayout, // VkPipelineLayout layout;
+ *m_renderPass, // VkRenderPass renderPass;
+ 0u, // deUint32 subpass;
+ 0u, // VkPipeline basePipelineHandle;
+ 0u // deInt32 basePipelineIndex;
+ };
+
+ // Setup different stencil masks and refs in each quad
+ for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
+ {
+ const StencilTest::StencilStateConfig& config = StencilTest::s_stencilStateConfigs[quadNdx];
+ VkStencilOpState& front = depthStencilStateParams.front;
+ VkStencilOpState& back = depthStencilStateParams.back;
+
+ front.compareMask = config.frontReadMask;
+ front.writeMask = config.frontWriteMask;
+ front.reference = config.frontRef;
+
+ back.compareMask = config.backReadMask;
+ back.writeMask = config.backWriteMask;
+ back.reference = config.backRef;
+
+ m_graphicsPipelines[quadNdx] = createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams);
+ }
+ }
+
+
+ // Create vertex buffer
+ {
+ const VkBufferCreateInfo vertexBufferParams =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkBufferCreateFlags flags;
+ 1024u, // VkDeviceSize size;
+ VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
+ VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
+ 1u, // deUint32 queueFamilyIndexCount;
+ &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
+ };
+
+ m_vertices = createOverlappingQuads();
+ m_vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams);
+ m_vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
+
+ VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
+
+ // Adjust depths
+ for (int quadNdx = 0; quadNdx < 4; quadNdx++)
+ for (int vertexNdx = 0; vertexNdx < 6; vertexNdx++)
+ m_vertices[quadNdx * 6 + vertexNdx].position.z() = StencilTest::s_quadDepths[quadNdx];
+
+ // Load vertices into vertex buffer
+ deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
+
+ const VkMappedMemoryRange flushRange =
+ {
+ VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ m_vertexBufferAlloc->getMemory(), // VkDeviceMemory memory;
+ m_vertexBufferAlloc->getOffset(), // VkDeviceSize offset;
+ vertexBufferParams.size // VkDeviceSize size;
+ };
+
+ vk.flushMappedMemoryRanges(vkDevice, 1, &flushRange);
+ }
+
+ // Create command pool
+ {
+ const VkCommandPoolCreateInfo cmdPoolParams =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // VkCommandPoolCreateFlags flags;
+ queueFamilyIndex, // deUint32 queueFamilyIndex;
+ };
+
+ m_cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams);
+ }
+
+ // Create command buffer
+ {
+ const VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ *m_cmdPool, // VkCommandPool commandPool;
+ VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
+ 1u // deUint32 bufferCount;
+ };
+
+ const VkCommandBufferBeginInfo cmdBufferBeginInfo =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkCommandBufferUsageFlags flags;
+ DE_NULL, // VkRenderPass renderPass;
+ 0u, // deUint32 subpass;
+ DE_NULL, // VkFramebuffer framebuffer;
+ false, // VkBool32 occlusionQueryEnable;
+ 0u, // VkQueryControlFlags queryFlags;
+ 0u // VkQueryPipelineStatisticFlags pipelineStatistics;
+ };
+
+ const VkClearValue attachmentClearValues[2] =
+ {
+ defaultClearValue(m_colorFormat),
+ defaultClearValue(m_stencilFormat)
+ };
+
+ const VkRenderPassBeginInfo renderPassBeginInfo =
+ {
+ VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ *m_renderPass, // VkRenderPass renderPass;
+ *m_framebuffer, // VkFramebuffer framebuffer;
+ { { 0, 0 } , { m_renderSize.x(), m_renderSize.y() } }, // VkRect2D renderArea;
+ 2, // deUint32 clearValueCount;
+ attachmentClearValues // const VkClearValue* pClearValues;
+ };
+
+ m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferAllocateInfo);
+
+ VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
+ vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
+
+ const VkDeviceSize quadOffset = (m_vertices.size() / StencilTest::QUAD_COUNT) * sizeof(Vertex4RGBA);
+
+ for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
+ {
+ VkDeviceSize vertexBufferOffset = quadOffset * quadNdx;
+
+ vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelines[quadNdx]);
+ vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
+ vk.cmdDraw(*m_cmdBuffer, (deUint32)(m_vertices.size() / StencilTest::QUAD_COUNT), 1, 0, 0);
+ }
+
+ vk.cmdEndRenderPass(*m_cmdBuffer);
+ VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
+ }
+
+ // Create fence
+ {
+ const VkFenceCreateInfo fenceParams =
+ {
+ VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u // VkFenceCreateFlags flags;
+ };
+
+ m_fence = createFence(vk, vkDevice, &fenceParams);
+ }
+}
+
+StencilTestInstance::~StencilTestInstance (void)
+{
+}
+
+tcu::TestStatus StencilTestInstance::iterate (void)
+{
+ const DeviceInterface& vk = m_context.getDeviceInterface();
+ const VkDevice vkDevice = m_context.getDevice();
+ const VkQueue queue = m_context.getUniversalQueue();
+ const VkSubmitInfo submitInfo =
+ {
+ VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // deUint32 waitSemaphoreCount;
+ DE_NULL, // const VkSemaphore* pWaitSemaphores;
+ 1u, // deUint32 commandBufferCount;
+ &m_cmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
+ 0u, // deUint32 signalSemaphoreCount;
+ DE_NULL // const VkSemaphore* pSignalSemaphores;
+ };
+
+ VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
+ VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
+ VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity*/));
+
+ return verifyImage();
+}
+
+tcu::TestStatus StencilTestInstance::verifyImage (void)
+{
+ const tcu::TextureFormat tcuColorFormat = mapVkFormat(m_colorFormat);
+ const tcu::TextureFormat tcuStencilFormat = mapVkFormat(m_stencilFormat);
+ const ColorVertexShader vertexShader;
+ const ColorFragmentShader fragmentShader (tcuColorFormat, tcuStencilFormat);
+ const rr::Program program (&vertexShader, &fragmentShader);
+ ReferenceRenderer refRenderer (m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuStencilFormat, &program);
+ bool compareOk = false;
+
+ // Render reference image
+ {
+ // Set depth state
+ rr::RenderState renderState(refRenderer.getViewportState());
+
+ renderState.fragOps.depthTestEnabled = true;
+ renderState.fragOps.depthFunc = mapVkCompareOp(VK_COMPARE_OP_LESS);
+ renderState.fragOps.stencilTestEnabled = true;
+
+ rr::StencilState& refStencilFront = renderState.fragOps.stencilStates[rr::FACETYPE_FRONT];
+ rr::StencilState& refStencilBack = renderState.fragOps.stencilStates[rr::FACETYPE_BACK];
+
+ refStencilFront.sFail = mapVkStencilOp(m_stencilOpStateFront.failOp);
+ refStencilFront.dpFail = mapVkStencilOp(m_stencilOpStateFront.depthFailOp);
+ refStencilFront.dpPass = mapVkStencilOp(m_stencilOpStateFront.passOp);
+ refStencilFront.func = mapVkCompareOp(m_stencilOpStateFront.compareOp);
+
+ refStencilBack.sFail = mapVkStencilOp(m_stencilOpStateBack.failOp);
+ refStencilBack.dpFail = mapVkStencilOp(m_stencilOpStateBack.depthFailOp);
+ refStencilBack.dpPass = mapVkStencilOp(m_stencilOpStateBack.passOp);
+ refStencilBack.func = mapVkCompareOp(m_stencilOpStateBack.compareOp);
+
+ // Reverse winding of vertices, as Vulkan screen coordinates start at upper left
+ std::vector<Vertex4RGBA> cwVertices(m_vertices);
+ for (size_t vertexNdx = 0; vertexNdx < cwVertices.size() - 2; vertexNdx += 3)
+ {
+ const Vertex4RGBA cwVertex1 = cwVertices[vertexNdx + 1];
+
+ cwVertices[vertexNdx + 1] = cwVertices[vertexNdx + 2];
+ cwVertices[vertexNdx + 2] = cwVertex1;
+ }
+
+ for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
+ {
+ refStencilFront.ref = (int)StencilTest::s_stencilStateConfigs[quadNdx].frontRef;
+ refStencilFront.compMask = StencilTest::s_stencilStateConfigs[quadNdx].frontReadMask;
+ refStencilFront.writeMask = StencilTest::s_stencilStateConfigs[quadNdx].frontWriteMask;
+
+ refStencilBack.ref = (int)StencilTest::s_stencilStateConfigs[quadNdx].backRef;
+ refStencilBack.compMask = StencilTest::s_stencilStateConfigs[quadNdx].backReadMask;
+ refStencilBack.writeMask = StencilTest::s_stencilStateConfigs[quadNdx].backWriteMask;
+
+ refRenderer.draw(renderState,
+ rr::PRIMITIVETYPE_TRIANGLES,
+ std::vector<Vertex4RGBA>(cwVertices.begin() + quadNdx * 6,
+ cwVertices.begin() + (quadNdx + 1) * 6));
+ }
+ }
+
+ // Compare result with reference image
+ {
+ const DeviceInterface& vk = m_context.getDeviceInterface();
+ const VkDevice vkDevice = m_context.getDevice();
+ const VkQueue queue = m_context.getUniversalQueue();
+ const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
+ SimpleAllocator allocator (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
+ de::UniquePtr<tcu::TextureLevel> result (readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize).release());
+
+ compareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
+ "IntImageCompare",
+ "Image comparison",
+ refRenderer.getAccess(),
+ result->getAccess(),
+ tcu::UVec4(2, 2, 2, 2),
+ tcu::IVec3(1, 1, 0),
+ true,
+ tcu::COMPARE_LOG_RESULT);
+ }
+
+ if (compareOk)
+ return tcu::TestStatus::pass("Result image matches reference");
+ else
+ return tcu::TestStatus::fail("Image mismatch");
+}
+
+
+// Utilities for test names
+
+std::string getShortName (VkCompareOp compareOp)
+{
+ const std::string fullName = getCompareOpName(compareOp);
+
+ DE_ASSERT(de::beginsWith(fullName, "VK_COMPARE_OP_"));
+
+ return de::toLower(fullName.substr(14));
+}
+
+const char* getShortName (VkStencilOp stencilOp)
+{
+ switch (stencilOp)
+ {
+ case VK_STENCIL_OP_KEEP: return "keep";
+ case VK_STENCIL_OP_ZERO: return "zero";
+ case VK_STENCIL_OP_REPLACE: return "repl";
+ case VK_STENCIL_OP_INCREMENT_AND_CLAMP: return "incc";
+ case VK_STENCIL_OP_DECREMENT_AND_CLAMP: return "decc";
+ case VK_STENCIL_OP_INVERT: return "inv";
+ case VK_STENCIL_OP_INCREMENT_AND_WRAP: return "wrap";
+ case VK_STENCIL_OP_DECREMENT_AND_WRAP: return "decw";
+
+ default:
+ DE_FATAL("Invalid VkStencilOpState value");
+ }
+ return DE_NULL;
+}
+
+std::string getStencilName(const VkStencilOpState& stencilOpState)
+{
+ std::ostringstream name;
+
+ name << "fail_" << getShortName(stencilOpState.failOp)
+ << "_pass_" << getShortName(stencilOpState.passOp)
+ << "_dfail_" << getShortName(stencilOpState.depthFailOp)
+ << "_comp_" << getShortName(stencilOpState.compareOp);
+
+ return name.str();
+}
+
+std::string getStencilStateSetName(const VkStencilOpState& stencilOpStateFront,
+ const VkStencilOpState& stencilOpStateBack)
+{
+ std::ostringstream name;
+
+ name << "front_" << getStencilName(stencilOpStateFront)
+ << "_back_" << getStencilName(stencilOpStateBack);
+
+ return name.str();
+}
+
+std::string getStencilStateSetDescription(const VkStencilOpState& stencilOpStateFront,
+ const VkStencilOpState& stencilOpStateBack)
+{
+ std::ostringstream desc;
+
+ desc << "\nFront faces:\n" << stencilOpStateFront;
+ desc << "Back faces:\n" << stencilOpStateBack;
+
+ return desc.str();
+}
+
+std::string getFormatCaseName (VkFormat format)
+{
+ const std::string fullName = getFormatName(format);
+
+ DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_"));
+
+ return de::toLower(fullName.substr(10));
+}
+
+} // anonymous
+
+tcu::TestCaseGroup* createStencilTests (tcu::TestContext& testCtx)
+{
+ const VkFormat stencilFormats[] =
+ {
+ VK_FORMAT_S8_UINT,
+ VK_FORMAT_D16_UNORM_S8_UINT,
+ VK_FORMAT_D24_UNORM_S8_UINT,
+ VK_FORMAT_D32_SFLOAT_S8_UINT
+ };
+
+ de::MovePtr<tcu::TestCaseGroup> stencilTests (new tcu::TestCaseGroup(testCtx, "stencil", "Stencil tests"));
+ de::MovePtr<tcu::TestCaseGroup> formatTests (new tcu::TestCaseGroup(testCtx, "format", "Uses different stencil formats"));
+ StencilOpStateUniqueRandomIterator stencilOpItr (123);
+
+ for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(stencilFormats); formatNdx++)
+ {
+ const VkFormat stencilFormat = stencilFormats[formatNdx];
+ de::MovePtr<tcu::TestCaseGroup> formatTest (new tcu::TestCaseGroup(testCtx,
+ getFormatCaseName(stencilFormat).c_str(),
+ (std::string("Uses format ") + getFormatName(stencilFormat)).c_str()));
+
+ de::MovePtr<tcu::TestCaseGroup> stencilStateTests;
+ {
+ std::ostringstream desc;
+ desc << "Draws 4 quads with the following depths and dynamic stencil states: ";
+ for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
+ {
+ const StencilTest::StencilStateConfig& stencilConfig = StencilTest::s_stencilStateConfigs[quadNdx];
+
+ desc << "(" << quadNdx << ") "
+ << "z = " << StencilTest::s_quadDepths[quadNdx] << ", "
+ << "frontReadMask = " << stencilConfig.frontReadMask << ", "
+ << "frontWriteMask = " << stencilConfig.frontWriteMask << ", "
+ << "frontRef = " << stencilConfig.frontRef << ", "
+ << "backReadMask = " << stencilConfig.backReadMask << ", "
+ << "backWriteMask = " << stencilConfig.backWriteMask << ", "
+ << "backRef = " << stencilConfig.backRef;
+ }
+
+ stencilStateTests = de::MovePtr<tcu::TestCaseGroup>(new tcu::TestCaseGroup(testCtx, "states", desc.str().c_str()));
+ }
+
+ stencilOpItr.reset();
+
+ VkStencilOpState prevStencilState = stencilOpItr.next();
+ const VkStencilOpState firstStencilState = prevStencilState;
+
+ while (stencilOpItr.hasNext())
+ {
+ const VkStencilOpState stencilState = stencilOpItr.next();
+
+ // Use current stencil state in front fraces and previous state in back faces
+ stencilStateTests->addChild(new StencilTest(testCtx,
+ getStencilStateSetName(stencilState, prevStencilState),
+ getStencilStateSetDescription(stencilState, prevStencilState),
+ stencilFormat,
+ stencilState,
+ prevStencilState));
+
+ prevStencilState = stencilState;
+ }
+
+ // Use first stencil state with last stencil state. This would make the test suite cover all states in front and back faces.
+ stencilStateTests->addChild(new StencilTest(testCtx,
+ getStencilStateSetName(firstStencilState, prevStencilState),
+ getStencilStateSetDescription(firstStencilState, prevStencilState),
+ stencilFormat,
+ firstStencilState,
+ prevStencilState));
+
+ formatTest->addChild(stencilStateTests.release());
+ formatTests->addChild(formatTest.release());
+ }
+ stencilTests->addChild(formatTests.release());
+
+ return stencilTests.release();
+}
+
+} // pipeline
+} // vkt
--- /dev/null
+#ifndef _VKTPIPELINESTENCILTESTS_HPP
+#define _VKTPIPELINESTENCILTESTS_HPP
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Imagination Technologies Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by Khronos,
+ * at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Stencil Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktTestCase.hpp"
+
+namespace vkt
+{
+namespace pipeline
+{
+
+tcu::TestCaseGroup* createStencilTests (tcu::TestContext& testCtx);
+
+} // pipeline
+} // vkt
+
+#endif // _VKTPIPELINESTENCILTESTS_HPP
--- /dev/null
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Imagination Technologies Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by Khronos,
+ * at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Pipeline Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktPipelineTests.hpp"
+#include "vktPipelineStencilTests.hpp"
+#include "vktPipelineBlendTests.hpp"
+#include "vktPipelineDepthTests.hpp"
+#include "vktPipelineImageTests.hpp"
+#include "vktPipelineSamplerTests.hpp"
+#include "vktPipelineImageViewTests.hpp"
+#include "deUniquePtr.hpp"
+
+namespace vkt
+{
+namespace pipeline
+{
+
+tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> pipelineTests (new tcu::TestCaseGroup(testCtx, "pipeline", "Pipeline Tests"));
+
+ pipelineTests->addChild(createStencilTests(testCtx));
+ pipelineTests->addChild(createBlendTests(testCtx));
+ pipelineTests->addChild(createDepthTests(testCtx));
+ pipelineTests->addChild(createImageTests(testCtx));
+ pipelineTests->addChild(createSamplerTests(testCtx));
+ pipelineTests->addChild(createImageViewTests(testCtx));
+
+ return pipelineTests.release();
+}
+
+} // pipeline
+} // vkt
--- /dev/null
+#ifndef _VKTPIPELINETESTS_HPP
+#define _VKTPIPELINETESTS_HPP
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Imagination Technologies Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by Khronos,
+ * at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Pipeline Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+namespace pipeline
+{
+
+tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx);
+
+} // pipeline
+} // vkt
+
+#endif // _VKTPIPELINETESTS_HPP
--- /dev/null
+#ifndef _VKTPIPELINEUNIQUERANDOMITERATOR_HPP
+#define _VKTPIPELINEUNIQUERANDOMITERATOR_HPP
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Imagination Technologies Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by Khronos,
+ * at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Iterator over a unique sequence of items
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "deRandom.hpp"
+#include <set>
+#include <vector>
+
+namespace vkt
+{
+namespace pipeline
+{
+
+template <typename T>
+class UniqueRandomIterator
+{
+public:
+ UniqueRandomIterator (deUint32 numItems, deUint32 numValues, int seed);
+ virtual ~UniqueRandomIterator (void) {}
+ bool hasNext (void) const;
+ T next (void);
+ void reset (void);
+
+protected:
+ virtual T getIndexedValue (deUint32 index) = 0;
+
+private:
+ std::vector<deUint32> m_indices;
+ size_t m_currentIndex;
+};
+
+template <typename T>
+UniqueRandomIterator<T>::UniqueRandomIterator (deUint32 numItems, deUint32 numValues, int seed)
+{
+ de::Random rnd(seed);
+
+ DE_ASSERT(numItems <= numValues);
+
+ if (numItems == numValues)
+ {
+ // Fast way to populate the index sequence
+ m_indices = std::vector<deUint32>(numItems);
+
+ for (deUint32 itemNdx = 0; itemNdx < numItems; itemNdx++)
+ m_indices[itemNdx] = itemNdx;
+ }
+ else
+ {
+ std::set<deUint32> uniqueIndices;
+
+ // Populate set with "numItems" unique values between 0 and numValues - 1
+ while (uniqueIndices.size() < numItems)
+ uniqueIndices.insert(rnd.getUint32() % numValues);
+
+ // Copy set into index sequence
+ m_indices = std::vector<deUint32>(uniqueIndices.begin(), uniqueIndices.end());
+ }
+
+ // Scramble the indices
+ rnd.shuffle(m_indices.begin(), m_indices.end());
+
+ reset();
+}
+
+template <typename T>
+bool UniqueRandomIterator<T>::hasNext (void) const
+{
+ return m_currentIndex < m_indices.size();
+}
+
+template <typename T>
+T UniqueRandomIterator<T>::next (void)
+{
+ DE_ASSERT(m_currentIndex < m_indices.size());
+
+ return getIndexedValue(m_indices[m_currentIndex++]);
+}
+
+template <typename T>
+void UniqueRandomIterator<T>::reset (void)
+{
+ m_currentIndex = 0;
+}
+
+} // pipeline
+} // vkt
+
+#endif // _VKTPIPELINEUNIQUERANDOMITERATOR_HPP
--- /dev/null
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Imagination Technologies Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by Khronos,
+ * at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Utilities for vertex buffers.
+ *//*--------------------------------------------------------------------*/
+
+#include "vktPipelineVertexUtil.hpp"
+#include "tcuVectorUtil.hpp"
+
+namespace vkt
+{
+namespace pipeline
+{
+
+std::vector<Vertex4RGBA> createOverlappingQuads (void)
+{
+ using tcu::Vec2;
+ using tcu::Vec4;
+
+ std::vector<Vertex4RGBA> vertices;
+
+ const Vec2 translations[4] =
+ {
+ Vec2(-0.25f, -0.25f),
+ Vec2(-1.0f, -0.25f),
+ Vec2(-1.0f, -1.0f),
+ Vec2(-0.25f, -1.0f)
+ };
+
+ const Vec4 quadColors[4] =
+ {
+ Vec4(1.0f, 0.0f, 0.0f, 1.0),
+ Vec4(0.0f, 1.0f, 0.0f, 1.0),
+ Vec4(0.0f, 0.0f, 1.0f, 1.0),
+ Vec4(1.0f, 0.0f, 1.0f, 1.0)
+ };
+
+ const float quadSize = 1.25f;
+
+ for (int quadNdx = 0; quadNdx < 4; quadNdx++)
+ {
+ const Vec2& translation = translations[quadNdx];
+ const Vec4& color = quadColors[quadNdx];
+
+ const Vertex4RGBA lowerLeftVertex =
+ {
+ Vec4(translation.x(), translation.y(), 0.0f, 1.0f),
+ color
+ };
+ const Vertex4RGBA upperLeftVertex =
+ {
+ Vec4(translation.x(), translation.y() + quadSize, 0.0f, 1.0f),
+ color
+ };
+ const Vertex4RGBA lowerRightVertex =
+ {
+ Vec4(translation.x() + quadSize, translation.y(), 0.0f, 1.0f),
+ color
+ };
+ const Vertex4RGBA upperRightVertex =
+ {
+ Vec4(translation.x() + quadSize, translation.y() + quadSize, 0.0f, 1.0f),
+ color
+ };
+
+ // Triangle 1, CCW
+ vertices.push_back(lowerLeftVertex);
+ vertices.push_back(lowerRightVertex);
+ vertices.push_back(upperLeftVertex);
+
+ // Triangle 2, CW
+ vertices.push_back(lowerRightVertex);
+ vertices.push_back(upperLeftVertex);
+ vertices.push_back(upperRightVertex);
+ }
+
+ return vertices;
+}
+
+std::vector<Vertex4Tex4> createFullscreenQuad (void)
+{
+ using tcu::Vec4;
+
+ const Vertex4Tex4 lowerLeftVertex =
+ {
+ Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
+ Vec4(0.0f, 0.0f, 0.0f, 0.0f)
+ };
+ const Vertex4Tex4 upperLeftVertex =
+ {
+ Vec4(-1.0f, 1.0f, 0.0f, 1.0f),
+ Vec4(0.0f, 1.0f, 0.0f, 0.0f)
+ };
+ const Vertex4Tex4 lowerRightVertex =
+ {
+ Vec4(1.0f, -1.0f, 0.0f, 1.0f),
+ Vec4(1.0f, 0.0f, 0.0f, 0.0f)
+ };
+ const Vertex4Tex4 upperRightVertex =
+ {
+ Vec4(1.0f, 1.0f, 0.0f, 1.0f),
+ Vec4(1.0f, 1.0f, 0.0f, 0.0f)
+ };
+
+ const Vertex4Tex4 vertices[6] =
+ {
+ lowerLeftVertex,
+ lowerRightVertex,
+ upperLeftVertex,
+
+ upperLeftVertex,
+ lowerRightVertex,
+ upperRightVertex
+ };
+
+ return std::vector<Vertex4Tex4>(vertices, vertices + DE_LENGTH_OF_ARRAY(vertices));
+}
+
+std::vector<Vertex4Tex4> createQuadMosaic (int rows, int columns)
+{
+ using tcu::Vec4;
+
+ DE_ASSERT(rows >= 1);
+ DE_ASSERT(columns >= 1);
+
+ std::vector<Vertex4Tex4> vertices;
+ const float rowSize = 2.0f / (float)rows;
+ const float columnSize = 2.0f / (float)columns;
+ int arrayIndex = 0;
+
+ for (int rowNdx = 0; rowNdx < rows; rowNdx++)
+ {
+ for (int columnNdx = 0; columnNdx < columns; columnNdx++)
+ {
+ const Vertex4Tex4 lowerLeftVertex =
+ {
+ Vec4(-1.0f + (float)columnNdx * columnSize, -1.0f + (float)rowNdx * rowSize, 0.0f, 1.0f),
+ Vec4(0.0f, 0.0f, (float)arrayIndex, 0.0f)
+ };
+ const Vertex4Tex4 upperLeftVertex =
+ {
+ Vec4(lowerLeftVertex.position.x(), lowerLeftVertex.position.y() + rowSize, 0.0f, 1.0f),
+ Vec4(0.0f, 1.0f, (float)arrayIndex, 0.0f)
+ };
+ const Vertex4Tex4 lowerRightVertex =
+ {
+ Vec4(lowerLeftVertex.position.x() + columnSize, lowerLeftVertex.position.y(), 0.0f, 1.0f),
+ Vec4(1.0f, 0.0f, (float)arrayIndex, 0.0f)
+ };
+ const Vertex4Tex4 upperRightVertex =
+ {
+ Vec4(lowerLeftVertex.position.x() + columnSize, lowerLeftVertex.position.y() + rowSize, 0.0f, 1.0f),
+ Vec4(1.0f, 1.0f, (float)arrayIndex, 0.0f)
+ };
+
+ vertices.push_back(lowerLeftVertex);
+ vertices.push_back(lowerRightVertex);
+ vertices.push_back(upperLeftVertex);
+ vertices.push_back(upperLeftVertex);
+ vertices.push_back(lowerRightVertex);
+ vertices.push_back(upperRightVertex);
+
+ arrayIndex++;
+ }
+ }
+
+ return vertices;
+}
+
+std::vector<Vertex4Tex4> createQuadMosaicCube (void)
+{
+ using tcu::Vec3;
+
+ static const Vec3 texCoordsCube[8] =
+ {
+ Vec3(-1.0f, -1.0f, -1.0f), // 0: -X, -Y, -Z
+ Vec3(1.0f, -1.0f, -1.0f), // 1: X, -Y, -Z
+ Vec3(1.0f, -1.0f, 1.0f), // 2: X, -Y, Z
+ Vec3(-1.0f, -1.0f, 1.0f), // 3: -X, -Y, Z
+
+ Vec3(-1.0f, 1.0f, -1.0f), // 4: -X, Y, -Z
+ Vec3(1.0f, 1.0f, -1.0f), // 5: X, Y, -Z
+ Vec3(1.0f, 1.0f, 1.0f), // 6: X, Y, Z
+ Vec3(-1.0f, 1.0f, 1.0f), // 7: -X, Y, Z
+ };
+
+ static const int texCoordCubeIndices[6][6] =
+ {
+ { 6, 5, 2, 2, 5, 1 }, // +X face
+ { 3, 0, 7, 7, 0, 4 }, // -X face
+ { 4, 5, 7, 7, 5, 6 }, // +Y face
+ { 3, 2, 0, 0, 2, 1 }, // -Y face
+ { 2, 3, 6, 6, 3, 7 }, // +Z face
+ { 0, 1, 4, 4, 1, 5 } // -Z face
+ };
+
+ // Create 6 quads and set appropriate texture coordinates for cube mapping
+
+ std::vector<Vertex4Tex4> vertices = createQuadMosaic(2, 3);
+ std::vector<Vertex4Tex4>::iterator vertexItr = vertices.begin();
+
+ for (int quadNdx = 0; quadNdx < 6; quadNdx++)
+ {
+ for (int vertexNdx = 0; vertexNdx < 6; vertexNdx++)
+ {
+ vertexItr->texCoord.xyz() = texCoordsCube[texCoordCubeIndices[quadNdx][vertexNdx]];
+ vertexItr++;
+ }
+ }
+
+ return vertices;
+}
+
+std::vector<Vertex4Tex4> createQuadMosaicCubeArray (int faceArrayIndices[6])
+{
+ std::vector<Vertex4Tex4> vertices = createQuadMosaicCube();
+ std::vector<Vertex4Tex4>::iterator vertexItr = vertices.begin();
+
+ for (int quadNdx = 0; quadNdx < 6; quadNdx++)
+ {
+ for (int vertexNdx = 0; vertexNdx < 6; vertexNdx++)
+ {
+ vertexItr->texCoord.w() = (float)faceArrayIndices[quadNdx];
+ vertexItr++;
+ }
+ }
+
+ return vertices;
+}
+
+std::vector<Vertex4Tex4> createTestQuadMosaic (vk::VkImageViewType viewType)
+{
+ std::vector<Vertex4Tex4> vertices;
+
+ switch (viewType)
+ {
+ case vk::VK_IMAGE_VIEW_TYPE_1D:
+ case vk::VK_IMAGE_VIEW_TYPE_2D:
+ vertices = createFullscreenQuad();
+ break;
+
+ case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY:
+ vertices = createQuadMosaic(2, 3);
+
+ // Set up array indices
+ for (size_t quadNdx = 0; quadNdx < 6; quadNdx++)
+ for (size_t vertexNdx = 0; vertexNdx < 6; vertexNdx++)
+ vertices[quadNdx * 6 + vertexNdx].texCoord.y() = (float)quadNdx;
+
+ break;
+
+ case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY:
+ vertices = createQuadMosaic(2, 3);
+ break;
+
+ case vk::VK_IMAGE_VIEW_TYPE_3D:
+ vertices = createQuadMosaic(2, 3);
+
+ // Use z between 0.0 and 1.0.
+ for (size_t vertexNdx = 0; vertexNdx < vertices.size(); vertexNdx++)
+ vertices[vertexNdx].texCoord.z() /= 5.0f;
+
+ break;
+
+ case vk::VK_IMAGE_VIEW_TYPE_CUBE:
+ vertices = createQuadMosaicCube();
+ break;
+
+ case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
+ {
+ int faceArrayIndices[6] = { 0, 1, 2, 3, 4, 5 };
+ vertices = createQuadMosaicCubeArray(faceArrayIndices);
+ }
+ break;
+
+ default:
+ DE_ASSERT(false);
+ break;
+ }
+
+ return vertices;
+}
+
+} // pipeline
+} // vkt
--- /dev/null
+#ifndef _VKTPIPELINEVERTEXUTIL_HPP
+#define _VKTPIPELINEVERTEXUTIL_HPP
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Imagination Technologies Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by Khronos,
+ * at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Utilities for vertex buffers.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkDefs.hpp"
+#include "tcuDefs.hpp"
+#include "tcuVectorUtil.hpp"
+
+#include <vector>
+
+namespace vkt
+{
+namespace pipeline
+{
+
+struct Vertex4RGBA
+{
+ tcu::Vec4 position;
+ tcu::Vec4 color;
+};
+
+struct Vertex4Tex4
+{
+ tcu::Vec4 position;
+ tcu::Vec4 texCoord;
+};
+
+/*! \brief Creates a pattern of 4 overlapping quads.
+ *
+ * The quads are alined along the plane Z = 0, with X,Y taking values between -1 and 1.
+ * Each quad covers one of the quadrants of the scene and partially extends to the other 3 quadrants.
+ * The triangles of each quad have different winding orders (CW/CCW).
+ */
+std::vector<Vertex4RGBA> createOverlappingQuads (void);
+
+std::vector<Vertex4Tex4> createFullscreenQuad (void);
+std::vector<Vertex4Tex4> createQuadMosaic (int rows, int columns);
+std::vector<Vertex4Tex4> createQuadMosaicCube (void);
+std::vector<Vertex4Tex4> createQuadMosaicCubeArray (int faceArrayIndices[6]);
+
+std::vector<Vertex4Tex4> createTestQuadMosaic (vk::VkImageViewType viewType);
+
+} // pipeline
+} // vkt
+
+#endif // _VKTPIPELINEVERTEXUTIL_HPP
--- /dev/null
+include_directories(
+ ..
+ )
+
+set(DEQP_VK_SHADERRENDER_SRCS
+ vktShaderRender.cpp
+ vktShaderRender.hpp
+ vktShaderRenderDiscardTests.cpp
+ vktShaderRenderDiscardTests.hpp
+ )
+
+set(DEQP_VK_SHADERRENDER_LIBS
+ tcutil
+ vkutil
+ )
+
+add_library(deqp-vk-shaderrender STATIC ${DEQP_VK_SHADERRENDER_SRCS})
+target_link_libraries(deqp-vk-shaderrender ${DEQP_VK_SHADERRENDER_LIBS})
--- /dev/null
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by Khronos,
+ * at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Vulkan ShaderRenderCase
+ *//*--------------------------------------------------------------------*/
+
+#include "vktShaderRender.hpp"
+
+#include "tcuImageCompare.hpp"
+#include "tcuImageIO.hpp"
+#include "tcuTestLog.hpp"
+#include "tcuTextureUtil.hpp"
+#include "tcuSurface.hpp"
+#include "tcuVector.hpp"
+
+#include "deFilePath.hpp"
+#include "deMath.h"
+#include "deUniquePtr.hpp"
+
+#include "vkDeviceUtil.hpp"
+#include "vkImageUtil.hpp"
+#include "vkPlatform.hpp"
+#include "vkQueryUtil.hpp"
+#include "vkRef.hpp"
+#include "vkRefUtil.hpp"
+#include "vkStrUtil.hpp"
+#include "vkTypeUtil.hpp"
+
+#include <vector>
+#include <string>
+
+namespace vkt
+{
+namespace sr
+{
+
+using namespace vk;
+
+namespace
+{
+
+static const int s_gridSize = 2;
+static const int s_maxRenderWidth = 128;
+static const int s_maxRenderHeight = 128;
+static const tcu::Vec4 s_defaultClearColor = tcu::Vec4(0.125f, 0.25f, 0.5f, 1.0f);
+
+static bool isSupportedLinearTilingFormat (const InstanceInterface& instanceInterface, VkPhysicalDevice device, VkFormat format)
+{
+ VkFormatProperties formatProps;
+
+ instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
+
+ return (formatProps.linearTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) != 0u;
+}
+
+static bool isSupportedOptimalTilingFormat (const InstanceInterface& instanceInterface, VkPhysicalDevice device, VkFormat format)
+{
+ VkFormatProperties formatProps;
+
+ instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
+
+ return (formatProps.linearTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) != 0u;
+}
+
+static VkImageMemoryBarrier createImageMemoryBarrier (const VkImage& image,
+ VkAccessFlags srcAccessMask,
+ VkAccessFlags dstAccessMask,
+ VkImageLayout oldLayout,
+ VkImageLayout newLayout)
+{
+ VkImageMemoryBarrier imageMemoryBarrier =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ srcAccessMask, // VkAccessFlags srcAccessMask;
+ dstAccessMask, // VkAccessFlags dstAccessMask;
+ oldLayout, // VkImageLayout oldLayout;
+ newLayout, // VkImageLayout newLayout;
+ VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
+ VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
+ image, // VkImage image;
+ {
+ VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
+ 0, // deUint32 baseMipLevel;
+ 1, // deUint32 mipLevels;
+ 0, // deUint32 baseArrayLayer;
+ 1 // deUint32 arraySize;
+ } // VkImageSubresourceRange subresourceRange;
+ };
+ return imageMemoryBarrier;
+}
+
+} // anonymous
+
+// QuadGrid.
+
+class QuadGrid
+{
+public:
+ QuadGrid (int gridSize,
+ int screenWidth,
+ int screenHeight,
+ const tcu::Vec4& constCoords,
+ const std::vector<tcu::Mat4>& userAttribTransforms,
+ const std::vector<TextureBindingSp>& textures);
+ ~QuadGrid (void);
+
+ int getGridSize (void) const { return m_gridSize; }
+ int getNumVertices (void) const { return m_numVertices; }
+ int getNumTriangles (void) const { return m_numTriangles; }
+ const tcu::Vec4& getConstCoords (void) const { return m_constCoords; }
+ const std::vector<tcu::Mat4> getUserAttribTransforms (void) const { return m_userAttribTransforms; }
+ const std::vector<TextureBindingSp>& getTextures (void) const { return m_textures; }
+
+ const tcu::Vec4* getPositions (void) const { return &m_positions[0]; }
+ const float* getAttribOne (void) const { return &m_attribOne[0]; }
+ const tcu::Vec4* getCoords (void) const { return &m_coords[0]; }
+ const tcu::Vec4* getUnitCoords (void) const { return &m_unitCoords[0]; }
+
+ const tcu::Vec4* getUserAttrib (int attribNdx) const { return &m_userAttribs[attribNdx][0]; }
+ const deUint16* getIndices (void) const { return &m_indices[0]; }
+
+ tcu::Vec4 getCoords (float sx, float sy) const;
+ tcu::Vec4 getUnitCoords (float sx, float sy) const;
+
+ int getNumUserAttribs (void) const { return (int)m_userAttribTransforms.size(); }
+ tcu::Vec4 getUserAttrib (int attribNdx, float sx, float sy) const;
+
+private:
+ const int m_gridSize;
+ const int m_numVertices;
+ const int m_numTriangles;
+ const tcu::Vec4 m_constCoords;
+ const std::vector<tcu::Mat4> m_userAttribTransforms;
+
+ const std::vector<TextureBindingSp>& m_textures;
+
+ std::vector<tcu::Vec4> m_screenPos;
+ std::vector<tcu::Vec4> m_positions;
+ std::vector<tcu::Vec4> m_coords; //!< Near-unit coordinates, roughly [-2.0 .. 2.0].
+ std::vector<tcu::Vec4> m_unitCoords; //!< Positive-only coordinates [0.0 .. 1.5].
+ std::vector<float> m_attribOne;
+ std::vector<tcu::Vec4> m_userAttribs[ShaderEvalContext::MAX_TEXTURES];
+ std::vector<deUint16> m_indices;
+};
+
+QuadGrid::QuadGrid (int gridSize,
+ int width,
+ int height,
+ const tcu::Vec4& constCoords,
+ const std::vector<tcu::Mat4>& userAttribTransforms,
+ const std::vector<TextureBindingSp>& textures)
+ : m_gridSize (gridSize)
+ , m_numVertices ((gridSize + 1) * (gridSize + 1))
+ , m_numTriangles (gridSize * gridSize * 2)
+ , m_constCoords (constCoords)
+ , m_userAttribTransforms (userAttribTransforms)
+ , m_textures (textures)
+{
+ const tcu::Vec4 viewportScale ((float)width, (float)height, 0.0f, 0.0f);
+
+ // Compute vertices.
+ m_screenPos.resize(m_numVertices);
+ m_positions.resize(m_numVertices);
+ m_coords.resize(m_numVertices);
+ m_unitCoords.resize(m_numVertices);
+ m_attribOne.resize(m_numVertices);
+
+ // User attributes.
+ for (int attrNdx = 0; attrNdx < DE_LENGTH_OF_ARRAY(m_userAttribs); attrNdx++)
+ m_userAttribs[attrNdx].resize(m_numVertices);
+
+ for (int y = 0; y < gridSize+1; y++)
+ for (int x = 0; x < gridSize+1; x++)
+ {
+ float sx = (float)x / (float)gridSize;
+ float sy = (float)y / (float)gridSize;
+ float fx = 2.0f * sx - 1.0f;
+ float fy = 2.0f * sy - 1.0f;
+ int vtxNdx = ((y * (gridSize+1)) + x);
+
+ m_positions[vtxNdx] = tcu::Vec4(fx, fy, 0.0f, 1.0f);
+ m_coords[vtxNdx] = getCoords(sx, sy);
+ m_unitCoords[vtxNdx] = getUnitCoords(sx, sy);
+ m_attribOne[vtxNdx] = 1.0f;
+
+ m_screenPos[vtxNdx] = tcu::Vec4(sx, sy, 0.0f, 1.0f) * viewportScale;
+
+ for (int attribNdx = 0; attribNdx < getNumUserAttribs(); attribNdx++)
+ m_userAttribs[attribNdx][vtxNdx] = getUserAttrib(attribNdx, sx, sy);
+ }
+
+ // Compute indices.
+ m_indices.resize(3 * m_numTriangles);
+ for (int y = 0; y < gridSize; y++)
+ for (int x = 0; x < gridSize; x++)
+ {
+ int stride = gridSize + 1;
+ int v00 = (y * stride) + x;
+ int v01 = (y * stride) + x + 1;
+ int v10 = ((y+1) * stride) + x;
+ int v11 = ((y+1) * stride) + x + 1;
+
+ int baseNdx = ((y * gridSize) + x) * 6;
+ m_indices[baseNdx + 0] = (deUint16)v10;
+ m_indices[baseNdx + 1] = (deUint16)v00;
+ m_indices[baseNdx + 2] = (deUint16)v01;
+
+ m_indices[baseNdx + 3] = (deUint16)v10;
+ m_indices[baseNdx + 4] = (deUint16)v01;
+ m_indices[baseNdx + 5] = (deUint16)v11;
+ }
+}
+
+QuadGrid::~QuadGrid (void)
+{
+}
+
+inline tcu::Vec4 QuadGrid::getCoords (float sx, float sy) const
+{
+ const float fx = 2.0f * sx - 1.0f;
+ const float fy = 2.0f * sy - 1.0f;
+ return tcu::Vec4(fx, fy, -fx + 0.33f*fy, -0.275f*fx - fy);
+}
+
+inline tcu::Vec4 QuadGrid::getUnitCoords (float sx, float sy) const
+{
+ return tcu::Vec4(sx, sy, 0.33f*sx + 0.5f*sy, 0.5f*sx + 0.25f*sy);
+}
+
+inline tcu::Vec4 QuadGrid::getUserAttrib (int attribNdx, float sx, float sy) const
+{
+ // homogeneous normalized screen-space coordinates
+ return m_userAttribTransforms[attribNdx] * tcu::Vec4(sx, sy, 0.0f, 1.0f);
+}
+
+// TextureBinding
+
+TextureBinding::TextureBinding (const tcu::Archive& archive,
+ const char* filename,
+ const Type type,
+ const tcu::Sampler& sampler)
+ : m_type (type)
+ , m_sampler (sampler)
+{
+ switch(m_type)
+ {
+ case TYPE_2D: m_binding.tex2D = loadTexture2D(archive, filename).release(); break;
+ default:
+ DE_FATAL("Unsupported texture type");
+ }
+}
+
+TextureBinding::~TextureBinding (void)
+{
+ switch(m_type)
+ {
+ case TYPE_2D: delete m_binding.tex2D; break;
+ default: break;
+ }
+}
+
+
+de::MovePtr<tcu::Texture2D> TextureBinding::loadTexture2D (const tcu::Archive& archive, const char* filename)
+{
+ tcu::TextureLevel level;
+ tcu::ImageIO::loadImage(level, archive, filename);
+
+ TCU_CHECK_INTERNAL(level.getFormat() == tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8) ||
+ level.getFormat() == tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8));
+
+ // \todo [2015-10-08 elecro] for some reason we get better when using RGBA texture even in RGB case, this needs to be investigated
+ de::MovePtr<tcu::Texture2D> texture(new tcu::Texture2D(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), level.getWidth(), level.getHeight()));
+
+ // Fill level 0.
+ texture->allocLevel(0);
+ tcu::copy(texture->getLevel(0), level.getAccess());
+
+ return texture;
+}
+
+// ShaderEvalContext.
+
+ShaderEvalContext::ShaderEvalContext (const QuadGrid& quadGrid)
+ : constCoords (quadGrid.getConstCoords())
+ , isDiscarded (false)
+ , m_quadGrid (quadGrid)
+{
+ const std::vector<TextureBindingSp>& bindings = m_quadGrid.getTextures();
+ DE_ASSERT((int)bindings.size() <= MAX_TEXTURES);
+
+ // Fill in texture array.
+ for (int ndx = 0; ndx < (int)bindings.size(); ndx++)
+ {
+ const TextureBinding& binding = *bindings[ndx];
+
+ if (binding.getType() == TextureBinding::TYPE_NONE)
+ continue;
+
+ textures[ndx].sampler = binding.getSampler();
+
+ switch (binding.getType())
+ {
+ case TextureBinding::TYPE_2D: textures[ndx].tex2D = &binding.get2D(); break;
+ // \todo [2015-09-07 elecro] Add support for the other binding types
+ /*
+ case TextureBinding::TYPE_CUBE_MAP: textures[ndx].texCube = binding.getCube(); break;
+ case TextureBinding::TYPE_2D_ARRAY: textures[ndx].tex2DArray = binding.get2DArray(); break;
+ case TextureBinding::TYPE_3D: textures[ndx].tex3D = binding.get3D(); break;
+ */
+ default:
+ TCU_THROW(InternalError, "Handling of texture binding type not implemented");
+ }
+ }
+}
+
+ShaderEvalContext::~ShaderEvalContext (void)
+{
+}
+
+void ShaderEvalContext::reset (float sx, float sy)
+{
+ // Clear old values
+ color = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
+ isDiscarded = false;
+
+ // Compute coords
+ coords = m_quadGrid.getCoords(sx, sy);
+ unitCoords = m_quadGrid.getUnitCoords(sx, sy);
+
+ // Compute user attributes.
+ const int numAttribs = m_quadGrid.getNumUserAttribs();
+ DE_ASSERT(numAttribs <= MAX_USER_ATTRIBS);
+ for (int attribNdx = 0; attribNdx < numAttribs; attribNdx++)
+ in[attribNdx] = m_quadGrid.getUserAttrib(attribNdx, sx, sy);
+}
+
+tcu::Vec4 ShaderEvalContext::texture2D (int unitNdx, const tcu::Vec2& texCoords)
+{
+ if (textures[unitNdx].tex2D)
+ return textures[unitNdx].tex2D->sample(textures[unitNdx].sampler, texCoords.x(), texCoords.y(), 0.0f);
+ else
+ return tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
+}
+
+// ShaderEvaluator.
+
+ShaderEvaluator::ShaderEvaluator (void)
+ : m_evalFunc(DE_NULL)
+{
+}
+
+ShaderEvaluator::ShaderEvaluator (ShaderEvalFunc evalFunc)
+ : m_evalFunc(evalFunc)
+{
+}
+
+ShaderEvaluator::~ShaderEvaluator (void)
+{
+}
+
+void ShaderEvaluator::evaluate (ShaderEvalContext& ctx) const
+{
+ DE_ASSERT(m_evalFunc);
+ m_evalFunc(ctx);
+}
+
+// UniformSetup.
+
+UniformSetup::UniformSetup (void)
+ : m_setupFunc(DE_NULL)
+{
+}
+
+UniformSetup::UniformSetup (UniformSetupFunc setupFunc)
+ : m_setupFunc(setupFunc)
+{
+}
+
+UniformSetup::~UniformSetup (void)
+{
+}
+
+void UniformSetup::setup (ShaderRenderCaseInstance& instance, const tcu::Vec4& constCoords) const
+{
+ if (m_setupFunc)
+ m_setupFunc(instance, constCoords);
+}
+
+// ShaderRenderCase.
+
+ShaderRenderCase::ShaderRenderCase (tcu::TestContext& testCtx,
+ const std::string& name,
+ const std::string& description,
+ const bool isVertexCase,
+ const ShaderEvalFunc evalFunc,
+ const UniformSetup* uniformSetup,
+ const AttributeSetupFunc attribFunc)
+ : vkt::TestCase (testCtx, name, description)
+ , m_isVertexCase (isVertexCase)
+ , m_evaluator (new ShaderEvaluator(evalFunc))
+ , m_uniformSetup (uniformSetup ? uniformSetup : new UniformSetup())
+ , m_attribFunc (attribFunc)
+{}
+
+ShaderRenderCase::ShaderRenderCase (tcu::TestContext& testCtx,
+ const std::string& name,
+ const std::string& description,
+ const bool isVertexCase,
+ const ShaderEvaluator* evaluator,
+ const UniformSetup* uniformSetup,
+ const AttributeSetupFunc attribFunc)
+ : vkt::TestCase (testCtx, name, description)
+ , m_isVertexCase (isVertexCase)
+ , m_evaluator (evaluator)
+ , m_uniformSetup (uniformSetup ? uniformSetup : new UniformSetup())
+ , m_attribFunc (attribFunc)
+{}
+
+ShaderRenderCase::~ShaderRenderCase (void)
+{
+}
+
+void ShaderRenderCase::initPrograms (vk::SourceCollections& programCollection) const
+{
+ programCollection.glslSources.add("vert") << glu::VertexSource(m_vertShaderSource);
+ programCollection.glslSources.add("frag") << glu::FragmentSource(m_fragShaderSource);
+}
+
+TestInstance* ShaderRenderCase::createInstance (Context& context) const
+{
+ DE_ASSERT(m_evaluator != DE_NULL);
+ DE_ASSERT(m_uniformSetup != DE_NULL);
+ return new ShaderRenderCaseInstance(context, m_isVertexCase, *m_evaluator, *m_uniformSetup, m_attribFunc);
+}
+
+// ShaderRenderCaseInstance.
+
+ShaderRenderCaseInstance::ShaderRenderCaseInstance (Context& context,
+ const bool isVertexCase,
+ const ShaderEvaluator& evaluator,
+ const UniformSetup& uniformSetup,
+ const AttributeSetupFunc attribFunc)
+ : vkt::TestInstance (context)
+ , m_clearColor (s_defaultClearColor)
+ , m_memAlloc (context.getDefaultAllocator())
+ , m_isVertexCase (isVertexCase)
+ , m_evaluator (evaluator)
+ , m_uniformSetup (uniformSetup)
+ , m_attribFunc (attribFunc)
+ , m_renderSize (100, 100)
+ , m_colorFormat (VK_FORMAT_R8G8B8A8_UNORM)
+{
+}
+
+ShaderRenderCaseInstance::~ShaderRenderCaseInstance (void)
+{
+}
+
+tcu::TestStatus ShaderRenderCaseInstance::iterate (void)
+{
+ setup();
+
+ // Create quad grid.
+ const tcu::IVec2 viewportSize = getViewportSize();
+ const int width = viewportSize.x();
+ const int height = viewportSize.y();
+
+ QuadGrid quadGrid (m_isVertexCase ? s_gridSize : 4, width, height, tcu::Vec4(0.125f, 0.25f, 0.5f, 1.0f), m_userAttribTransforms, m_textures);
+
+ // Render result.
+ tcu::Surface resImage (width, height);
+ render(resImage, quadGrid);
+
+ // Compute reference.
+ tcu::Surface refImage (width, height);
+ if (m_isVertexCase)
+ computeVertexReference(refImage, quadGrid);
+ else
+ computeFragmentReference(refImage, quadGrid);
+
+ // Compare.
+ const bool compareOk = compareImages(resImage, refImage, 0.05f);
+
+ if (compareOk)
+ return tcu::TestStatus::pass("Result image matches reference");
+ else
+ return tcu::TestStatus::fail("Image mismatch");
+}
+
+void ShaderRenderCaseInstance::setupUniformData (deUint32 bindingLocation, deUint32 size, const void* dataPtr)
+{
+ const VkDevice vkDevice = m_context.getDevice();
+ const DeviceInterface& vk = m_context.getDeviceInterface();
+ const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
+
+ const VkBufferCreateInfo uniformBufferParams =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkBufferCreateFlags flags;
+ size, // VkDeviceSize size;
+ VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, // VkBufferUsageFlags usage;
+ VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
+ 1u, // deUint32 queueFamilyCount;
+ &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
+ };
+
+ Move<VkBuffer> buffer = createBuffer(vk, vkDevice, &uniformBufferParams);
+ de::MovePtr<Allocation> alloc = m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *buffer), MemoryRequirement::HostVisible);
+ VK_CHECK(vk.bindBufferMemory(vkDevice, *buffer, alloc->getMemory(), alloc->getOffset()));
+
+ deMemcpy(alloc->getHostPtr(), dataPtr, size);
+ flushMappedMemoryRange(vk, vkDevice, alloc->getMemory(), alloc->getOffset(), size);
+
+ // \todo [2015-10-09 elecro] remove the 'hackPadding' variable if the driver support small uniforms,
+ // that is for example one float big uniforms.
+ const deUint32 hackPadding = size < 4 * sizeof(float) ? (deUint32)(3u * sizeof(float)) : 0u;
+
+ de::MovePtr<BufferUniform> uniformInfo(new BufferUniform());
+ uniformInfo->type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+ uniformInfo->descriptor = makeDescriptorBufferInfo(*buffer, 0u, size + hackPadding);
+ uniformInfo->location = bindingLocation;
+ uniformInfo->buffer = VkBufferSp(new vk::Unique<VkBuffer>(buffer));
+ uniformInfo->alloc = AllocationSp(alloc.release());
+
+ m_uniformInfos.push_back(UniformInfoSp(new de::UniquePtr<UniformInfo>(uniformInfo)));
+}
+
+void ShaderRenderCaseInstance::addUniform (deUint32 bindingLocation, vk::VkDescriptorType descriptorType, deUint32 dataSize, const void* data)
+{
+ m_descriptorSetLayoutBuilder.addSingleBinding(descriptorType, vk::VK_SHADER_STAGE_ALL);
+ m_descriptorPoolBuilder.addType(descriptorType);
+
+ setupUniformData(bindingLocation, dataSize, data);
+}
+
+void ShaderRenderCaseInstance::addAttribute (deUint32 bindingLocation,
+ vk::VkFormat format,
+ deUint32 sizePerElement,
+ deUint32 count,
+ const void* dataPtr)
+{
+ // Add binding specification
+ const deUint32 binding = (deUint32)m_vertexBindingDescription.size();
+ const VkVertexInputBindingDescription bindingDescription =
+ {
+ binding, // deUint32 binding;
+ sizePerElement, // deUint32 stride;
+ VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate stepRate;
+ };
+
+ m_vertexBindingDescription.push_back(bindingDescription);
+
+ // Add location and format specification
+ const VkVertexInputAttributeDescription attributeDescription =
+ {
+ bindingLocation, // deUint32 location;
+ binding, // deUint32 binding;
+ format, // VkFormat format;
+ 0u, // deUint32 offset;
+ };
+
+ m_vertexattributeDescription.push_back(attributeDescription);
+
+ // Upload data to buffer
+ const VkDevice vkDevice = m_context.getDevice();
+ const DeviceInterface& vk = m_context.getDeviceInterface();
+ const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
+
+ const VkDeviceSize inputSize = sizePerElement * count;
+ const VkBufferCreateInfo vertexBufferParams =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkBufferCreateFlags flags;
+ inputSize, // VkDeviceSize size;
+ VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
+ VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
+ 1u, // deUint32 queueFamilyCount;
+ &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
+ };
+
+ Move<VkBuffer> buffer = createBuffer(vk, vkDevice, &vertexBufferParams);
+ de::MovePtr<vk::Allocation> alloc = m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *buffer), MemoryRequirement::HostVisible);
+ VK_CHECK(vk.bindBufferMemory(vkDevice, *buffer, alloc->getMemory(), alloc->getOffset()));
+
+ deMemcpy(alloc->getHostPtr(), dataPtr, (size_t)inputSize);
+ flushMappedMemoryRange(vk, vkDevice, alloc->getMemory(), alloc->getOffset(), inputSize);
+
+ m_vertexBuffers.push_back(VkBufferSp(new vk::Unique<VkBuffer>(buffer)));
+ m_vertexBufferAllocs.push_back(AllocationSp(alloc.release()));
+}
+
+void ShaderRenderCaseInstance::useAttribute (deUint32 bindingLocation, BaseAttributeType type)
+{
+ const EnabledBaseAttribute attribute =
+ {
+ bindingLocation, // deUint32 location;
+ type // BaseAttributeType type;
+ };
+ m_enabledBaseAttributes.push_back(attribute);
+}
+
+void ShaderRenderCaseInstance::setup (void)
+{
+}
+
+void ShaderRenderCaseInstance::setupUniforms (const tcu::Vec4& constCoords)
+{
+ m_uniformSetup.setup(*this, constCoords);
+}
+
+void ShaderRenderCaseInstance::useUniform (deUint32 bindingLocation, BaseUniformType type)
+{
+ #define UNIFORM_CASE(type, value) case type: addUniform(bindingLocation, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, value); break
+
+ switch(type)
+ {
+ // Bool
+ UNIFORM_CASE(UB_FALSE, 0);
+ UNIFORM_CASE(UB_TRUE, 1);
+
+ // BVec4
+ UNIFORM_CASE(UB4_FALSE, tcu::Vec4(0));
+ UNIFORM_CASE(UB4_TRUE, tcu::Vec4(1));
+
+ // Integer
+ UNIFORM_CASE(UI_ZERO, 0);
+ UNIFORM_CASE(UI_ONE, 1);
+ UNIFORM_CASE(UI_TWO, 2);
+ UNIFORM_CASE(UI_THREE, 3);
+ UNIFORM_CASE(UI_FOUR, 4);
+ UNIFORM_CASE(UI_FIVE, 5);
+ UNIFORM_CASE(UI_SIX, 6);
+ UNIFORM_CASE(UI_SEVEN, 7);
+ UNIFORM_CASE(UI_EIGHT, 8);
+ UNIFORM_CASE(UI_ONEHUNDREDONE, 101);
+
+ // IVec2
+ UNIFORM_CASE(UI2_MINUS_ONE, tcu::IVec2(-1));
+ UNIFORM_CASE(UI2_ZERO, tcu::IVec2(0));
+ UNIFORM_CASE(UI2_ONE, tcu::IVec2(1));
+ UNIFORM_CASE(UI2_TWO, tcu::IVec2(2));
+ UNIFORM_CASE(UI2_THREE, tcu::IVec2(3));
+ UNIFORM_CASE(UI2_FOUR, tcu::IVec2(4));
+ UNIFORM_CASE(UI2_FIVE, tcu::IVec2(5));
+
+ // IVec3
+ UNIFORM_CASE(UI3_MINUS_ONE, tcu::IVec3(-1));
+ UNIFORM_CASE(UI3_ZERO, tcu::IVec3(0));
+ UNIFORM_CASE(UI3_ONE, tcu::IVec3(1));
+ UNIFORM_CASE(UI3_TWO, tcu::IVec3(2));
+ UNIFORM_CASE(UI3_THREE, tcu::IVec3(3));
+ UNIFORM_CASE(UI3_FOUR, tcu::IVec3(4));
+ UNIFORM_CASE(UI3_FIVE, tcu::IVec3(5));
+
+ // IVec4
+ UNIFORM_CASE(UI4_MINUS_ONE, tcu::IVec4(-1));
+ UNIFORM_CASE(UI4_ZERO, tcu::IVec4(0));
+ UNIFORM_CASE(UI4_ONE, tcu::IVec4(1));
+ UNIFORM_CASE(UI4_TWO, tcu::IVec4(2));
+ UNIFORM_CASE(UI4_THREE, tcu::IVec4(3));
+ UNIFORM_CASE(UI4_FOUR, tcu::IVec4(4));
+ UNIFORM_CASE(UI4_FIVE, tcu::IVec4(5));
+
+ // Float
+ UNIFORM_CASE(UF_ZERO, 0.0f);
+ UNIFORM_CASE(UF_ONE, 1.0f);
+ UNIFORM_CASE(UF_TWO, 2.0f);
+ UNIFORM_CASE(UF_THREE, 3.0f);
+ UNIFORM_CASE(UF_FOUR, 4.0f);
+ UNIFORM_CASE(UF_FIVE, 5.0f);
+ UNIFORM_CASE(UF_SIX, 6.0f);
+ UNIFORM_CASE(UF_SEVEN, 7.0f);
+ UNIFORM_CASE(UF_EIGHT, 8.0f);
+
+ UNIFORM_CASE(UF_HALF, 1.0f / 2.0f);
+ UNIFORM_CASE(UF_THIRD, 1.0f / 3.0f);
+ UNIFORM_CASE(UF_FOURTH, 1.0f / 4.0f);
+ UNIFORM_CASE(UF_FIFTH, 1.0f / 5.0f);
+ UNIFORM_CASE(UF_SIXTH, 1.0f / 6.0f);
+ UNIFORM_CASE(UF_SEVENTH, 1.0f / 7.0f);
+ UNIFORM_CASE(UF_EIGHTH, 1.0f / 8.0f);
+
+ // Vec2
+ UNIFORM_CASE(UV2_MINUS_ONE, tcu::Vec2(-1.0f));
+ UNIFORM_CASE(UV2_ZERO, tcu::Vec2(0.0f));
+ UNIFORM_CASE(UV2_ONE, tcu::Vec2(1.0f));
+ UNIFORM_CASE(UV2_TWO, tcu::Vec2(2.0f));
+ UNIFORM_CASE(UV2_THREE, tcu::Vec2(3.0f));
+
+ UNIFORM_CASE(UV2_HALF, tcu::Vec2(1.0f / 2.0f));
+
+ // Vec3
+ UNIFORM_CASE(UV3_MINUS_ONE, tcu::Vec3(-1.0f));
+ UNIFORM_CASE(UV3_ZERO, tcu::Vec3(0.0f));
+ UNIFORM_CASE(UV3_ONE, tcu::Vec3(1.0f));
+ UNIFORM_CASE(UV3_TWO, tcu::Vec3(2.0f));
+ UNIFORM_CASE(UV3_THREE, tcu::Vec3(3.0f));
+
+ UNIFORM_CASE(UV3_HALF, tcu::Vec3(1.0f / 2.0f));
+
+ // Vec4
+ UNIFORM_CASE(UV4_MINUS_ONE, tcu::Vec4(-1.0f));
+ UNIFORM_CASE(UV4_ZERO, tcu::Vec4(0.0f));
+ UNIFORM_CASE(UV4_ONE, tcu::Vec4(1.0f));
+ UNIFORM_CASE(UV4_TWO, tcu::Vec4(2.0f));
+ UNIFORM_CASE(UV4_THREE, tcu::Vec4(3.0f));
+
+ UNIFORM_CASE(UV4_HALF, tcu::Vec4(1.0f / 2.0f));
+
+ UNIFORM_CASE(UV4_BLACK, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
+ UNIFORM_CASE(UV4_GRAY, tcu::Vec4(0.5f, 0.5f, 0.5f, 1.0f));
+ UNIFORM_CASE(UV4_WHITE, tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
+
+ default:
+ m_context.getTestContext().getLog() << tcu::TestLog::Message << "Unknown Uniform type: " << type << tcu::TestLog::EndMessage;
+ break;
+ }
+
+ #undef UNIFORM_CASE
+}
+
+const tcu::IVec2 ShaderRenderCaseInstance::getViewportSize (void) const
+{
+ return tcu::IVec2(de::min(m_renderSize.x(), s_maxRenderWidth),
+ de::min(m_renderSize.y(), s_maxRenderHeight));
+}
+
+Move<VkImage> ShaderRenderCaseInstance::createImage2D (const tcu::Texture2D& texture,
+ const VkFormat format,
+ const VkImageUsageFlags usage,
+ const VkImageTiling tiling)
+{
+ const VkDevice vkDevice = m_context.getDevice();
+ const DeviceInterface& vk = m_context.getDeviceInterface();
+ const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
+
+ const VkImageCreateInfo imageCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0, // VkImageCreateFlags flags;
+ VK_IMAGE_TYPE_2D, // VkImageType imageType;
+ format, // VkFormat format;
+ { texture.getWidth(), texture.getHeight(), 1 }, // VkExtend3D extent;
+ 1u, // deUint32 mipLevels;
+ 1u, // deUint32 arraySize;
+ VK_SAMPLE_COUNT_1_BIT, // deUint32 samples;
+ tiling, // VkImageTiling tiling;
+ usage, // VkImageUsageFlags usage;
+ VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
+ 1, // deuint32 queueFamilyCount;
+ &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
+ VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
+ };
+
+ Move<VkImage> vkTexture = createImage(vk, vkDevice, &imageCreateInfo);
+ return vkTexture;
+}
+
+de::MovePtr<Allocation> ShaderRenderCaseInstance::uploadImage2D (const tcu::Texture2D& refTexture,
+ const VkImage& vkTexture)
+{
+ const VkDevice vkDevice = m_context.getDevice();
+ const DeviceInterface& vk = m_context.getDeviceInterface();
+
+ de::MovePtr<Allocation> allocation = m_memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, vkTexture), MemoryRequirement::HostVisible);
+ VK_CHECK(vk.bindImageMemory(vkDevice, vkTexture, allocation->getMemory(), allocation->getOffset()));
+
+ const VkImageSubresource subres =
+ {
+ VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
+ 0u, // deUint32 mipLevel;
+ 0u // deUint32 arraySlice
+ };
+
+ VkSubresourceLayout layout;
+ vk.getImageSubresourceLayout(vkDevice, vkTexture, &subres, &layout);
+
+ tcu::ConstPixelBufferAccess access = refTexture.getLevel(0);
+ tcu::PixelBufferAccess destAccess (refTexture.getFormat(), refTexture.getWidth(), refTexture.getHeight(), 1, allocation->getHostPtr());
+
+ tcu::copy(destAccess, access);
+
+ flushMappedMemoryRange(vk, vkDevice, allocation->getMemory(), allocation, layout.size);
+
+ return allocation;
+}
+
+void ShaderRenderCaseInstance::copyTilingImageToOptimal (const vk::VkImage& srcImage,
+ const vk::VkImage& dstImage,
+ deInt32 width,
+ deInt32 height)
+{
+ const VkDevice vkDevice = m_context.getDevice();
+ const DeviceInterface& vk = m_context.getDeviceInterface();
+ const VkQueue queue = m_context.getUniversalQueue();
+ const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
+
+ // Create command pool
+ const VkCommandPoolCreateInfo cmdPoolParams =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // VkCmdPoolCreateFlags flags;
+ queueFamilyIndex, // deUint32 queueFamilyIndex;
+ };
+
+ Move<VkCommandPool> cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams);
+
+ // Create command buffer
+ const VkCommandBufferAllocateInfo cmdBufferParams =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ *cmdPool, // VkCommandPool commandPool;
+ VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
+ 0u // deUint32 bufferCount;
+ };
+
+ const VkCommandBufferUsageFlags usageFlags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
+ const VkCommandBufferBeginInfo cmdBufferBeginInfo =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ usageFlags, // VkCommandBufferUsageFlags flags;
+ DE_NULL, // VkRenderPass renderPass;
+ 0u, // deUint32 subpass;
+ DE_NULL, // VkFramebuffer framebuffer;
+ VK_FALSE, // VkBool32 occlusionQueryEnable;
+ (VkQueryControlFlags)0,
+ (VkQueryPipelineStatisticFlags)0,
+ };
+
+ Move<VkCommandBuffer> cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferParams);
+
+ VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
+
+ // Add image barriers
+ const VkImageMemoryBarrier layoutBarriers[2] =
+ {
+ createImageMemoryBarrier(srcImage, (VkAccessFlags)0u, (VkAccessFlags)0u, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL),
+ createImageMemoryBarrier(dstImage, (VkAccessFlags)0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
+ };
+
+ for (deUint32 barrierNdx = 0; barrierNdx < DE_LENGTH_OF_ARRAY(layoutBarriers); barrierNdx++)
+ {
+ const VkImageMemoryBarrier* memoryBarrier = &layoutBarriers[barrierNdx];
+ vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, 1, (const void * const*)&memoryBarrier);
+ }
+
+ // Add image copy
+ const VkImageCopy imageCopy =
+ {
+ {
+ VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspect aspect;
+ 0u, // deUint32 mipLevel;
+ 0u, // deUint32 arrayLayer;
+ 1u // deUint32 arraySize;
+ }, // VkImageSubresourceCopy srcSubresource;
+ {
+ 0, // int32 x;
+ 0, // int32 y;
+ 0 // int32 z;
+ }, // VkOffset3D srcOffset;
+ {
+ VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspect aspect;
+ 0u, // deUint32 mipLevel;
+ 0u, // deUint32 arrayLayer;
+ 1u // deUint32 arraySize;
+ }, // VkImageSubresourceCopy destSubResource;
+ {
+ 0, // int32 x;
+ 0, // int32 y;
+ 0 // int32 z;
+ }, // VkOffset3D dstOffset;
+ {
+ width, // int32 width;
+ height, // int32 height;
+ 1, // int32 depth
+ } // VkExtent3D extent;
+ };
+
+ vk.cmdCopyImage(*cmdBuffer, srcImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dstImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &imageCopy);
+
+ // Add destination barrier
+ const VkImageMemoryBarrier dstBarrier =
+ createImageMemoryBarrier(dstImage, VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT, 0u, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
+
+ const void* const* barrier = (const void* const*)&dstBarrier;
+ vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, 1, (const void* const*)&barrier);
+
+ VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
+
+ const VkFenceCreateInfo fenceParams =
+ {
+ VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u // VkFenceCreateFlags flags;
+ };
+ const Unique<VkFence> fence (createFence(vk, vkDevice, &fenceParams));
+ const VkSubmitInfo submitInfo =
+ {
+ VK_STRUCTURE_TYPE_SUBMIT_INFO,
+ DE_NULL,
+ 0u,
+ (const VkSemaphore*)DE_NULL,
+ 1u,
+ &cmdBuffer.get(),
+ 0u,
+ (const VkSemaphore*)DE_NULL,
+ };
+
+
+ // Execute copy
+ VK_CHECK(vk.resetFences(vkDevice, 1, &fence.get()));
+ VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
+ VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), true, ~(0ull) /* infinity*/));
+}
+
+void ShaderRenderCaseInstance::useSampler2D (deUint32 bindingLocation, deUint32 textureID)
+{
+ DE_ASSERT(textureID < m_textures.size());
+
+ const VkDevice vkDevice = m_context.getDevice();
+ const DeviceInterface& vk = m_context.getDeviceInterface();
+ const TextureBinding& textureBinding = *m_textures[textureID];
+ const tcu::Texture2D& refTexture = textureBinding.get2D();
+ const tcu::Sampler& refSampler = textureBinding.getSampler();
+ const VkFormat format = refTexture.getFormat() == tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)
+ ? VK_FORMAT_R8G8B8A8_UNORM
+ : VK_FORMAT_R8G8B8_UNORM;
+
+ // Create & alloc the image
+ Move<VkImage> vkTexture;
+ de::MovePtr<Allocation> allocation;
+
+ if (isSupportedLinearTilingFormat(m_context.getInstanceInterface(), m_context.getPhysicalDevice(), format))
+ {
+ vkTexture = createImage2D(refTexture, format, VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_TILING_LINEAR);
+ allocation = uploadImage2D(refTexture, *vkTexture);
+ }
+ else if (isSupportedOptimalTilingFormat(m_context.getInstanceInterface(), m_context.getPhysicalDevice(), format))
+ {
+ Move<VkImage> stagingTexture (createImage2D(refTexture, format, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_IMAGE_TILING_LINEAR));
+ de::MovePtr<Allocation> stagingAlloc (uploadImage2D(refTexture, *stagingTexture));
+
+ const VkImageUsageFlags dstUsageFlags = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
+ vkTexture = createImage2D(refTexture, format, dstUsageFlags, VK_IMAGE_TILING_OPTIMAL);
+ allocation = m_memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *vkTexture), MemoryRequirement::Any);
+ VK_CHECK(vk.bindImageMemory(vkDevice, *vkTexture, allocation->getMemory(), allocation->getOffset()));
+
+ copyTilingImageToOptimal(*stagingTexture, *vkTexture, refTexture.getWidth(), refTexture.getHeight());
+ }
+ else
+ {
+ TCU_THROW(InternalError, "Unable to create 2D image");
+ }
+
+ // Create sampler
+ const bool compareEnabled = (refSampler.compare != tcu::Sampler::COMPAREMODE_NONE);
+ const VkSamplerCreateInfo samplerParams =
+ {
+ VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkSamplerCreateFlags)0,
+ mapFilterMode(refSampler.magFilter), // VkTexFilter magFilter;
+ mapFilterMode(refSampler.minFilter), // VkTexFilter minFilter;
+ mapMipmapMode(refSampler.minFilter), // VkTexMipmapMode mipMode;
+ mapWrapMode(refSampler.wrapS), // VkTexAddressMode addressModeU;
+ mapWrapMode(refSampler.wrapT), // VkTexAddressMode addressModeV;
+ mapWrapMode(refSampler.wrapR), // VkTexAddressMode addressModeW;
+ refSampler.lodThreshold, // float mipLodBias;
+ 1, // float maxAnisotropy;
+ compareEnabled, // VkBool32 compareEnable;
+ mapCompareMode(refSampler.compare), // VkCompareOp compareOp;
+ 0.0f, // float minLod;
+ 0.0f, // float maxLod;
+ VK_BORDER_COLOR_INT_OPAQUE_WHITE, // VkBorderColor boderColor;
+ VK_FALSE, // VkBool32 unnormalizerdCoordinates;
+ };
+
+ Move<VkSampler> sampler = createSampler(vk, vkDevice, &samplerParams);
+
+ const VkImageViewCreateInfo viewParams =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
+ NULL, // const voide* pNext;
+ 0u, // VkImageViewCreateFlags flags;
+ *vkTexture, // VkImage image;
+ VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
+ format, // VkFormat format;
+ {
+ VK_COMPONENT_SWIZZLE_R, // VkChannelSwizzle r;
+ VK_COMPONENT_SWIZZLE_G, // VkChannelSwizzle g;
+ VK_COMPONENT_SWIZZLE_B, // VkChannelSwizzle b;
+ VK_COMPONENT_SWIZZLE_A // VkChannelSwizzle a;
+ }, // VkChannelMapping channels;
+ {
+ VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
+ 0, // deUint32 baseMipLevel;
+ 1, // deUint32 mipLevels;
+ 0, // deUint32 baseArraySlice;
+ 1 // deUint32 arraySize;
+ }, // VkImageSubresourceRange subresourceRange;
+ };
+
+ Move<VkImageView> imageView = createImageView(vk, vkDevice, &viewParams);
+
+ const vk::VkDescriptorImageInfo descriptor =
+ {
+ sampler.get(), // VkSampler sampler;
+ imageView.get(), // VkImageView imageView;
+ VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout imageLayout;
+ };
+
+ de::MovePtr<SamplerUniform> uniform(new SamplerUniform());
+ uniform->type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+ uniform->descriptor = descriptor;
+ uniform->location = bindingLocation;
+ uniform->image = VkImageSp(new vk::Unique<VkImage>(vkTexture));
+ uniform->imageView = VkImageViewSp(new vk::Unique<VkImageView>(imageView));
+ uniform->sampler = VkSamplerSp(new vk::Unique<VkSampler>(sampler));
+ uniform->alloc = AllocationSp(allocation.release());
+
+ m_descriptorSetLayoutBuilder.addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, vk::VK_SHADER_STAGE_ALL, &uniform->descriptor.sampler);
+ m_descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
+
+ m_uniformInfos.push_back(UniformInfoSp(new de::UniquePtr<UniformInfo>(uniform)));
+}
+
+void ShaderRenderCaseInstance::setupDefaultInputs (const QuadGrid& quadGrid)
+{
+ /* Configuration of the vertex input attributes:
+ a_position is at location 0
+ a_coords is at location 1
+ a_unitCoords is at location 2
+ a_one is at location 3
+
+ User attributes starts from at the location 4.
+ */
+ addAttribute(0u, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(tcu::Vec4), quadGrid.getNumVertices(), quadGrid.getPositions());
+ addAttribute(1u, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(tcu::Vec4), quadGrid.getNumVertices(), quadGrid.getCoords());
+ addAttribute(2u, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(tcu::Vec4), quadGrid.getNumVertices(), quadGrid.getUnitCoords());
+ addAttribute(3u, VK_FORMAT_R32_SFLOAT, sizeof(float), quadGrid.getNumVertices(), quadGrid.getAttribOne());
+
+ static const struct
+ {
+ BaseAttributeType type;
+ int userNdx;
+ } userAttributes[] =
+ {
+ { A_IN0, 0 },
+ { A_IN1, 1 },
+ { A_IN2, 2 },
+ { A_IN3, 3 }
+ };
+
+ static const struct
+ {
+ BaseAttributeType matrixType;
+ int numCols;
+ int numRows;
+ } matrices[] =
+ {
+ { MAT2, 2, 2 },
+ { MAT2x3, 2, 3 },
+ { MAT2x4, 2, 4 },
+ { MAT3x2, 3, 2 },
+ { MAT3, 3, 3 },
+ { MAT3x4, 3, 4 },
+ { MAT4x2, 4, 2 },
+ { MAT4x3, 4, 3 },
+ { MAT4, 4, 4 }
+ };
+
+ for (size_t attrNdx = 0; attrNdx < m_enabledBaseAttributes.size(); attrNdx++)
+ {
+ for (int userNdx = 0; userNdx < DE_LENGTH_OF_ARRAY(userAttributes); userNdx++)
+ {
+ if (userAttributes[userNdx].type != m_enabledBaseAttributes[attrNdx].type)
+ continue;
+
+ addAttribute(m_enabledBaseAttributes[attrNdx].location, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(tcu::Vec4), quadGrid.getNumVertices(), quadGrid.getUserAttrib(userNdx));
+ }
+
+ for (int matNdx = 0; matNdx < DE_LENGTH_OF_ARRAY(matrices); matNdx++)
+ {
+
+ if (matrices[matNdx].matrixType != m_enabledBaseAttributes[attrNdx].type)
+ continue;
+
+ const int numCols = matrices[matNdx].numCols;
+
+ for (int colNdx = 0; colNdx < numCols; colNdx++)
+ {
+ addAttribute(m_enabledBaseAttributes[attrNdx].location + colNdx, VK_FORMAT_R32G32B32A32_SFLOAT, (deUint32)(4 * sizeof(float)), quadGrid.getNumVertices(), quadGrid.getUserAttrib(colNdx));
+ }
+ }
+ }
+}
+
+void ShaderRenderCaseInstance::render (tcu::Surface& result, const QuadGrid& quadGrid)
+{
+ const VkDevice vkDevice = m_context.getDevice();
+ const DeviceInterface& vk = m_context.getDeviceInterface();
+ const VkQueue queue = m_context.getUniversalQueue();
+ const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
+
+ // Create color image
+ {
+ const VkImageCreateInfo colorImageParams =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkImageCreateFlags flags;
+ VK_IMAGE_TYPE_2D, // VkImageType imageType;
+ m_colorFormat, // VkFormat format;
+ { m_renderSize.x(), m_renderSize.y(), 1u }, // VkExtent3D extent;
+ 1u, // deUint32 mipLevels;
+ 1u, // deUint32 arraySize;
+ VK_SAMPLE_COUNT_1_BIT, // deUint32 samples;
+ VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
+ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
+ VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
+ 1u, // deUint32 queueFamilyCount;
+ &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
+ VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
+ };
+
+ m_colorImage = createImage(vk, vkDevice, &colorImageParams);
+
+ // Allocate and bind color image memory
+ m_colorImageAlloc = m_memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
+ VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
+ }
+
+ // Create color attachment view
+ {
+ const VkImageViewCreateInfo colorImageViewParams =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkImageViewCreateFlags flags;
+ *m_colorImage, // VkImage image;
+ VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
+ m_colorFormat, // VkFormat format;
+ {
+ VK_COMPONENT_SWIZZLE_R, // VkChannelSwizzle r;
+ VK_COMPONENT_SWIZZLE_G, // VkChannelSwizzle g;
+ VK_COMPONENT_SWIZZLE_B, // VkChannelSwizzle b;
+ VK_COMPONENT_SWIZZLE_A // VkChannelSwizzle a;
+ }, // VkChannelMapping channels;
+ {
+ VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
+ 0, // deUint32 baseMipLevel;
+ 1, // deUint32 mipLevels;
+ 0, // deUint32 baseArraySlice;
+ 1 // deUint32 arraySize;
+ }, // VkImageSubresourceRange subresourceRange;
+ };
+
+ m_colorImageView = createImageView(vk, vkDevice, &colorImageViewParams);
+ }
+
+ // Create render pass
+ {
+ const VkAttachmentDescription attachmentDescription =
+ {
+ (VkAttachmentDescriptionFlags)0,
+ m_colorFormat, // VkFormat format;
+ VK_SAMPLE_COUNT_1_BIT, // deUint32 samples;
+ VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
+ VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
+ VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
+ VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout;
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
+ };
+
+ const VkAttachmentReference attachmentReference =
+ {
+ 0u, // deUint32 attachment;
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
+ };
+
+ const VkSubpassDescription subpassDescription =
+ {
+ 0u, // VkSubpassDescriptionFlags flags;
+ VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
+ 0u, // deUint32 inputCount;
+ DE_NULL, // constVkAttachmentReference* pInputAttachments;
+ 1u, // deUint32 colorCount;
+ &attachmentReference, // constVkAttachmentReference* pColorAttachments;
+ DE_NULL, // constVkAttachmentReference* pResolveAttachments;
+ DE_NULL, // VkAttachmentReference depthStencilAttachment;
+ 0u, // deUint32 preserveCount;
+ DE_NULL // constVkAttachmentReference* pPreserveAttachments;
+ };
+
+ const VkRenderPassCreateInfo renderPassParams =
+ {
+ VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkRenderPassCreateFlags)0,
+ 1u, // deUint32 attachmentCount;
+ &attachmentDescription, // const VkAttachmentDescription* pAttachments;
+ 1u, // deUint32 subpassCount;
+ &subpassDescription, // const VkSubpassDescription* pSubpasses;
+ 0u, // deUint32 dependencyCount;
+ DE_NULL // const VkSubpassDependency* pDependencies;
+ };
+
+ m_renderPass = createRenderPass(vk, vkDevice, &renderPassParams);
+ }
+
+ // Create framebuffer
+ {
+ const VkFramebufferCreateInfo framebufferParams =
+ {
+ VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkFramebufferCreateFlags)0,
+ *m_renderPass, // VkRenderPass renderPass;
+ 1u, // deUint32 attachmentCount;
+ &*m_colorImageView, // const VkImageView* pAttachments;
+ (deUint32)m_renderSize.x(), // deUint32 width;
+ (deUint32)m_renderSize.y(), // deUint32 height;
+ 1u // deUint32 layers;
+ };
+
+ m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
+ }
+
+ // Create descriptors
+ {
+ setupUniforms(quadGrid.getConstCoords());
+
+ m_descriptorSetLayout = m_descriptorSetLayoutBuilder.build(vk, vkDevice);
+ m_descriptorPool = m_descriptorPoolBuilder.build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
+
+ {
+ const VkDescriptorSetAllocateInfo allocInfo =
+ {
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+ DE_NULL,
+ *m_descriptorPool,
+ 1u,
+ &m_descriptorSetLayout.get(),
+ };
+
+ m_descriptorSet = allocateDescriptorSet(vk, vkDevice, &allocInfo);
+ }
+
+ for (deUint32 i = 0; i < m_uniformInfos.size(); i++)
+ {
+ const UniformInfo* uniformInfo = m_uniformInfos[i].get()->get();
+ deUint32 location = uniformInfo->location;
+
+ if (uniformInfo->type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
+ {
+ const BufferUniform* bufferInfo = dynamic_cast<const BufferUniform*>(uniformInfo);
+
+ m_descriptorSetUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(location), uniformInfo->type, &bufferInfo->descriptor);
+ }
+ else if (uniformInfo->type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
+ {
+ const SamplerUniform* samplerInfo = dynamic_cast<const SamplerUniform*>(uniformInfo);
+
+ m_descriptorSetUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(location), uniformInfo->type, &samplerInfo->descriptor);
+ }
+ else
+ DE_FATAL("Impossible");
+ }
+
+ m_descriptorSetUpdateBuilder.update(vk, vkDevice);
+ }
+
+ // Create pipeline layout
+ {
+ const VkPipelineLayoutCreateInfo pipelineLayoutParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkPipelineLayoutCreateFlags)0,
+ 1u, // deUint32 descriptorSetCount;
+ &*m_descriptorSetLayout, // const VkDescriptorSetLayout* pSetLayouts;
+ 0u, // deUint32 pushConstantRangeCount;
+ DE_NULL // const VkPushConstantRange* pPushConstantRanges;
+ };
+
+ m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
+ }
+
+ // Create shaders
+ {
+ m_vertexShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("vert"), 0);
+ m_fragmentShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("frag"), 0);
+ }
+
+ // Create pipeline
+ {
+ const VkPipelineShaderStageCreateInfo shaderStageParams[2] =
+ {
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkPipelineShaderStageCreateFlags)0,
+ VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStage stage;
+ *m_vertexShaderModule, // VkShader shader;
+ "main",
+ DE_NULL // const VkSpecializationInfo* pSpecializationInfo;
+ },
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkPipelineShaderStageCreateFlags)0,
+ VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStage stage;
+ *m_fragmentShaderModule, // VkShader shader;
+ "main",
+ DE_NULL // const VkSpecializationInfo* pSpecializationInfo;
+ }
+ };
+
+ // Add test case specific attributes
+ if (m_attribFunc)
+ m_attribFunc(*this, quadGrid.getNumVertices());
+
+ // Add base attributes
+ setupDefaultInputs(quadGrid);
+
+ const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkPipelineVertexInputStateCreateFlags)0,
+ (deUint32)m_vertexBindingDescription.size(), // deUint32 bindingCount;
+ &m_vertexBindingDescription[0], // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
+ (deUint32)m_vertexattributeDescription.size(), // deUint32 attributeCount;
+ &m_vertexattributeDescription[0], // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
+ };
+
+ const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkPipelineInputAssemblyStateCreateFlags)0,
+ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology topology;
+ false // VkBool32 primitiveRestartEnable;
+ };
+
+ const VkViewport viewport =
+ {
+ 0.0f, // float originX;
+ 0.0f, // float originY;
+ (float)m_renderSize.x(), // float width;
+ (float)m_renderSize.y(), // float height;
+ 0.0f, // float minDepth;
+ 1.0f // float maxDepth;
+ };
+
+ const VkRect2D scissor =
+ {
+ {
+ 0u, // deUint32 x;
+ 0u, // deUint32 y;
+ }, // VkOffset2D offset;
+ {
+ m_renderSize.x(), // deUint32 width;
+ m_renderSize.y(), // deUint32 height;
+ }, // VkExtent2D extent;
+ };
+
+ const VkPipelineViewportStateCreateInfo viewportStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkPipelineViewportStateCreateFlags)0,
+ 1u, // deUint32 viewportCount;
+ &viewport, // const VkViewport* pViewports;
+ 1u, // deUint32 scissorsCount;
+ &scissor, // const VkRect2D* pScissors;
+ };
+
+ const VkPipelineRasterizationStateCreateInfo rasterStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkPipelineRasterizationStateCreateFlags)0,
+ false, // VkBool32 depthClipEnable;
+ false, // VkBool32 rasterizerDiscardEnable;
+ VK_POLYGON_MODE_FILL, // VkFillMode fillMode;
+ VK_CULL_MODE_NONE, // VkCullMode cullMode;
+ VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
+ false, // VkBool32 depthBiasEnable;
+ 0.0f, // float depthBias;
+ 0.0f, // float depthBiasClamp;
+ 0.0f, // float slopeScaledDepthBias;
+ 1.0f, // float lineWidth;
+ };
+
+ const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
+ {
+ false, // VkBool32 blendEnable;
+ VK_BLEND_FACTOR_ONE, // VkBlend srcBlendColor;
+ VK_BLEND_FACTOR_ZERO, // VkBlend destBlendColor;
+ VK_BLEND_OP_ADD, // VkBlendOp blendOpColor;
+ VK_BLEND_FACTOR_ONE, // VkBlend srcBlendAlpha;
+ VK_BLEND_FACTOR_ZERO, // VkBlend destBlendAlpha;
+ VK_BLEND_OP_ADD, // VkBlendOp blendOpAlpha;
+ (VK_COLOR_COMPONENT_R_BIT |
+ VK_COLOR_COMPONENT_G_BIT |
+ VK_COLOR_COMPONENT_B_BIT |
+ VK_COLOR_COMPONENT_A_BIT), // VkChannelFlags channelWriteMask;
+ };
+
+ const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkPipelineColorBlendStateCreateFlags)0,
+ false, // VkBool32 logicOpEnable;
+ VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
+ 1u, // deUint32 attachmentCount;
+ &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
+ { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConst[4];
+ };
+
+ const VkPipelineDynamicStateCreateInfo dynamicStateInfo =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkPipelineDynamicStateCreateFlags)0,
+ 0u, // deUint32 dynamicStateCount;
+ DE_NULL // const VkDynamicState* pDynamicStates;
+ };
+
+ const VkGraphicsPipelineCreateInfo graphicsPipelineParams =
+ {
+ VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineCreateFlags flags;
+ 2u, // deUint32 stageCount;
+ shaderStageParams, // const VkPipelineShaderStageCreateInfo* pStages;
+ &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
+ &inputAssemblyStateParams, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
+ DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
+ &viewportStateParams, // const VkPipelineViewportStateCreateInfo* pViewportState;
+ &rasterStateParams, // const VkPipelineRasterStateCreateInfo* pRasterState;
+ DE_NULL, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
+ DE_NULL, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
+ &colorBlendStateParams, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
+ &dynamicStateInfo, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
+ *m_pipelineLayout, // VkPipelineLayout layout;
+ *m_renderPass, // VkRenderPass renderPass;
+ 0u, // deUint32 subpass;
+ 0u, // VkPipeline basePipelineHandle;
+ 0u // deInt32 basePipelineIndex;
+ };
+
+ m_graphicsPipeline = createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams);
+ }
+
+ // Create vertex indices buffer
+ {
+ const VkDeviceSize indiceBufferSize = quadGrid.getNumTriangles() * 3 * sizeof(deUint16);
+ const VkBufferCreateInfo indiceBufferParams =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkBufferCreateFlags flags;
+ indiceBufferSize, // VkDeviceSize size;
+ VK_BUFFER_USAGE_INDEX_BUFFER_BIT, // VkBufferUsageFlags usage;
+ VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
+ 1u, // deUint32 queueFamilyCount;
+ &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
+ };
+
+ m_indiceBuffer = createBuffer(vk, vkDevice, &indiceBufferParams);
+ m_indiceBufferAlloc = m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_indiceBuffer), MemoryRequirement::HostVisible);
+
+ VK_CHECK(vk.bindBufferMemory(vkDevice, *m_indiceBuffer, m_indiceBufferAlloc->getMemory(), m_indiceBufferAlloc->getOffset()));
+
+ // Load vertice indices into buffer
+ deMemcpy(m_indiceBufferAlloc->getHostPtr(), quadGrid.getIndices(), (size_t)indiceBufferSize);
+ flushMappedMemoryRange(vk, vkDevice, m_indiceBufferAlloc->getMemory(), m_indiceBufferAlloc->getOffset(), indiceBufferSize);
+ }
+
+ // Create command pool
+ {
+ const VkCommandPoolCreateInfo cmdPoolParams =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // VkCmdPoolCreateFlags flags;
+ queueFamilyIndex, // deUint32 queueFamilyIndex;
+ };
+
+ m_cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams);
+ }
+
+ // Create command buffer
+ {
+ const VkCommandBufferAllocateInfo cmdBufferParams =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ *m_cmdPool, // VkCmdPool cmdPool;
+ VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCmdBufferLevel level;
+ 1u // deUint32 bufferCount;
+ };
+
+ const VkCommandBufferBeginInfo cmdBufferBeginInfo =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkCmdBufferOptimizeFlags flags;
+ DE_NULL, // VkRenderPass renderPass;
+ 0u, // deUint32 subpass;
+ DE_NULL, // VkFramebuffer framebuffer;
+ VK_FALSE,
+ (VkQueryControlFlags)0,
+ (VkQueryPipelineStatisticFlags)0,
+ };
+
+ const VkClearValue clearValues = makeClearValueColorF32(m_clearColor.x(),
+ m_clearColor.y(),
+ m_clearColor.z(),
+ m_clearColor.w());
+
+ const VkRenderPassBeginInfo renderPassBeginInfo =
+ {
+ VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ *m_renderPass, // VkRenderPass renderPass;
+ *m_framebuffer, // VkFramebuffer framebuffer;
+ { { 0, 0 }, {m_renderSize.x(), m_renderSize.y() } }, // VkRect2D renderArea;
+ 1, // deUint32 clearValueCount;
+ &clearValues, // const VkClearValue* pClearValues;
+ };
+
+ m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferParams);
+
+ VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
+
+ // Add texture barriers
+ std::vector<VkImageMemoryBarrier> barriers;
+ std::vector<void*> barrierPtrs;
+
+ for(deUint32 i = 0; i < m_uniformInfos.size(); i++)
+ {
+ const UniformInfo* uniformInfo = m_uniformInfos[i].get()->get();
+
+ if (uniformInfo->type != VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
+ {
+ continue;
+ }
+
+ const SamplerUniform* sampler = static_cast<const SamplerUniform*>(uniformInfo);
+
+ const VkAccessFlags outputMask = VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
+ const VkImageMemoryBarrier textureBarrier = createImageMemoryBarrier(sampler->image->get(), outputMask, 0u, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
+
+ barriers.push_back(textureBarrier);
+ barrierPtrs.push_back((void*)&barriers.back());
+ }
+
+ vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, (deUint32)barrierPtrs.size(), (barrierPtrs.size() ? (const void * const*)&barrierPtrs[0] : DE_NULL));
+
+ vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
+
+ vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline);
+ vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1, &*m_descriptorSet, 0u, DE_NULL);
+ vk.cmdBindIndexBuffer(*m_cmdBuffer, *m_indiceBuffer, 0, VK_INDEX_TYPE_UINT16);
+
+ const deUint32 numberOfVertexAttributes = (deUint32)m_vertexBuffers.size();
+ const std::vector<VkDeviceSize> offsets(numberOfVertexAttributes, 0);
+
+ std::vector<VkBuffer> buffers(numberOfVertexAttributes);
+ for (size_t i = 0; i < numberOfVertexAttributes; i++)
+ {
+ buffers[i] = m_vertexBuffers[i].get()->get();
+ }
+
+ vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, numberOfVertexAttributes, &buffers[0], &offsets[0]);
+ vk.cmdDrawIndexed(*m_cmdBuffer, quadGrid.getNumTriangles() * 3, 1, 0, 0, 0);
+
+ vk.cmdEndRenderPass(*m_cmdBuffer);
+ VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
+ }
+
+ // Create fence
+ {
+ const VkFenceCreateInfo fenceParams =
+ {
+ VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u // VkFenceCreateFlags flags;
+ };
+ m_fence = createFence(vk, vkDevice, &fenceParams);
+ }
+
+ // Execute Draw
+ {
+ const VkSubmitInfo submitInfo =
+ {
+ VK_STRUCTURE_TYPE_SUBMIT_INFO,
+ DE_NULL,
+ 0u,
+ (const VkSemaphore*)DE_NULL,
+ 1u,
+ &m_cmdBuffer.get(),
+ 0u,
+ (const VkSemaphore*)DE_NULL,
+ };
+
+ VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
+ VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
+ VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity*/));
+ }
+
+ // Read back the result
+ {
+ const VkDeviceSize imageSizeBytes = (VkDeviceSize)(sizeof(deUint32) * m_renderSize.x() * m_renderSize.y());
+ const VkBufferCreateInfo readImageBufferParams =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkBufferCreateFlags flags;
+ imageSizeBytes, // VkDeviceSize size;
+ VK_BUFFER_USAGE_TRANSFER_DST_BIT, // VkBufferUsageFlags usage;
+ VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
+ 1u, // deUint32 queueFamilyCount;
+ &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
+ };
+ const Unique<VkBuffer> readImageBuffer (createBuffer(vk, vkDevice, &readImageBufferParams));
+ const de::UniquePtr<Allocation> readImageBufferMemory (m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *readImageBuffer), MemoryRequirement::HostVisible));
+
+ VK_CHECK(vk.bindBufferMemory(vkDevice, *readImageBuffer, readImageBufferMemory->getMemory(), readImageBufferMemory->getOffset()));
+
+ // Copy image to buffer
+ const VkCommandBufferAllocateInfo cmdBufferParams =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ *m_cmdPool, // VkCmdPool cmdPool;
+ VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCmdBufferLevel level;
+ 1u // deUint32 bufferCount;
+ };
+
+ const VkCommandBufferBeginInfo cmdBufferBeginInfo =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkCmdBufferOptimizeFlags flags;
+ DE_NULL, // VkRenderPass renderPass;
+ 0u, // deUint32 subpass;
+ DE_NULL, // VkFramebuffer framebuffer;
+ VK_FALSE,
+ (VkQueryControlFlags)0,
+ (VkQueryPipelineStatisticFlags)0,
+ };
+
+ const Move<VkCommandBuffer> cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferParams);
+
+ const VkBufferImageCopy copyParams =
+ {
+ 0u, // VkDeviceSize bufferOffset;
+ (deUint32)m_renderSize.x(), // deUint32 bufferRowLength;
+ (deUint32)m_renderSize.y(), // deUint32 bufferImageHeight;
+ {
+ VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspect aspect;
+ 0u, // deUint32 mipLevel;
+ 0u, // deUint32 arraySlice;
+ 1u, // deUint32 arraySize;
+ }, // VkImageSubresourceCopy imageSubresource;
+ { 0u, 0u, 0u }, // VkOffset3D imageOffset;
+ { m_renderSize.x(), m_renderSize.y(), 1u } // VkExtent3D imageExtent;
+ };
+ const VkSubmitInfo submitInfo =
+ {
+ VK_STRUCTURE_TYPE_SUBMIT_INFO,
+ DE_NULL,
+ 0u,
+ (const VkSemaphore*)DE_NULL,
+ 1u,
+ &cmdBuffer.get(),
+ 0u,
+ (const VkSemaphore*)DE_NULL,
+ };
+
+ VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
+ vk.cmdCopyImageToBuffer(*cmdBuffer, *m_colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *readImageBuffer, 1u, ©Params);
+ VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
+
+ VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
+ VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
+ VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity */));
+
+ invalidateMappedMemoryRange(vk, vkDevice, readImageBufferMemory->getMemory(), readImageBufferMemory->getOffset(), imageSizeBytes);
+
+ const tcu::TextureFormat resultFormat (tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
+ const tcu::ConstPixelBufferAccess resultAccess (resultFormat, m_renderSize.x(), m_renderSize.y(), 1, readImageBufferMemory->getHostPtr());
+
+ tcu::copy(result.getAccess(), resultAccess);
+ }
+}
+
+void ShaderRenderCaseInstance::computeVertexReference (tcu::Surface& result, const QuadGrid& quadGrid)
+{
+ // Buffer info.
+ const int width = result.getWidth();
+ const int height = result.getHeight();
+ const int gridSize = quadGrid.getGridSize();
+ const int stride = gridSize + 1;
+ const bool hasAlpha = true; // \todo [2015-09-07 elecro] add correct alpha check
+ ShaderEvalContext evalCtx (quadGrid);
+
+ // Evaluate color for each vertex.
+ std::vector<tcu::Vec4> colors ((gridSize + 1) * (gridSize + 1));
+ for (int y = 0; y < gridSize+1; y++)
+ for (int x = 0; x < gridSize+1; x++)
+ {
+ const float sx = (float)x / (float)gridSize;
+ const float sy = (float)y / (float)gridSize;
+ const int vtxNdx = ((y * (gridSize+1)) + x);
+
+ evalCtx.reset(sx, sy);
+ m_evaluator.evaluate(evalCtx);
+ DE_ASSERT(!evalCtx.isDiscarded); // Discard is not available in vertex shader.
+ tcu::Vec4 color = evalCtx.color;
+
+ if (!hasAlpha)
+ color.w() = 1.0f;
+
+ colors[vtxNdx] = color;
+ }
+
+ // Render quads.
+ for (int y = 0; y < gridSize; y++)
+ for (int x = 0; x < gridSize; x++)
+ {
+ const float x0 = (float)x / (float)gridSize;
+ const float x1 = (float)(x + 1) / (float)gridSize;
+ const float y0 = (float)y / (float)gridSize;
+ const float y1 = (float)(y + 1) / (float)gridSize;
+
+ const float sx0 = x0 * (float)width;
+ const float sx1 = x1 * (float)width;
+ const float sy0 = y0 * (float)height;
+ const float sy1 = y1 * (float)height;
+ const float oosx = 1.0f / (sx1 - sx0);
+ const float oosy = 1.0f / (sy1 - sy0);
+
+ const int ix0 = deCeilFloatToInt32(sx0 - 0.5f);
+ const int ix1 = deCeilFloatToInt32(sx1 - 0.5f);
+ const int iy0 = deCeilFloatToInt32(sy0 - 0.5f);
+ const int iy1 = deCeilFloatToInt32(sy1 - 0.5f);
+
+ const int v00 = (y * stride) + x;
+ const int v01 = (y * stride) + x + 1;
+ const int v10 = ((y + 1) * stride) + x;
+ const int v11 = ((y + 1) * stride) + x + 1;
+ const tcu::Vec4 c00 = colors[v00];
+ const tcu::Vec4 c01 = colors[v01];
+ const tcu::Vec4 c10 = colors[v10];
+ const tcu::Vec4 c11 = colors[v11];
+
+ //printf("(%d,%d) -> (%f..%f, %f..%f) (%d..%d, %d..%d)\n", x, y, sx0, sx1, sy0, sy1, ix0, ix1, iy0, iy1);
+
+ for (int iy = iy0; iy < iy1; iy++)
+ for (int ix = ix0; ix < ix1; ix++)
+ {
+ DE_ASSERT(deInBounds32(ix, 0, width));
+ DE_ASSERT(deInBounds32(iy, 0, height));
+
+ const float sfx = (float)ix + 0.5f;
+ const float sfy = (float)iy + 0.5f;
+ const float fx1 = deFloatClamp((sfx - sx0) * oosx, 0.0f, 1.0f);
+ const float fy1 = deFloatClamp((sfy - sy0) * oosy, 0.0f, 1.0f);
+
+ // Triangle quad interpolation.
+ const bool tri = fx1 + fy1 <= 1.0f;
+ const float tx = tri ? fx1 : (1.0f-fx1);
+ const float ty = tri ? fy1 : (1.0f-fy1);
+ const tcu::Vec4& t0 = tri ? c00 : c11;
+ const tcu::Vec4& t1 = tri ? c01 : c10;
+ const tcu::Vec4& t2 = tri ? c10 : c01;
+ const tcu::Vec4 color = t0 + (t1-t0)*tx + (t2-t0)*ty;
+
+ result.setPixel(ix, iy, tcu::RGBA(color));
+ }
+ }
+}
+
+void ShaderRenderCaseInstance::computeFragmentReference (tcu::Surface& result, const QuadGrid& quadGrid)
+{
+ // Buffer info.
+ const int width = result.getWidth();
+ const int height = result.getHeight();
+ const bool hasAlpha = true; // \todo [2015-09-07 elecro] add correct alpha check
+ ShaderEvalContext evalCtx (quadGrid);
+
+ // Render.
+ for (int y = 0; y < height; y++)
+ for (int x = 0; x < width; x++)
+ {
+ const float sx = ((float)x + 0.5f) / (float)width;
+ const float sy = ((float)y + 0.5f) / (float)height;
+
+ evalCtx.reset(sx, sy);
+ m_evaluator.evaluate(evalCtx);
+ // Select either clear color or computed color based on discarded bit.
+ tcu::Vec4 color = evalCtx.isDiscarded ? m_clearColor : evalCtx.color;
+
+ if (!hasAlpha)
+ color.w() = 1.0f;
+
+ result.setPixel(x, y, tcu::RGBA(color));
+ }
+}
+
+bool ShaderRenderCaseInstance::compareImages (const tcu::Surface& resImage, const tcu::Surface& refImage, float errorThreshold)
+{
+ return tcu::fuzzyCompare(m_context.getTestContext().getLog(), "ComparisonResult", "Image comparison result", refImage, resImage, errorThreshold, tcu::COMPARE_LOG_RESULT);
+}
+
+} // sr
+} // vkt
--- /dev/null
+#ifndef _VKTSHADERRENDER_HPP
+#define _VKTSHADERRENDER_HPP
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by Khronos,
+ * at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Vulkan ShaderRenderCase
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuTexture.hpp"
+#include "tcuSurface.hpp"
+
+#include "deMemory.h"
+#include "deSharedPtr.hpp"
+#include "deUniquePtr.hpp"
+
+#include "vkDefs.hpp"
+#include "vkPrograms.hpp"
+#include "vkRef.hpp"
+#include "vkMemUtil.hpp"
+#include "vkBuilderUtil.hpp"
+
+#include "vktTestCaseUtil.hpp"
+
+namespace vkt
+{
+namespace sr
+{
+
+class QuadGrid;
+class ShaderRenderCaseInstance;
+
+class TextureBinding
+{
+public:
+ enum Type
+ {
+ TYPE_NONE = 0,
+ TYPE_2D,
+ TYPE_CUBE_MAP,
+ TYPE_2D_ARRAY,
+ TYPE_3D,
+
+ TYPE_LAST
+ };
+
+ TextureBinding (const tcu::Archive& archive,
+ const char* filename,
+ const Type type,
+ const tcu::Sampler& sampler);
+ ~TextureBinding (void);
+ Type getType (void) const { return m_type; }
+ const tcu::Sampler& getSampler (void) const { return m_sampler; }
+ const tcu::Texture2D& get2D (void) const { DE_ASSERT(getType() == TYPE_2D && m_binding.tex2D !=NULL); return *m_binding.tex2D; }
+
+private:
+ TextureBinding (const TextureBinding&); // not allowed!
+ TextureBinding& operator= (const TextureBinding&); // not allowed!
+
+ static de::MovePtr<tcu::Texture2D> loadTexture2D (const tcu::Archive& archive, const char* filename);
+
+ Type m_type;
+ tcu::Sampler m_sampler;
+
+ union
+ {
+ const tcu::Texture2D* tex2D;
+ } m_binding;
+};
+
+typedef de::SharedPtr<TextureBinding> TextureBindingSp;
+
+// ShaderEvalContext.
+
+class ShaderEvalContext
+{
+public:
+ // Limits.
+ enum
+ {
+ MAX_USER_ATTRIBS = 4,
+ MAX_TEXTURES = 4
+ };
+
+ struct ShaderSampler
+ {
+ tcu::Sampler sampler;
+ const tcu::Texture2D* tex2D;
+ const tcu::TextureCube* texCube;
+ const tcu::Texture2DArray* tex2DArray;
+ const tcu::Texture3D* tex3D;
+
+ inline ShaderSampler (void)
+ : tex2D (DE_NULL)
+ , texCube (DE_NULL)
+ , tex2DArray(DE_NULL)
+ , tex3D (DE_NULL)
+ {
+ }
+ };
+
+ ShaderEvalContext (const QuadGrid& quadGrid);
+ ~ShaderEvalContext (void);
+
+ void reset (float sx, float sy);
+
+ // Inputs.
+ tcu::Vec4 coords;
+ tcu::Vec4 unitCoords;
+ tcu::Vec4 constCoords;
+
+ tcu::Vec4 in[MAX_USER_ATTRIBS];
+ ShaderSampler textures[MAX_TEXTURES];
+
+ // Output.
+ tcu::Vec4 color;
+ bool isDiscarded;
+
+ // Functions.
+ inline void discard (void) { isDiscarded = true; }
+ tcu::Vec4 texture2D (int unitNdx, const tcu::Vec2& coords);
+
+private:
+ const QuadGrid& m_quadGrid;
+};
+
+typedef void (*ShaderEvalFunc) (ShaderEvalContext& c);
+
+inline void evalCoordsPassthroughX (ShaderEvalContext& c) { c.color.x() = c.coords.x(); }
+inline void evalCoordsPassthroughXY (ShaderEvalContext& c) { c.color.xy() = c.coords.swizzle(0,1); }
+inline void evalCoordsPassthroughXYZ (ShaderEvalContext& c) { c.color.xyz() = c.coords.swizzle(0,1,2); }
+inline void evalCoordsPassthrough (ShaderEvalContext& c) { c.color = c.coords; }
+inline void evalCoordsSwizzleWZYX (ShaderEvalContext& c) { c.color = c.coords.swizzle(3,2,1,0); }
+
+// ShaderEvaluator
+// Either inherit a class with overridden evaluate() or just pass in an evalFunc.
+
+class ShaderEvaluator
+{
+public:
+ ShaderEvaluator (void);
+ ShaderEvaluator (const ShaderEvalFunc evalFunc);
+ virtual ~ShaderEvaluator (void);
+
+ virtual void evaluate (ShaderEvalContext& ctx) const;
+
+private:
+ ShaderEvaluator (const ShaderEvaluator&); // not allowed!
+ ShaderEvaluator& operator= (const ShaderEvaluator&); // not allowed!
+
+ const ShaderEvalFunc m_evalFunc;
+};
+
+// UniformSetup
+
+typedef void (*UniformSetupFunc) (ShaderRenderCaseInstance& instance, const tcu::Vec4& constCoords);
+
+class UniformSetup
+{
+public:
+ UniformSetup (void);
+ UniformSetup (const UniformSetupFunc setup);
+ virtual ~UniformSetup (void);
+ virtual void setup (ShaderRenderCaseInstance& instance, const tcu::Vec4& constCoords) const;
+
+private:
+ UniformSetup (const UniformSetup&); // not allowed!
+ UniformSetup& operator= (const UniformSetup&); // not allowed!
+
+ const UniformSetupFunc m_setupFunc;
+};
+
+typedef void (*AttributeSetupFunc) (ShaderRenderCaseInstance& instance, deUint32 numVertices);
+
+class ShaderRenderCase : public vkt::TestCase
+{
+public:
+ ShaderRenderCase (tcu::TestContext& testCtx,
+ const std::string& name,
+ const std::string& description,
+ const bool isVertexCase,
+ const ShaderEvalFunc evalFunc,
+ const UniformSetup* uniformSetup,
+ const AttributeSetupFunc attribFunc);
+
+ ShaderRenderCase (tcu::TestContext& testCtx,
+ const std::string& name,
+ const std::string& description,
+ const bool isVertexCase,
+ const ShaderEvaluator* evaluator,
+ const UniformSetup* uniformSetup,
+ const AttributeSetupFunc attribFunc);
+
+
+ virtual ~ShaderRenderCase (void);
+ virtual void initPrograms (vk::SourceCollections& programCollection) const;
+ virtual TestInstance* createInstance (Context& context) const;
+
+protected:
+ std::string m_vertShaderSource;
+ std::string m_fragShaderSource;
+
+ const bool m_isVertexCase;
+ const de::UniquePtr<const ShaderEvaluator> m_evaluator;
+ const de::UniquePtr<const UniformSetup> m_uniformSetup;
+ const AttributeSetupFunc m_attribFunc;
+};
+
+
+enum BaseUniformType
+{
+// Bool
+ UB_FALSE,
+ UB_TRUE,
+
+// BVec4
+ UB4_FALSE,
+ UB4_TRUE,
+
+// Integers
+ UI_ZERO,
+ UI_ONE,
+ UI_TWO,
+ UI_THREE,
+ UI_FOUR,
+ UI_FIVE,
+ UI_SIX,
+ UI_SEVEN,
+ UI_EIGHT,
+ UI_ONEHUNDREDONE,
+
+// IVec2
+ UI2_MINUS_ONE,
+ UI2_ZERO,
+ UI2_ONE,
+ UI2_TWO,
+ UI2_THREE,
+ UI2_FOUR,
+ UI2_FIVE,
+
+// IVec3
+ UI3_MINUS_ONE,
+ UI3_ZERO,
+ UI3_ONE,
+ UI3_TWO,
+ UI3_THREE,
+ UI3_FOUR,
+ UI3_FIVE,
+
+// IVec4
+ UI4_MINUS_ONE,
+ UI4_ZERO,
+ UI4_ONE,
+ UI4_TWO,
+ UI4_THREE,
+ UI4_FOUR,
+ UI4_FIVE,
+
+// Float
+ UF_ZERO,
+ UF_ONE,
+ UF_TWO,
+ UF_THREE,
+ UF_FOUR,
+ UF_FIVE,
+ UF_SIX,
+ UF_SEVEN,
+ UF_EIGHT,
+
+ UF_HALF,
+ UF_THIRD,
+ UF_FOURTH,
+ UF_FIFTH,
+ UF_SIXTH,
+ UF_SEVENTH,
+ UF_EIGHTH,
+
+// Vec2
+ UV2_MINUS_ONE,
+ UV2_ZERO,
+ UV2_ONE,
+ UV2_TWO,
+ UV2_THREE,
+
+ UV2_HALF,
+
+// Vec3
+ UV3_MINUS_ONE,
+ UV3_ZERO,
+ UV3_ONE,
+ UV3_TWO,
+ UV3_THREE,
+
+ UV3_HALF,
+
+// Vec4
+ UV4_MINUS_ONE,
+ UV4_ZERO,
+ UV4_ONE,
+ UV4_TWO,
+ UV4_THREE,
+
+ UV4_HALF,
+
+ UV4_BLACK,
+ UV4_GRAY,
+ UV4_WHITE
+};
+
+enum BaseAttributeType
+{
+// User attributes
+ A_IN0,
+ A_IN1,
+ A_IN2,
+ A_IN3,
+
+// Matrices
+ MAT2,
+ MAT2x3,
+ MAT2x4,
+ MAT3x2,
+ MAT3,
+ MAT3x4,
+ MAT4x2,
+ MAT4x3,
+ MAT4
+};
+
+// ShaderRenderCaseInstance.
+
+class ShaderRenderCaseInstance : public vkt::TestInstance
+{
+public:
+ ShaderRenderCaseInstance (Context& context,
+ const bool isVertexCase,
+ const ShaderEvaluator& evaluator,
+ const UniformSetup& uniformSetup,
+ const AttributeSetupFunc attribFunc);
+
+ virtual ~ShaderRenderCaseInstance (void);
+ virtual tcu::TestStatus iterate (void);
+
+ void addAttribute (deUint32 bindingLocation,
+ vk::VkFormat format,
+ deUint32 sizePerElement,
+ deUint32 count,
+ const void* data);
+ void useAttribute (deUint32 bindingLocation,
+ BaseAttributeType type);
+
+ template<typename T>
+ void addUniform (deUint32 bindingLocation,
+ vk::VkDescriptorType descriptorType,
+ const T& data);
+ void addUniform (deUint32 bindingLocation,
+ vk::VkDescriptorType descriptorType,
+ deUint32 dataSize,
+ const void* data);
+ void useUniform (deUint32 bindingLocation,
+ BaseUniformType type);
+ void useSampler2D (deUint32 bindingLocation,
+ deUint32 textureId);
+
+protected:
+ virtual void setup (void);
+ virtual void setupUniforms (const tcu::Vec4& constCoords);
+
+ const tcu::IVec2 getViewportSize (void) const;
+
+ std::vector<tcu::Mat4> m_userAttribTransforms;
+ const tcu::Vec4 m_clearColor;
+ std::vector<TextureBindingSp> m_textures;
+
+ vk::Allocator& m_memAlloc;
+
+private:
+
+ void setupTextures (void);
+ de::MovePtr<vk::Allocation> uploadImage2D (const tcu::Texture2D& refTexture,
+ const vk::VkImage& vkTexture);
+ vk::Move<vk::VkImage> createImage2D (const tcu::Texture2D& texture,
+ const vk::VkFormat format,
+ const vk::VkImageUsageFlags usage,
+ const vk::VkImageTiling tiling);
+ void copyTilingImageToOptimal (const vk::VkImage& srcImage,
+ const vk::VkImage& dstImage,
+ deInt32 width,
+ deInt32 height);
+
+ void setupUniformData (deUint32 bindingLocation, deUint32 size, const void* dataPtr);
+ void setupDefaultInputs (const QuadGrid& quadGrid);
+
+ void render (tcu::Surface& result, const QuadGrid& quadGrid);
+ void computeVertexReference (tcu::Surface& result, const QuadGrid& quadGrid);
+ void computeFragmentReference (tcu::Surface& result, const QuadGrid& quadGrid);
+ bool compareImages (const tcu::Surface& resImage,
+ const tcu::Surface& refImage,
+ float errorThreshold);
+
+ const bool m_isVertexCase;
+ const ShaderEvaluator& m_evaluator;
+ const UniformSetup& m_uniformSetup;
+ const AttributeSetupFunc m_attribFunc;
+
+ struct EnabledBaseAttribute
+ {
+ deUint32 location;
+ BaseAttributeType type;
+ };
+ std::vector<EnabledBaseAttribute> m_enabledBaseAttributes;
+
+ const tcu::IVec2 m_renderSize;
+ const vk::VkFormat m_colorFormat;
+
+ vk::Move<vk::VkImage> m_colorImage;
+ de::MovePtr<vk::Allocation> m_colorImageAlloc;
+ vk::Move<vk::VkImageView> m_colorImageView;
+
+ vk::Move<vk::VkRenderPass> m_renderPass;
+ vk::Move<vk::VkFramebuffer> m_framebuffer;
+ vk::Move<vk::VkPipelineLayout> m_pipelineLayout;
+ vk::Move<vk::VkPipeline> m_graphicsPipeline;
+
+ vk::Move<vk::VkShaderModule> m_vertexShaderModule;
+ vk::Move<vk::VkShaderModule> m_fragmentShaderModule;
+
+ vk::Move<vk::VkBuffer> m_indiceBuffer;
+ de::MovePtr<vk::Allocation> m_indiceBufferAlloc;
+
+ vk::Move<vk::VkDescriptorSetLayout> m_descriptorSetLayout;
+
+ vk::Move<vk::VkDescriptorPool> m_descriptorPool;
+ vk::Move<vk::VkDescriptorSet> m_descriptorSet;
+
+ vk::Move<vk::VkCommandPool> m_cmdPool;
+ vk::Move<vk::VkCommandBuffer> m_cmdBuffer;
+
+ vk::Move<vk::VkFence> m_fence;
+
+ vk::DescriptorSetLayoutBuilder m_descriptorSetLayoutBuilder;
+ vk::DescriptorPoolBuilder m_descriptorPoolBuilder;
+ vk::DescriptorSetUpdateBuilder m_descriptorSetUpdateBuilder;
+
+ typedef de::SharedPtr<vk::Unique<vk::VkBuffer> > VkBufferSp;
+
+ typedef de::SharedPtr<vk::Unique<vk::VkImage> > VkImageSp;
+ typedef de::SharedPtr<vk::Unique<vk::VkImageView> > VkImageViewSp;
+ typedef de::SharedPtr<vk::Unique<vk::VkSampler> > VkSamplerSp;
+ typedef de::SharedPtr<vk::Allocation> AllocationSp;
+
+ class UniformInfo
+ {
+ public:
+ UniformInfo (void) {}
+ virtual ~UniformInfo (void) {}
+
+ vk::VkDescriptorType type;
+ deUint32 location;
+ };
+
+ class BufferUniform : public UniformInfo
+ {
+ public:
+ BufferUniform (void) {}
+ virtual ~BufferUniform (void) {}
+
+ VkBufferSp buffer;
+ AllocationSp alloc;
+ vk::VkDescriptorBufferInfo descriptor;
+ };
+
+ class SamplerUniform : public UniformInfo
+ {
+ public:
+ SamplerUniform (void) {}
+ virtual ~SamplerUniform (void) {}
+
+ VkImageSp image;
+ VkImageViewSp imageView;
+ VkSamplerSp sampler;
+ AllocationSp alloc;
+ vk::VkDescriptorImageInfo descriptor;
+ };
+
+ typedef de::SharedPtr<de::UniquePtr<UniformInfo> > UniformInfoSp;
+ std::vector<UniformInfoSp> m_uniformInfos;
+
+ std::vector<vk::VkVertexInputBindingDescription> m_vertexBindingDescription;
+ std::vector<vk::VkVertexInputAttributeDescription> m_vertexattributeDescription;
+
+ std::vector<VkBufferSp> m_vertexBuffers;
+ std::vector<AllocationSp> m_vertexBufferAllocs;
+};
+
+template<typename T>
+void ShaderRenderCaseInstance::addUniform (deUint32 bindingLocation, vk::VkDescriptorType descriptorType, const T& data)
+{
+ addUniform(bindingLocation, descriptorType, sizeof(T), &data);
+}
+
+} // sr
+} // vkt
+
+#endif // _VKTSHADERRENDER_HPP
--- /dev/null
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by Khronos,
+ * at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Shader discard statement tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "vktShaderRenderDiscardTests.hpp"
+#include "vktShaderRender.hpp"
+#include "tcuStringTemplate.hpp"
+#include "gluTexture.hpp"
+
+#include <string>
+
+using tcu::StringTemplate;
+
+namespace vkt
+{
+namespace sr
+{
+namespace
+{
+
+class SamplerUniformSetup : public UniformSetup
+{
+public:
+ SamplerUniformSetup (bool useSampler)
+ : m_useSampler(useSampler)
+ {}
+
+ virtual void setup (ShaderRenderCaseInstance& instance, const tcu::Vec4&) const
+ {
+ instance.useUniform(0u, UI_ONE);
+ instance.useUniform(1u, UI_TWO);
+ if (m_useSampler)
+ instance.useSampler2D(2u, 0u); // To the uniform binding location 2 bind the texture 0
+ }
+
+private:
+ const bool m_useSampler;
+};
+
+
+class ShaderDiscardCaseInstance : public ShaderRenderCaseInstance
+{
+public:
+ ShaderDiscardCaseInstance (Context& context,
+ bool isVertexCase,
+ const ShaderEvaluator& evaluator,
+ const UniformSetup& uniformSetup,
+ bool usesTexture);
+ virtual ~ShaderDiscardCaseInstance (void);
+};
+
+ShaderDiscardCaseInstance::ShaderDiscardCaseInstance (Context& context,
+ bool isVertexCase,
+ const ShaderEvaluator& evaluator,
+ const UniformSetup& uniformSetup,
+ bool usesTexture)
+ : ShaderRenderCaseInstance (context, isVertexCase, evaluator, uniformSetup, DE_NULL)
+{
+ if (usesTexture)
+ {
+ de::SharedPtr<TextureBinding> brickTexture(new TextureBinding(m_context.getTestContext().getArchive(),
+ "vulkan/data/brick.png",
+ TextureBinding::TYPE_2D,
+ tcu::Sampler(tcu::Sampler::CLAMP_TO_EDGE,
+ tcu::Sampler::CLAMP_TO_EDGE,
+ tcu::Sampler::CLAMP_TO_EDGE,
+ tcu::Sampler::LINEAR,
+ tcu::Sampler::LINEAR)));
+ m_textures.push_back(brickTexture);
+ }
+}
+
+ShaderDiscardCaseInstance::~ShaderDiscardCaseInstance (void)
+{
+}
+
+class ShaderDiscardCase : public ShaderRenderCase
+{
+public:
+ ShaderDiscardCase (tcu::TestContext& testCtx,
+ const char* name,
+ const char* description,
+ const char* shaderSource,
+ const ShaderEvalFunc evalFunc,
+ bool usesTexture);
+ virtual TestInstance* createInstance (Context& context) const
+ {
+ DE_ASSERT(m_evaluator != DE_NULL);
+ DE_ASSERT(m_uniformSetup != DE_NULL);
+ return new ShaderDiscardCaseInstance(context, m_isVertexCase, *m_evaluator, *m_uniformSetup, m_usesTexture);
+ }
+
+private:
+ const bool m_usesTexture;
+};
+
+ShaderDiscardCase::ShaderDiscardCase (tcu::TestContext& testCtx,
+ const char* name,
+ const char* description,
+ const char* shaderSource,
+ const ShaderEvalFunc evalFunc,
+ bool usesTexture)
+ : ShaderRenderCase (testCtx, name, description, false, evalFunc, new SamplerUniformSetup(usesTexture), DE_NULL)
+ , m_usesTexture (usesTexture)
+{
+ m_fragShaderSource = shaderSource;
+ m_vertShaderSource =
+ "#version 140\n"
+ "#extension GL_ARB_separate_shader_objects : enable\n"
+ "#extension GL_ARB_shading_language_420pack : enable\n"
+ "layout(location=0) in highp vec4 a_position;\n"
+ "layout(location=1) in highp vec4 a_coords;\n"
+ "layout(location=0) out mediump vec4 v_color;\n"
+ "layout(location=1) out mediump vec4 v_coords;\n\n"
+ "void main (void)\n"
+ "{\n"
+ " gl_Position = a_position;\n"
+ " v_color = vec4(a_coords.xyz, 1.0);\n"
+ " v_coords = a_coords;\n"
+ "}\n";
+}
+
+
+enum DiscardMode
+{
+ DISCARDMODE_ALWAYS = 0,
+ DISCARDMODE_NEVER,
+ DISCARDMODE_UNIFORM,
+ DISCARDMODE_DYNAMIC,
+ DISCARDMODE_TEXTURE,
+
+ DISCARDMODE_LAST
+};
+
+enum DiscardTemplate
+{
+ DISCARDTEMPLATE_MAIN_BASIC = 0,
+ DISCARDTEMPLATE_FUNCTION_BASIC,
+ DISCARDTEMPLATE_MAIN_STATIC_LOOP,
+ DISCARDTEMPLATE_MAIN_DYNAMIC_LOOP,
+ DISCARDTEMPLATE_FUNCTION_STATIC_LOOP,
+
+ DISCARDTEMPLATE_LAST
+};
+
+// Evaluation functions
+inline void evalDiscardAlways (ShaderEvalContext& c) { c.discard(); }
+inline void evalDiscardNever (ShaderEvalContext& c) { c.color.xyz() = c.coords.swizzle(0,1,2); }
+inline void evalDiscardDynamic (ShaderEvalContext& c) { c.color.xyz() = c.coords.swizzle(0,1,2); if (c.coords.x()+c.coords.y() > 0.0f) c.discard(); }
+
+inline void evalDiscardTexture (ShaderEvalContext& c)
+{
+ c.color.xyz() = c.coords.swizzle(0,1,2);
+ if (c.texture2D(0, c.coords.swizzle(0,1) * 0.25f + 0.5f).x() < 0.7f)
+ c.discard();
+}
+
+static ShaderEvalFunc getEvalFunc (DiscardMode mode)
+{
+ switch (mode)
+ {
+ case DISCARDMODE_ALWAYS: return evalDiscardAlways;
+ case DISCARDMODE_NEVER: return evalDiscardNever;
+ case DISCARDMODE_UNIFORM: return evalDiscardAlways;
+ case DISCARDMODE_DYNAMIC: return evalDiscardDynamic;
+ case DISCARDMODE_TEXTURE: return evalDiscardTexture;
+ default:
+ DE_ASSERT(DE_FALSE);
+ return evalDiscardAlways;
+ }
+}
+
+static const char* getTemplate (DiscardTemplate variant)
+{
+ #define GLSL_SHADER_TEMPLATE_HEADER \
+ "#version 140\n" \
+ "#extension GL_ARB_separate_shader_objects : enable\n" \
+ "#extension GL_ARB_shading_language_420pack : enable\n" \
+ "layout(location = 0) in mediump vec4 v_color;\n" \
+ "layout(location = 1) in mediump vec4 v_coords;\n" \
+ "layout(location = 0) out mediump vec4 o_color;\n" \
+ "layout(set = 0, binding = 2) uniform sampler2D ut_brick;\n" \
+ "layout(set = 0, binding = 0) uniform block0 { mediump int ui_one; };\n\n"
+
+ switch (variant)
+ {
+ case DISCARDTEMPLATE_MAIN_BASIC:
+ return GLSL_SHADER_TEMPLATE_HEADER
+ "void main (void)\n"
+ "{\n"
+ " o_color = v_color;\n"
+ " ${DISCARD};\n"
+ "}\n";
+
+ case DISCARDTEMPLATE_FUNCTION_BASIC:
+ return GLSL_SHADER_TEMPLATE_HEADER
+ "void myfunc (void)\n"
+ "{\n"
+ " ${DISCARD};\n"
+ "}\n\n"
+ "void main (void)\n"
+ "{\n"
+ " o_color = v_color;\n"
+ " myfunc();\n"
+ "}\n";
+
+ case DISCARDTEMPLATE_MAIN_STATIC_LOOP:
+ return GLSL_SHADER_TEMPLATE_HEADER
+ "void main (void)\n"
+ "{\n"
+ " o_color = v_color;\n"
+ " for (int i = 0; i < 2; i++)\n"
+ " {\n"
+ " if (i > 0)\n"
+ " ${DISCARD};\n"
+ " }\n"
+ "}\n";
+
+ case DISCARDTEMPLATE_MAIN_DYNAMIC_LOOP:
+ return GLSL_SHADER_TEMPLATE_HEADER
+ "layout(set = 0, binding = 1) uniform block1 { mediump int ui_two; };\n\n"
+ "void main (void)\n"
+ "{\n"
+ " o_color = v_color;\n"
+ " for (int i = 0; i < ui_two; i++)\n"
+ " {\n"
+ " if (i > 0)\n"
+ " ${DISCARD};\n"
+ " }\n"
+ "}\n";
+
+ case DISCARDTEMPLATE_FUNCTION_STATIC_LOOP:
+ return GLSL_SHADER_TEMPLATE_HEADER
+ "void myfunc (void)\n"
+ "{\n"
+ " for (int i = 0; i < 2; i++)\n"
+ " {\n"
+ " if (i > 0)\n"
+ " ${DISCARD};\n"
+ " }\n"
+ "}\n\n"
+ "void main (void)\n"
+ "{\n"
+ " o_color = v_color;\n"
+ " myfunc();\n"
+ "}\n";
+
+ default:
+ DE_ASSERT(DE_FALSE);
+ return DE_NULL;
+ }
+
+ #undef GLSL_SHADER_TEMPLATE_HEADER
+}
+
+static const char* getTemplateName (DiscardTemplate variant)
+{
+ switch (variant)
+ {
+ case DISCARDTEMPLATE_MAIN_BASIC: return "basic";
+ case DISCARDTEMPLATE_FUNCTION_BASIC: return "function";
+ case DISCARDTEMPLATE_MAIN_STATIC_LOOP: return "static_loop";
+ case DISCARDTEMPLATE_MAIN_DYNAMIC_LOOP: return "dynamic_loop";
+ case DISCARDTEMPLATE_FUNCTION_STATIC_LOOP: return "function_static_loop";
+ default:
+ DE_ASSERT(DE_FALSE);
+ return DE_NULL;
+ }
+}
+
+static const char* getModeName (DiscardMode mode)
+{
+ switch (mode)
+ {
+ case DISCARDMODE_ALWAYS: return "always";
+ case DISCARDMODE_NEVER: return "never";
+ case DISCARDMODE_UNIFORM: return "uniform";
+ case DISCARDMODE_DYNAMIC: return "dynamic";
+ case DISCARDMODE_TEXTURE: return "texture";
+ default:
+ DE_ASSERT(DE_FALSE);
+ return DE_NULL;
+ }
+}
+
+static const char* getTemplateDesc (DiscardTemplate variant)
+{
+ switch (variant)
+ {
+ case DISCARDTEMPLATE_MAIN_BASIC: return "main";
+ case DISCARDTEMPLATE_FUNCTION_BASIC: return "function";
+ case DISCARDTEMPLATE_MAIN_STATIC_LOOP: return "static loop";
+ case DISCARDTEMPLATE_MAIN_DYNAMIC_LOOP: return "dynamic loop";
+ case DISCARDTEMPLATE_FUNCTION_STATIC_LOOP: return "static loop in function";
+ default:
+ DE_ASSERT(DE_FALSE);
+ return DE_NULL;
+ }
+}
+
+static const char* getModeDesc (DiscardMode mode)
+{
+ switch (mode)
+ {
+ case DISCARDMODE_ALWAYS: return "Always discard";
+ case DISCARDMODE_NEVER: return "Never discard";
+ case DISCARDMODE_UNIFORM: return "Discard based on uniform value";
+ case DISCARDMODE_DYNAMIC: return "Discard based on varying values";
+ case DISCARDMODE_TEXTURE: return "Discard based on texture value";
+ default:
+ DE_ASSERT(DE_FALSE);
+ return DE_NULL;
+ }
+}
+
+de::MovePtr<ShaderDiscardCase> makeDiscardCase (tcu::TestContext& testCtx, DiscardTemplate tmpl, DiscardMode mode)
+{
+ StringTemplate shaderTemplate(getTemplate(tmpl));
+
+ std::map<std::string, std::string> params;
+
+ switch (mode)
+ {
+ case DISCARDMODE_ALWAYS: params["DISCARD"] = "discard"; break;
+ case DISCARDMODE_NEVER: params["DISCARD"] = "if (false) discard"; break;
+ case DISCARDMODE_UNIFORM: params["DISCARD"] = "if (ui_one > 0) discard"; break;
+ case DISCARDMODE_DYNAMIC: params["DISCARD"] = "if (v_coords.x+v_coords.y > 0.0) discard"; break;
+ case DISCARDMODE_TEXTURE: params["DISCARD"] = "if (texture(ut_brick, v_coords.xy*0.25+0.5).x < 0.7) discard"; break;
+ default:
+ DE_ASSERT(DE_FALSE);
+ break;
+ }
+
+ std::string name = std::string(getTemplateName(tmpl)) + "_" + getModeName(mode);
+ std::string description = std::string(getModeDesc(mode)) + " in " + getTemplateDesc(tmpl);
+
+ return de::MovePtr<ShaderDiscardCase>(new ShaderDiscardCase(testCtx, name.c_str(), description.c_str(), shaderTemplate.specialize(params).c_str(), getEvalFunc(mode), mode == DISCARDMODE_TEXTURE));
+}
+
+class ShaderDiscardTests : public tcu::TestCaseGroup
+{
+public:
+ ShaderDiscardTests (tcu::TestContext& textCtx);
+ virtual ~ShaderDiscardTests (void);
+
+ virtual void init (void);
+
+private:
+ ShaderDiscardTests (const ShaderDiscardTests&); // not allowed!
+ ShaderDiscardTests& operator= (const ShaderDiscardTests&); // not allowed!
+};
+
+ShaderDiscardTests::ShaderDiscardTests (tcu::TestContext& testCtx)
+ : TestCaseGroup(testCtx, "discard", "Discard statement tests")
+{
+}
+
+ShaderDiscardTests::~ShaderDiscardTests (void)
+{
+}
+
+void ShaderDiscardTests::init (void)
+{
+ for (int tmpl = 0; tmpl < DISCARDTEMPLATE_LAST; tmpl++)
+ for (int mode = 0; mode < DISCARDMODE_LAST; mode++)
+ addChild(makeDiscardCase(m_testCtx, (DiscardTemplate)tmpl, (DiscardMode)mode).release());
+}
+
+} // anonymous
+
+tcu::TestCaseGroup* createDiscardTests (tcu::TestContext& testCtx)
+{
+ return new ShaderDiscardTests(testCtx);
+}
+
+} // sr
+} // vkt
--- /dev/null
+#ifndef _VKTSHADERRENDERDISCARDTESTS_HPP
+#define _VKTSHADERRENDERDISCARDTESTS_HPP
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by Khronos,
+ * at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Shader discard statement tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+namespace sr
+{
+
+tcu::TestCaseGroup* createDiscardTests (tcu::TestContext& testCtx);
+
+} // sr
+} // vkt
+
+#endif // _VKTSHADERRENDERDISCARDTESTS_HPP
--- /dev/null
+# SPIR-V assembly tests
+
+include_directories(..)
+
+set(DEQP_VK_SPIRV_ASSEMBLY_SRCS
+ vktSpvAsmComputeShaderCase.cpp
+ vktSpvAsmComputeShaderCase.hpp
+ vktSpvAsmComputeShaderTestUtil.cpp
+ vktSpvAsmComputeShaderTestUtil.hpp
+ vktSpvAsmInstructionTests.cpp
+ vktSpvAsmInstructionTests.hpp
+ vktSpvAsmTests.cpp
+ vktSpvAsmTests.hpp
+ )
+
+set(DEQP_VK_SPIRV_ASSEMBLY_LIBS
+ tcutil
+ vkutil
+ )
+
+add_library(deqp-vk-spirv-assembly STATIC ${DEQP_VK_SPIRV_ASSEMBLY_SRCS})
+target_link_libraries(deqp-vk-spirv-assembly ${DEQP_VK_SPIRV_ASSEMBLY_LIBS})
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Test Case Skeleton Based on Compute Shaders
+ *//*--------------------------------------------------------------------*/
+
+#include "vktSpvAsmComputeShaderCase.hpp"
+
+#include "deSharedPtr.hpp"
+
+#include "vkBuilderUtil.hpp"
+#include "vkMemUtil.hpp"
+#include "vkRefUtil.hpp"
+#include "vkQueryUtil.hpp"
+#include "vkTypeUtil.hpp"
+
+namespace
+{
+
+using namespace vk;
+using std::vector;
+
+typedef de::MovePtr<Allocation> AllocationMp;
+typedef de::SharedPtr<Allocation> AllocationSp;
+typedef Unique<VkBuffer> BufferHandleUp;
+typedef de::SharedPtr<BufferHandleUp> BufferHandleSp;
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Create storage buffer, allocate and bind memory for the buffer
+ *
+ * The memory is created as host visible and passed back as a vk::Allocation
+ * instance via outMemory.
+ *//*--------------------------------------------------------------------*/
+Move<VkBuffer> createBufferAndBindMemory (const DeviceInterface& vkdi, const VkDevice& device, Allocator& allocator, size_t numBytes, AllocationMp* outMemory)
+{
+ const VkBufferCreateInfo bufferCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ 0u, // flags
+ numBytes, // size
+ VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, // usage
+ VK_SHARING_MODE_EXCLUSIVE, // sharingMode
+ 0u, // queueFamilyCount
+ DE_NULL, // pQueueFamilyIndices
+ };
+
+ Move<VkBuffer> buffer (createBuffer(vkdi, device, &bufferCreateInfo));
+ const VkMemoryRequirements requirements = getBufferMemoryRequirements(vkdi, device, *buffer);
+ AllocationMp bufferMemory = allocator.allocate(requirements, MemoryRequirement::HostVisible);
+
+ VK_CHECK(vkdi.bindBufferMemory(device, *buffer, bufferMemory->getMemory(), bufferMemory->getOffset()));
+ *outMemory = bufferMemory;
+
+ return buffer;
+}
+
+void setMemory (const DeviceInterface& vkdi, const VkDevice& device, Allocation* destAlloc, size_t numBytes, const void* data)
+{
+ void* const hostPtr = destAlloc->getHostPtr();
+
+ deMemcpy((deUint8*)hostPtr, data, numBytes);
+ flushMappedMemoryRange(vkdi, device, destAlloc->getMemory(), destAlloc->getOffset(), numBytes);
+}
+
+void clearMemory (const DeviceInterface& vkdi, const VkDevice& device, Allocation* destAlloc, size_t numBytes)
+{
+ void* const hostPtr = destAlloc->getHostPtr();
+
+ deMemset((deUint8*)hostPtr, 0, numBytes);
+ flushMappedMemoryRange(vkdi, device, destAlloc->getMemory(), destAlloc->getOffset(), numBytes);
+}
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Create a descriptor set layout with numBindings descriptors
+ *
+ * All descriptors are created for shader storage buffer objects and
+ * compute pipeline.
+ *//*--------------------------------------------------------------------*/
+Move<VkDescriptorSetLayout> createDescriptorSetLayout (const DeviceInterface& vkdi, const VkDevice& device, size_t numBindings)
+{
+ DescriptorSetLayoutBuilder builder;
+
+ for (size_t bindingNdx = 0; bindingNdx < numBindings; ++bindingNdx)
+ builder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT);
+
+ return builder.build(vkdi, device);
+}
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Create a pipeline layout with one descriptor set
+ *//*--------------------------------------------------------------------*/
+Move<VkPipelineLayout> createPipelineLayout (const DeviceInterface& vkdi, const VkDevice& device, VkDescriptorSetLayout descriptorSetLayout)
+{
+ const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ (VkPipelineLayoutCreateFlags)0,
+ 1u, // descriptorSetCount
+ &descriptorSetLayout, // pSetLayouts
+ 0u, // pushConstantRangeCount
+ DE_NULL, // pPushConstantRanges
+ };
+
+ return createPipelineLayout(vkdi, device, &pipelineLayoutCreateInfo);
+}
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Create a one-time descriptor pool for one descriptor set
+ *
+ * The pool supports numDescriptors storage buffer descriptors.
+ *//*--------------------------------------------------------------------*/
+inline Move<VkDescriptorPool> createDescriptorPool (const DeviceInterface& vkdi, const VkDevice& device, deUint32 numDescriptors)
+{
+ return DescriptorPoolBuilder()
+ .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, numDescriptors)
+ .build(vkdi, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, /* maxSets = */ 1);
+}
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Create a descriptor set
+ *
+ * The descriptor set's layout should contain numViews descriptors.
+ * All the descriptors represent buffer views, and they are sequentially
+ * binded to binding point starting from 0.
+ *//*--------------------------------------------------------------------*/
+Move<VkDescriptorSet> createDescriptorSet (const DeviceInterface& vkdi, const VkDevice& device, VkDescriptorPool pool, VkDescriptorSetLayout layout, size_t numViews, const vector<VkDescriptorBufferInfo>& descriptorInfos)
+{
+ const VkDescriptorSetAllocateInfo allocInfo =
+ {
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+ DE_NULL,
+ pool,
+ 1u,
+ &layout
+ };
+
+ Move<VkDescriptorSet> descriptorSet = allocateDescriptorSet(vkdi, device, &allocInfo);
+ DescriptorSetUpdateBuilder builder;
+
+ for (deUint32 descriptorNdx = 0; descriptorNdx < numViews; ++descriptorNdx)
+ builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(descriptorNdx), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfos[descriptorNdx]);
+ builder.update(vkdi, device);
+
+ return descriptorSet;
+}
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Create a compute pipeline based on the given shader
+ *//*--------------------------------------------------------------------*/
+Move<VkPipeline> createComputePipeline (const DeviceInterface& vkdi, const VkDevice& device, VkPipelineLayout pipelineLayout, VkShaderModule shader)
+{
+ const VkPipelineShaderStageCreateInfo pipelineShaderStageCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ (VkPipelineShaderStageCreateFlags)0,
+ VK_SHADER_STAGE_COMPUTE_BIT, // stage
+ shader, // shader
+ "main",
+ DE_NULL, // pSpecializationInfo
+ };
+ const VkComputePipelineCreateInfo pipelineCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ (VkPipelineCreateFlags)0,
+ pipelineShaderStageCreateInfo, // cs
+ pipelineLayout, // layout
+ (VkPipeline)0, // basePipelineHandle
+ 0u, // basePipelineIndex
+ };
+
+ return createComputePipeline(vkdi, device, (VkPipelineCache)0u, &pipelineCreateInfo);
+}
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Create a command pool
+ *
+ * The created command pool is designated for use on the queue type
+ * represented by the given queueFamilyIndex.
+ *//*--------------------------------------------------------------------*/
+Move<VkCommandPool> createCommandPool (const DeviceInterface& vkdi, VkDevice device, deUint32 queueFamilyIndex)
+{
+ const VkCommandPoolCreateInfo cmdPoolCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ 0u, // flags
+ queueFamilyIndex, // queueFamilyIndex
+ };
+
+ return createCommandPool(vkdi, device, &cmdPoolCreateInfo);
+}
+
+} // anonymous
+
+namespace vkt
+{
+namespace SpirVAssembly
+{
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Test instance for compute pipeline
+ *
+ * The compute shader is specified in the format of SPIR-V assembly, which
+ * is allowed to access MAX_NUM_INPUT_BUFFERS input storage buffers and
+ * MAX_NUM_OUTPUT_BUFFERS output storage buffers maximally. The shader
+ * source and input/output data are given in a ComputeShaderSpec object.
+ *
+ * This instance runs the given compute shader by feeding the data from input
+ * buffers and compares the data in the output buffers with the expected.
+ *//*--------------------------------------------------------------------*/
+class SpvAsmComputeShaderInstance : public TestInstance
+{
+public:
+ SpvAsmComputeShaderInstance (Context& ctx, const ComputeShaderSpec& spec);
+ tcu::TestStatus iterate (void);
+
+private:
+ const ComputeShaderSpec& m_shaderSpec;
+};
+
+// ComputeShaderTestCase implementations
+
+SpvAsmComputeShaderCase::SpvAsmComputeShaderCase (tcu::TestContext& testCtx, const char* name, const char* description, const ComputeShaderSpec& spec)
+ : TestCase (testCtx, name, description)
+ , m_shaderSpec (spec)
+{
+}
+
+void SpvAsmComputeShaderCase::initPrograms (SourceCollections& programCollection) const
+{
+ programCollection.spirvAsmSources.add("compute") << m_shaderSpec.assembly.c_str();
+}
+
+TestInstance* SpvAsmComputeShaderCase::createInstance (Context& ctx) const
+{
+ return new SpvAsmComputeShaderInstance(ctx, m_shaderSpec);
+}
+
+// ComputeShaderTestInstance implementations
+
+SpvAsmComputeShaderInstance::SpvAsmComputeShaderInstance (Context& ctx, const ComputeShaderSpec& spec)
+ : TestInstance (ctx)
+ , m_shaderSpec (spec)
+{
+}
+
+tcu::TestStatus SpvAsmComputeShaderInstance::iterate (void)
+{
+ const DeviceInterface& vkdi = m_context.getDeviceInterface();
+ const VkDevice& device = m_context.getDevice();
+ Allocator& allocator = m_context.getDefaultAllocator();
+
+ vector<AllocationSp> inputAllocs;
+ vector<AllocationSp> outputAllocs;
+ vector<BufferHandleSp> inputBuffers;
+ vector<BufferHandleSp> outputBuffers;
+ vector<VkDescriptorBufferInfo> descriptorInfos;
+
+ DE_ASSERT(!m_shaderSpec.outputs.empty());
+ const size_t numBuffers = m_shaderSpec.inputs.size() + m_shaderSpec.outputs.size();
+
+ // Create buffer object, allocate storage, and create view for all input/output buffers.
+
+ for (size_t inputNdx = 0; inputNdx < m_shaderSpec.inputs.size(); ++inputNdx)
+ {
+ AllocationMp alloc;
+ const BufferSp& input = m_shaderSpec.inputs[inputNdx];
+ const size_t numBytes = input->getNumBytes();
+ BufferHandleUp* buffer = new BufferHandleUp(createBufferAndBindMemory(vkdi, device, allocator, numBytes, &alloc));
+
+ setMemory(vkdi, device, &*alloc, numBytes, input->data());
+ descriptorInfos.push_back(vk::makeDescriptorBufferInfo(**buffer, 0u, numBytes));
+ inputBuffers.push_back(BufferHandleSp(buffer));
+ inputAllocs.push_back(de::SharedPtr<Allocation>(alloc.release()));
+ }
+
+ for (size_t outputNdx = 0; outputNdx < m_shaderSpec.outputs.size(); ++outputNdx)
+ {
+ AllocationMp alloc;
+ const BufferSp& output = m_shaderSpec.outputs[outputNdx];
+ const size_t numBytes = output->getNumBytes();
+ BufferHandleUp* buffer = new BufferHandleUp(createBufferAndBindMemory(vkdi, device, allocator, numBytes, &alloc));
+
+ clearMemory(vkdi, device, &*alloc, numBytes);
+ descriptorInfos.push_back(vk::makeDescriptorBufferInfo(**buffer, 0u, numBytes));
+ outputBuffers.push_back(BufferHandleSp(buffer));
+ outputAllocs.push_back(de::SharedPtr<Allocation>(alloc.release()));
+ }
+
+ // Create layouts and descriptor set.
+
+ Unique<VkDescriptorSetLayout> descriptorSetLayout (createDescriptorSetLayout(vkdi, device, numBuffers));
+ Unique<VkPipelineLayout> pipelineLayout (createPipelineLayout(vkdi, device, *descriptorSetLayout));
+ Unique<VkDescriptorPool> descriptorPool (createDescriptorPool(vkdi, device, (deUint32)numBuffers));
+ Unique<VkDescriptorSet> descriptorSet (createDescriptorSet(vkdi, device, *descriptorPool, *descriptorSetLayout, numBuffers, descriptorInfos));
+
+ // Create compute shader and pipeline.
+
+ const ProgramBinary& binary = m_context.getBinaryCollection().get("compute");
+ Unique<VkShaderModule> module (createShaderModule(vkdi, device, binary, (VkShaderModuleCreateFlags)0u));
+
+ Unique<VkPipeline> computePipeline (createComputePipeline(vkdi, device, *pipelineLayout, *module));
+
+ // Create command buffer and record commands
+
+ const Unique<VkCommandPool> cmdPool (createCommandPool(vkdi, device, m_context.getUniversalQueueFamilyIndex()));
+ const VkCommandBufferAllocateInfo cmdBufferCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType
+ NULL, // pNext
+ *cmdPool, // cmdPool
+ VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level
+ 1u // count
+ };
+
+ Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer(vkdi, device, &cmdBufferCreateInfo));
+
+ const VkCommandBufferBeginInfo cmdBufferBeginInfo =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
+ DE_NULL, // pNext
+ VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
+ (VkRenderPass)0u, // renderPass
+ 0u, // subpass
+ (VkFramebuffer)0u, // framebuffer
+ VK_FALSE, // occlusionQueryEnable
+ (VkQueryControlFlags)0,
+ (VkQueryPipelineStatisticFlags)0,
+ };
+
+ const tcu::IVec3& numWorkGroups = m_shaderSpec.numWorkGroups;
+
+ VK_CHECK(vkdi.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
+ vkdi.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipeline);
+ vkdi.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0, 1, &descriptorSet.get(), 0, DE_NULL);
+ vkdi.cmdDispatch(*cmdBuffer, numWorkGroups.x(), numWorkGroups.y(), numWorkGroups.z());
+ VK_CHECK(vkdi.endCommandBuffer(*cmdBuffer));
+
+ // Create fence and run.
+
+ const VkFenceCreateInfo fenceCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // sType
+ NULL, // pNext
+ 0 // flags
+ };
+ const Unique<VkFence> cmdCompleteFence (createFence(vkdi, device, &fenceCreateInfo));
+ const deUint64 infiniteTimeout = ~(deUint64)0u;
+ const VkSubmitInfo submitInfo =
+ {
+ VK_STRUCTURE_TYPE_SUBMIT_INFO,
+ DE_NULL,
+ 0u,
+ (const VkSemaphore*)DE_NULL,
+ 1u,
+ &cmdBuffer.get(),
+ 0u,
+ (const VkSemaphore*)DE_NULL,
+ };
+
+ VK_CHECK(vkdi.queueSubmit(m_context.getUniversalQueue(), 1, &submitInfo, *cmdCompleteFence));
+ VK_CHECK(vkdi.waitForFences(device, 1, &cmdCompleteFence.get(), 0u, infiniteTimeout)); // \note: timeout is failure
+
+ // Check output.
+
+ for (size_t outputNdx = 0; outputNdx < m_shaderSpec.outputs.size(); ++outputNdx)
+ {
+ const BufferSp& expectedOutput = m_shaderSpec.outputs[outputNdx];
+ if (deMemCmp(expectedOutput->data(), outputAllocs[outputNdx]->getHostPtr(), expectedOutput->getNumBytes()))
+ return tcu::TestStatus::fail("Output doesn't match with expected");
+ }
+
+ return tcu::TestStatus::pass("Ouput match with expected");
+}
+
+} // SpirVAssembly
+} // vkt
--- /dev/null
+#ifndef _VKTSPVASMCOMPUTESHADERCASE_HPP
+#define _VKTSPVASMCOMPUTESHADERCASE_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Test Case Skeleton Based on Compute Shaders
+ *//*--------------------------------------------------------------------*/
+
+#include "vkPrograms.hpp"
+#include "vktTestCase.hpp"
+
+#include "vktSpvAsmComputeShaderTestUtil.hpp"
+
+namespace vkt
+{
+namespace SpirVAssembly
+{
+
+class SpvAsmComputeShaderCase : public TestCase
+{
+public:
+ SpvAsmComputeShaderCase (tcu::TestContext& testCtx, const char* name, const char* description, const ComputeShaderSpec& spec);
+ void initPrograms (vk::SourceCollections& programCollection) const;
+ TestInstance* createInstance (Context& ctx) const;
+
+private:
+ ComputeShaderSpec m_shaderSpec;
+};
+
+} // SpirVAssembly
+} // vkt
+
+#endif // _VKTSPVASMCOMPUTESHADERCASE_HPP
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Compute Shader Based Test Case Utility Structs/Functions
+ *//*--------------------------------------------------------------------*/
+
+#include "vktSpvAsmComputeShaderTestUtil.hpp"
+
+DE_EMPTY_CPP_FILE
--- /dev/null
+#ifndef _VKTSPVASMCOMPUTESHADERTESTUTIL_HPP
+#define _VKTSPVASMCOMPUTESHADERTESTUTIL_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Compute Shader Based Test Case Utility Structs/Functions
+ *//*--------------------------------------------------------------------*/
+
+#include "deDefs.h"
+#include "deSharedPtr.hpp"
+#include "tcuVector.hpp"
+
+#include <string>
+#include <vector>
+
+namespace vkt
+{
+namespace SpirVAssembly
+{
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Abstract class for an input/output storage buffer object
+ *//*--------------------------------------------------------------------*/
+class BufferInterface
+{
+public:
+ virtual ~BufferInterface (void) {}
+
+ virtual size_t getNumBytes (void) const = 0;
+ virtual const void* data (void) const = 0;
+};
+
+typedef de::SharedPtr<BufferInterface> BufferSp;
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Concrete class for an input/output storage buffer object
+ *//*--------------------------------------------------------------------*/
+template<typename E>
+class Buffer : public BufferInterface
+{
+public:
+ Buffer (const std::vector<E>& elements)
+ : m_elements(elements)
+ {}
+
+ size_t getNumBytes (void) const { return m_elements.size() * sizeof(E); }
+ const void* data (void) const { return &m_elements.front(); }
+
+private:
+ std::vector<E> m_elements;
+};
+
+typedef Buffer<float> Float32Buffer;
+
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Specification for a compute shader.
+ *
+ * This struct bundles SPIR-V assembly code, input and expected output
+ * together.
+ *//*--------------------------------------------------------------------*/
+struct ComputeShaderSpec
+{
+ std::string assembly;
+ std::vector<BufferSp> inputs;
+ std::vector<BufferSp> outputs;
+ tcu::IVec3 numWorkGroups;
+};
+
+} // SpirVAssembly
+} // vkt
+
+#endif // _VKTSPVASMCOMPUTESHADERTESTUTIL_HPP
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief SPIR-V Assembly Tests for Instructions (special opcode/operand)
+ *//*--------------------------------------------------------------------*/
+
+#include "vktSpvAsmInstructionTests.hpp"
+
+#include "tcuCommandLine.hpp"
+#include "tcuFormatUtil.hpp"
+#include "tcuRGBA.hpp"
+#include "tcuStringTemplate.hpp"
+#include "tcuTestLog.hpp"
+#include "tcuVectorUtil.hpp"
+
+#include "vkDefs.hpp"
+#include "vkDeviceUtil.hpp"
+#include "vkMemUtil.hpp"
+#include "vkPlatform.hpp"
+#include "vkPrograms.hpp"
+#include "vkQueryUtil.hpp"
+#include "vkRef.hpp"
+#include "vkRefUtil.hpp"
+#include "vkStrUtil.hpp"
+#include "vkTypeUtil.hpp"
+
+#include "deRandom.hpp"
+#include "deStringUtil.hpp"
+#include "deUniquePtr.hpp"
+#include "tcuStringTemplate.hpp"
+
+#include "vktSpvAsmComputeShaderCase.hpp"
+#include "vktSpvAsmComputeShaderTestUtil.hpp"
+#include "vktTestCaseUtil.hpp"
+
+#include <map>
+#include <string>
+#include <sstream>
+
+namespace vkt
+{
+namespace SpirVAssembly
+{
+
+namespace
+{
+
+using namespace vk;
+using std::map;
+using std::string;
+using std::vector;
+using tcu::IVec3;
+using tcu::IVec4;
+using tcu::RGBA;
+using tcu::TestLog;
+using tcu::TestStatus;
+using tcu::Vec4;
+using de::UniquePtr;
+using tcu::StringTemplate;
+
+typedef Unique<VkShaderModule> ModuleHandleUp;
+typedef de::SharedPtr<ModuleHandleUp> ModuleHandleSp;
+
+template<typename T> T randomScalar (de::Random& rnd, T minValue, T maxValue);
+template<> inline float randomScalar (de::Random& rnd, float minValue, float maxValue) { return rnd.getFloat(minValue, maxValue); }
+template<> inline deInt32 randomScalar (de::Random& rnd, deInt32 minValue, deInt32 maxValue) { return rnd.getInt(minValue, maxValue); }
+template<> inline deUint32 randomScalar (de::Random& rnd, deUint32 minValue, deUint32 maxValue) { return minValue + rnd.getUint32() % (maxValue - minValue + 1); }
+
+template<typename T>
+static void fillRandomScalars (de::Random& rnd, T minValue, T maxValue, void* dst, int numValues, int offset = 0)
+{
+ T* const typedPtr = (T*)dst;
+ for (int ndx = 0; ndx < numValues; ndx++)
+ typedPtr[offset + ndx] = randomScalar<T>(rnd, minValue, maxValue);
+}
+
+// Assembly code used for testing OpNop, OpConstant{Null|Composite}, Op[No]Line, OpSource[Continued], OpSourceExtension, OpUndef is based on GLSL source code:
+//
+// #version 430
+//
+// layout(std140, set = 0, binding = 0) readonly buffer Input {
+// float elements[];
+// } input_data;
+// layout(std140, set = 0, binding = 1) writeonly buffer Output {
+// float elements[];
+// } output_data;
+//
+// layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+//
+// void main() {
+// uint x = gl_GlobalInvocationID.x;
+// output_data.elements[x] = -input_data.elements[x];
+// }
+
+static const char* const s_ShaderPreamble =
+ "OpCapability Shader\n"
+ "OpMemoryModel Logical GLSL450\n"
+ "OpEntryPoint GLCompute %main \"main\" %id\n"
+ "OpExecutionMode %main LocalSize 1 1 1\n";
+
+static const char* const s_CommonTypes =
+ "%bool = OpTypeBool\n"
+ "%void = OpTypeVoid\n"
+ "%voidf = OpTypeFunction %void\n"
+ "%u32 = OpTypeInt 32 0\n"
+ "%i32 = OpTypeInt 32 1\n"
+ "%f32 = OpTypeFloat 32\n"
+ "%uvec3 = OpTypeVector %u32 3\n"
+ "%uvec3ptr = OpTypePointer Input %uvec3\n"
+ "%f32ptr = OpTypePointer Uniform %f32\n"
+ "%f32arr = OpTypeRuntimeArray %f32\n";
+
+// Declares two uniform variables (indata, outdata) of type "struct { float[] }". Depends on type "f32arr" (for "float[]").
+static const char* const s_InputOutputBuffer =
+ "%inbuf = OpTypeStruct %f32arr\n"
+ "%inbufptr = OpTypePointer Uniform %inbuf\n"
+ "%indata = OpVariable %inbufptr Uniform\n"
+ "%outbuf = OpTypeStruct %f32arr\n"
+ "%outbufptr = OpTypePointer Uniform %outbuf\n"
+ "%outdata = OpVariable %outbufptr Uniform\n";
+
+// Declares buffer type and layout for uniform variables indata and outdata. Both of them are SSBO bounded to descriptor set 0.
+// indata is at binding point 0, while outdata is at 1.
+static const char* const s_InputOutputBufferTraits =
+ "OpDecorate %inbuf BufferBlock\n"
+ "OpDecorate %indata DescriptorSet 0\n"
+ "OpDecorate %indata Binding 0\n"
+ "OpDecorate %outbuf BufferBlock\n"
+ "OpDecorate %outdata DescriptorSet 0\n"
+ "OpDecorate %outdata Binding 1\n"
+ "OpDecorate %f32arr ArrayStride 4\n"
+ "OpMemberDecorate %inbuf 0 Offset 0\n"
+ "OpMemberDecorate %outbuf 0 Offset 0\n";
+
+tcu::TestCaseGroup* createOpNopGroup (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opnop", "Test the OpNop instruction"));
+ ComputeShaderSpec spec;
+ de::Random rnd (deStringHash(group->getName()));
+ const int numElements = 100;
+ vector<float> positiveFloats (numElements, 0);
+ vector<float> negativeFloats (numElements, 0);
+
+ fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
+
+ for (size_t ndx = 0; ndx < numElements; ++ndx)
+ negativeFloats[ndx] = -positiveFloats[ndx];
+
+ spec.assembly =
+ string(s_ShaderPreamble) +
+
+ "OpSource GLSL 430\n"
+ "OpName %main \"main\"\n"
+ "OpName %id \"gl_GlobalInvocationID\"\n"
+
+ "OpDecorate %id BuiltIn GlobalInvocationId\n"
+
+ + string(s_InputOutputBufferTraits) + string(s_CommonTypes)
+
+ + string(s_InputOutputBuffer) +
+
+ "%id = OpVariable %uvec3ptr Input\n"
+ "%zero = OpConstant %i32 0\n"
+
+ "%main = OpFunction %void None %voidf\n"
+ "%label = OpLabel\n"
+ "%idval = OpLoad %uvec3 %id\n"
+ "%x = OpCompositeExtract %u32 %idval 0\n"
+
+ " OpNop\n" // Inside a function body
+
+ "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
+ "%inval = OpLoad %f32 %inloc\n"
+ "%neg = OpFNegate %f32 %inval\n"
+ "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
+ " OpStore %outloc %neg\n"
+ " OpReturn\n"
+ " OpFunctionEnd\n";
+ spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
+ spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
+ spec.numWorkGroups = IVec3(numElements, 1, 1);
+
+ group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "OpNop appearing at different places", spec));
+
+ return group.release();
+}
+
+tcu::TestCaseGroup* createOpLineGroup (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opline", "Test the OpLine instruction"));
+ ComputeShaderSpec spec;
+ de::Random rnd (deStringHash(group->getName()));
+ const int numElements = 100;
+ vector<float> positiveFloats (numElements, 0);
+ vector<float> negativeFloats (numElements, 0);
+
+ fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
+
+ for (size_t ndx = 0; ndx < numElements; ++ndx)
+ negativeFloats[ndx] = -positiveFloats[ndx];
+
+ spec.assembly =
+ string(s_ShaderPreamble) +
+
+ "%fname1 = OpString \"negateInputs.comp\"\n"
+ "%fname2 = OpString \"negateInputs\"\n"
+
+ "OpSource GLSL 430\n"
+ "OpName %main \"main\"\n"
+ "OpName %id \"gl_GlobalInvocationID\"\n"
+
+ "OpDecorate %id BuiltIn GlobalInvocationId\n"
+
+ + string(s_InputOutputBufferTraits) +
+
+ "OpLine %fname1 0 0\n" // At the earliest possible position
+
+ + string(s_CommonTypes) + string(s_InputOutputBuffer) +
+
+ "OpLine %fname1 0 1\n" // Multiple OpLines in sequence
+ "OpLine %fname2 1 0\n" // Different filenames
+ "OpLine %fname1 1000 100000\n"
+
+ "%id = OpVariable %uvec3ptr Input\n"
+ "%zero = OpConstant %i32 0\n"
+
+ "OpLine %fname1 1 1\n" // Before a function
+
+ "%main = OpFunction %void None %voidf\n"
+ "%label = OpLabel\n"
+
+ "OpLine %fname1 1 1\n" // In a function
+
+ "%idval = OpLoad %uvec3 %id\n"
+ "%x = OpCompositeExtract %u32 %idval 0\n"
+ "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
+ "%inval = OpLoad %f32 %inloc\n"
+ "%neg = OpFNegate %f32 %inval\n"
+ "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
+ " OpStore %outloc %neg\n"
+ " OpReturn\n"
+ " OpFunctionEnd\n";
+ spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
+ spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
+ spec.numWorkGroups = IVec3(numElements, 1, 1);
+
+ group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "OpLine appearing at different places", spec));
+
+ return group.release();
+}
+
+tcu::TestCaseGroup* createOpNoLineGroup (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opnoline", "Test the OpNoLine instruction"));
+ ComputeShaderSpec spec;
+ de::Random rnd (deStringHash(group->getName()));
+ const int numElements = 100;
+ vector<float> positiveFloats (numElements, 0);
+ vector<float> negativeFloats (numElements, 0);
+
+ fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
+
+ for (size_t ndx = 0; ndx < numElements; ++ndx)
+ negativeFloats[ndx] = -positiveFloats[ndx];
+
+ spec.assembly =
+ string(s_ShaderPreamble) +
+
+ "%fname = OpString \"negateInputs.comp\"\n"
+
+ "OpSource GLSL 430\n"
+ "OpName %main \"main\"\n"
+ "OpName %id \"gl_GlobalInvocationID\"\n"
+
+ "OpDecorate %id BuiltIn GlobalInvocationId\n"
+
+ + string(s_InputOutputBufferTraits) +
+
+ "OpNoLine\n" // At the earliest possible position, without preceding OpLine
+
+ + string(s_CommonTypes) + string(s_InputOutputBuffer) +
+
+ "OpLine %fname 0 1\n"
+ "OpNoLine\n" // Immediately following a preceding OpLine
+
+ "OpLine %fname 1000 1\n"
+
+ "%id = OpVariable %uvec3ptr Input\n"
+ "%zero = OpConstant %i32 0\n"
+
+ "OpNoLine\n" // Contents after the previous OpLine
+
+ "%main = OpFunction %void None %voidf\n"
+ "%label = OpLabel\n"
+ "%idval = OpLoad %uvec3 %id\n"
+ "%x = OpCompositeExtract %u32 %idval 0\n"
+
+ "OpNoLine\n" // Multiple OpNoLine
+ "OpNoLine\n"
+ "OpNoLine\n"
+
+ "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
+ "%inval = OpLoad %f32 %inloc\n"
+ "%neg = OpFNegate %f32 %inval\n"
+ "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
+ " OpStore %outloc %neg\n"
+ " OpReturn\n"
+ " OpFunctionEnd\n";
+ spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
+ spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
+ spec.numWorkGroups = IVec3(numElements, 1, 1);
+
+ group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "OpNoLine appearing at different places", spec));
+
+ return group.release();
+}
+
+// Assembly code used for testing OpUnreachable is based on GLSL source code:
+//
+// #version 430
+//
+// layout(std140, set = 0, binding = 0) readonly buffer Input {
+// float elements[];
+// } input_data;
+// layout(std140, set = 0, binding = 1) writeonly buffer Output {
+// float elements[];
+// } output_data;
+//
+// void not_called_func() {
+// // place OpUnreachable here
+// }
+//
+// uint modulo4(uint val) {
+// switch (val % uint(4)) {
+// case 0: return 3;
+// case 1: return 2;
+// case 2: return 1;
+// case 3: return 0;
+// default: return 100; // place OpUnreachable here
+// }
+// }
+//
+// uint const5() {
+// return 5;
+// // place OpUnreachable here
+// }
+//
+// void main() {
+// uint x = gl_GlobalInvocationID.x;
+// if (const5() > modulo4(1000)) {
+// output_data.elements[x] = -input_data.elements[x];
+// } else {
+// // place OpUnreachable here
+// output_data.elements[x] = input_data.elements[x];
+// }
+// }
+
+tcu::TestCaseGroup* createOpUnreachableGroup (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opunreachable", "Test the OpUnreachable instruction"));
+ ComputeShaderSpec spec;
+ de::Random rnd (deStringHash(group->getName()));
+ const int numElements = 100;
+ vector<float> positiveFloats (numElements, 0);
+ vector<float> negativeFloats (numElements, 0);
+
+ fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
+
+ for (size_t ndx = 0; ndx < numElements; ++ndx)
+ negativeFloats[ndx] = -positiveFloats[ndx];
+
+ spec.assembly =
+ string(s_ShaderPreamble) +
+
+ "OpSource GLSL 430\n"
+ "OpName %func_main \"main\"\n"
+ "OpName %func_not_called_func \"not_called_func(\"\n"
+ "OpName %func_modulo4 \"modulo4(u1;\"\n"
+ "OpName %func_const5 \"const5(\"\n"
+ "OpName %id \"gl_GlobalInvocationID\"\n"
+
+ "OpDecorate %id BuiltIn GlobalInvocationId\n"
+
+ + string(s_InputOutputBufferTraits) + string(s_CommonTypes) +
+
+ "%u32ptr = OpTypePointer Function %u32\n"
+ "%uintfuint = OpTypeFunction %u32 %u32ptr\n"
+ "%unitf = OpTypeFunction %u32\n"
+
+ "%id = OpVariable %uvec3ptr Input\n"
+ "%zero = OpConstant %u32 0\n"
+ "%one = OpConstant %u32 1\n"
+ "%two = OpConstant %u32 2\n"
+ "%three = OpConstant %u32 3\n"
+ "%four = OpConstant %u32 4\n"
+ "%five = OpConstant %u32 5\n"
+ "%hundred = OpConstant %u32 100\n"
+ "%thousand = OpConstant %u32 1000\n"
+
+ + string(s_InputOutputBuffer) +
+
+ // Main()
+ "%func_main = OpFunction %void None %voidf\n"
+ "%main_entry = OpLabel\n"
+ "%idval = OpLoad %uvec3 %id\n"
+ "%x = OpCompositeExtract %u32 %idval 0\n"
+ "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
+ "%inval = OpLoad %f32 %inloc\n"
+ "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
+ "%ret_const5 = OpFunctionCall %u32 %func_const5\n"
+ "%ret_modulo4 = OpFunctionCall %u32 %func_modulo4 %thousand\n"
+ "%cmp_gt = OpUGreaterThan %bool %ret_const5 %ret_modulo4\n"
+ " OpSelectionMerge %if_end None\n"
+ " OpBranchConditional %cmp_gt %if_true %if_false\n"
+ "%if_true = OpLabel\n"
+ "%negate = OpFNegate %f32 %inval\n"
+ " OpStore %outloc %negate\n"
+ " OpBranch %if_end\n"
+ "%if_false = OpLabel\n"
+ " OpUnreachable\n" // Unreachable else branch for if statement
+ "%if_end = OpLabel\n"
+ " OpReturn\n"
+ " OpFunctionEnd\n"
+
+ // not_called_function()
+ "%func_not_called_func = OpFunction %void None %voidf\n"
+ "%not_called_func_entry = OpLabel\n"
+ " OpUnreachable\n" // Unreachable entry block in not called static function
+ " OpFunctionEnd\n"
+
+ // modulo4()
+ "%func_modulo4 = OpFunction %u32 None %uintfuint\n"
+ "%valptr = OpFunctionParameter %u32ptr\n"
+ "%modulo4_entry = OpLabel\n"
+ "%val = OpLoad %u32 %valptr\n"
+ "%modulo = OpUMod %u32 %val %four\n"
+ " OpSelectionMerge %switch_merge None\n"
+ " OpSwitch %modulo %default 0 %case0 1 %case1 2 %case2 3 %case3\n"
+ "%case0 = OpLabel\n"
+ " OpReturnValue %three\n"
+ "%case1 = OpLabel\n"
+ " OpReturnValue %two\n"
+ "%case2 = OpLabel\n"
+ " OpReturnValue %one\n"
+ "%case3 = OpLabel\n"
+ " OpReturnValue %zero\n"
+ "%default = OpLabel\n"
+ " OpUnreachable\n" // Unreachable default case for switch statement
+ "%switch_merge = OpLabel\n"
+ " OpUnreachable\n" // Unreachable merge block for switch statement
+ " OpFunctionEnd\n"
+
+ // const5()
+ "%func_const5 = OpFunction %u32 None %unitf\n"
+ "%const5_entry = OpLabel\n"
+ " OpReturnValue %five\n"
+ "%unreachable = OpLabel\n"
+ " OpUnreachable\n" // Unreachable block in function
+ " OpFunctionEnd\n";
+ spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
+ spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
+ spec.numWorkGroups = IVec3(numElements, 1, 1);
+
+ group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "OpUnreachable appearing at different places", spec));
+
+ return group.release();
+}
+
+// Assembly code used for testing decoration group is based on GLSL source code:
+//
+// #version 430
+//
+// layout(std140, set = 0, binding = 0) readonly buffer Input0 {
+// float elements[];
+// } input_data0;
+// layout(std140, set = 0, binding = 1) readonly buffer Input1 {
+// float elements[];
+// } input_data1;
+// layout(std140, set = 0, binding = 2) readonly buffer Input2 {
+// float elements[];
+// } input_data2;
+// layout(std140, set = 0, binding = 3) readonly buffer Input3 {
+// float elements[];
+// } input_data3;
+// layout(std140, set = 0, binding = 4) readonly buffer Input4 {
+// float elements[];
+// } input_data4;
+// layout(std140, set = 0, binding = 5) writeonly buffer Output {
+// float elements[];
+// } output_data;
+//
+// void main() {
+// uint x = gl_GlobalInvocationID.x;
+// output_data.elements[x] = input_data0.elements[x] + input_data1.elements[x] + input_data2.elements[x] + input_data3.elements[x] + input_data4.elements[x];
+// }
+tcu::TestCaseGroup* createDecorationGroupGroup (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "decoration_group", "Test the OpDecorationGroup & OpGroupDecorate instruction"));
+ ComputeShaderSpec spec;
+ de::Random rnd (deStringHash(group->getName()));
+ const int numElements = 100;
+ vector<float> inputFloats0 (numElements, 0);
+ vector<float> inputFloats1 (numElements, 0);
+ vector<float> inputFloats2 (numElements, 0);
+ vector<float> inputFloats3 (numElements, 0);
+ vector<float> inputFloats4 (numElements, 0);
+ vector<float> outputFloats (numElements, 0);
+
+ fillRandomScalars(rnd, -300.f, 300.f, &inputFloats0[0], numElements);
+ fillRandomScalars(rnd, -300.f, 300.f, &inputFloats1[0], numElements);
+ fillRandomScalars(rnd, -300.f, 300.f, &inputFloats2[0], numElements);
+ fillRandomScalars(rnd, -300.f, 300.f, &inputFloats3[0], numElements);
+ fillRandomScalars(rnd, -300.f, 300.f, &inputFloats4[0], numElements);
+
+ for (size_t ndx = 0; ndx < numElements; ++ndx)
+ outputFloats[ndx] = inputFloats0[ndx] + inputFloats1[ndx] + inputFloats2[ndx] + inputFloats3[ndx] + inputFloats4[ndx];
+
+ spec.assembly =
+ string(s_ShaderPreamble) +
+
+ "OpSource GLSL 430\n"
+ "OpName %main \"main\"\n"
+ "OpName %id \"gl_GlobalInvocationID\"\n"
+
+ // Not using group decoration on variable.
+ "OpDecorate %id BuiltIn GlobalInvocationId\n"
+ // Not using group decoration on type.
+ "OpDecorate %f32arr ArrayStride 4\n"
+
+ "OpDecorate %groups BufferBlock\n"
+ "OpDecorate %groupm Offset 0\n"
+ "%groups = OpDecorationGroup\n"
+ "%groupm = OpDecorationGroup\n"
+
+ // Group decoration on multiple structs.
+ "OpGroupDecorate %groups %outbuf %inbuf0 %inbuf1 %inbuf2 %inbuf3 %inbuf4\n"
+ // Group decoration on multiple struct members.
+ "OpGroupMemberDecorate %groupm %outbuf 0 %inbuf0 0 %inbuf1 0 %inbuf2 0 %inbuf3 0 %inbuf4 0\n"
+
+ "OpDecorate %group1 DescriptorSet 0\n"
+ "OpDecorate %group3 DescriptorSet 0\n"
+ "OpDecorate %group3 NonWritable\n"
+ "OpDecorate %group3 Restrict\n"
+ "%group0 = OpDecorationGroup\n"
+ "%group1 = OpDecorationGroup\n"
+ "%group3 = OpDecorationGroup\n"
+
+ // Applying the same decoration group multiple times.
+ "OpGroupDecorate %group1 %outdata\n"
+ "OpGroupDecorate %group1 %outdata\n"
+ "OpGroupDecorate %group1 %outdata\n"
+ "OpDecorate %outdata DescriptorSet 0\n"
+ "OpDecorate %outdata Binding 5\n"
+ // Applying decoration group containing nothing.
+ "OpGroupDecorate %group0 %indata0\n"
+ "OpDecorate %indata0 DescriptorSet 0\n"
+ "OpDecorate %indata0 Binding 0\n"
+ // Applying decoration group containing one decoration.
+ "OpGroupDecorate %group1 %indata1\n"
+ "OpDecorate %indata1 Binding 1\n"
+ // Applying decoration group containing multiple decorations.
+ "OpGroupDecorate %group3 %indata2 %indata3\n"
+ "OpDecorate %indata2 Binding 2\n"
+ "OpDecorate %indata3 Binding 3\n"
+ // Applying multiple decoration groups (with overlapping).
+ "OpGroupDecorate %group0 %indata4\n"
+ "OpGroupDecorate %group1 %indata4\n"
+ "OpGroupDecorate %group3 %indata4\n"
+ "OpDecorate %indata4 Binding 4\n"
+
+ + string(s_CommonTypes) +
+
+ "%id = OpVariable %uvec3ptr Input\n"
+ "%zero = OpConstant %i32 0\n"
+
+ "%outbuf = OpTypeStruct %f32arr\n"
+ "%outbufptr = OpTypePointer Uniform %outbuf\n"
+ "%outdata = OpVariable %outbufptr Uniform\n"
+ "%inbuf0 = OpTypeStruct %f32arr\n"
+ "%inbuf0ptr = OpTypePointer Uniform %inbuf0\n"
+ "%indata0 = OpVariable %inbuf0ptr Uniform\n"
+ "%inbuf1 = OpTypeStruct %f32arr\n"
+ "%inbuf1ptr = OpTypePointer Uniform %inbuf1\n"
+ "%indata1 = OpVariable %inbuf1ptr Uniform\n"
+ "%inbuf2 = OpTypeStruct %f32arr\n"
+ "%inbuf2ptr = OpTypePointer Uniform %inbuf2\n"
+ "%indata2 = OpVariable %inbuf2ptr Uniform\n"
+ "%inbuf3 = OpTypeStruct %f32arr\n"
+ "%inbuf3ptr = OpTypePointer Uniform %inbuf3\n"
+ "%indata3 = OpVariable %inbuf3ptr Uniform\n"
+ "%inbuf4 = OpTypeStruct %f32arr\n"
+ "%inbufptr = OpTypePointer Uniform %inbuf4\n"
+ "%indata4 = OpVariable %inbufptr Uniform\n"
+
+ "%main = OpFunction %void None %voidf\n"
+ "%label = OpLabel\n"
+ "%idval = OpLoad %uvec3 %id\n"
+ "%x = OpCompositeExtract %u32 %idval 0\n"
+ "%inloc0 = OpAccessChain %f32ptr %indata0 %zero %x\n"
+ "%inloc1 = OpAccessChain %f32ptr %indata1 %zero %x\n"
+ "%inloc2 = OpAccessChain %f32ptr %indata2 %zero %x\n"
+ "%inloc3 = OpAccessChain %f32ptr %indata3 %zero %x\n"
+ "%inloc4 = OpAccessChain %f32ptr %indata4 %zero %x\n"
+ "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
+ "%inval0 = OpLoad %f32 %inloc0\n"
+ "%inval1 = OpLoad %f32 %inloc1\n"
+ "%inval2 = OpLoad %f32 %inloc2\n"
+ "%inval3 = OpLoad %f32 %inloc3\n"
+ "%inval4 = OpLoad %f32 %inloc4\n"
+ "%add0 = OpFAdd %f32 %inval0 %inval1\n"
+ "%add1 = OpFAdd %f32 %add0 %inval2\n"
+ "%add2 = OpFAdd %f32 %add1 %inval3\n"
+ "%add = OpFAdd %f32 %add2 %inval4\n"
+ " OpStore %outloc %add\n"
+ " OpReturn\n"
+ " OpFunctionEnd\n";
+ spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats0)));
+ spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats1)));
+ spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats2)));
+ spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats3)));
+ spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats4)));
+ spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
+ spec.numWorkGroups = IVec3(numElements, 1, 1);
+
+ group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "decoration group cases", spec));
+
+ return group.release();
+}
+
+tcu::TestCaseGroup* createOpPhiGroup (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opphi", "Test the OpPhi instruction"));
+ ComputeShaderSpec spec;
+ de::Random rnd (deStringHash(group->getName()));
+ const int numElements = 100;
+ vector<float> inputFloats (numElements, 0);
+ vector<float> outputFloats (numElements, 0);
+
+ fillRandomScalars(rnd, -300.f, 300.f, &inputFloats[0], numElements);
+
+ for (size_t ndx = 0; ndx < numElements; ++ndx)
+ {
+ switch (ndx % 3)
+ {
+ case 0: outputFloats[ndx] = inputFloats[ndx] + 5.5f; break;
+ case 1: outputFloats[ndx] = inputFloats[ndx] + 20.5f; break;
+ case 2: outputFloats[ndx] = inputFloats[ndx] + 1.75f; break;
+ default: break;
+ }
+ }
+
+ spec.assembly =
+ string(s_ShaderPreamble) +
+
+ "OpSource GLSL 430\n"
+ "OpName %main \"main\"\n"
+ "OpName %id \"gl_GlobalInvocationID\"\n"
+
+ "OpDecorate %id BuiltIn GlobalInvocationId\n"
+
+ + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
+
+ "%id = OpVariable %uvec3ptr Input\n"
+ "%zero = OpConstant %i32 0\n"
+ "%three = OpConstant %u32 3\n"
+ "%constf5p5 = OpConstant %f32 5.5\n"
+ "%constf20p5 = OpConstant %f32 20.5\n"
+ "%constf1p75 = OpConstant %f32 1.75\n"
+ "%constf8p5 = OpConstant %f32 8.5\n"
+ "%constf6p5 = OpConstant %f32 6.5\n"
+
+ "%main = OpFunction %void None %voidf\n"
+ "%entry = OpLabel\n"
+ "%idval = OpLoad %uvec3 %id\n"
+ "%x = OpCompositeExtract %u32 %idval 0\n"
+ "%selector = OpUMod %u32 %x %three\n"
+ " OpSelectionMerge %default None\n"
+ " OpSwitch %selector %default 0 %case0 1 %case1 2 %case2\n"
+
+ // Case 1 before OpPhi.
+ "%case1 = OpLabel\n"
+ " OpBranch %phi\n"
+
+ "%default = OpLabel\n"
+ " OpUnreachable\n"
+
+ "%phi = OpLabel\n"
+ "%operand = OpPhi %f32 %constf1p75 %case2 %constf20p5 %case1 %constf5p5 %case0" // not in the order of blocks
+ " %constf8p5 %phi %constf6p5 %default\n" // from the same block & from an unreachable block
+ "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
+ "%inval = OpLoad %f32 %inloc\n"
+ "%add = OpFAdd %f32 %inval %operand\n"
+ "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
+ " OpStore %outloc %add\n"
+ " OpReturn\n"
+
+ // Case 0 after OpPhi.
+ "%case0 = OpLabel\n"
+ " OpBranch %phi\n"
+
+
+ // Case 2 after OpPhi.
+ "%case2 = OpLabel\n"
+ " OpBranch %phi\n"
+
+ " OpFunctionEnd\n";
+ spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
+ spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
+ spec.numWorkGroups = IVec3(numElements, 1, 1);
+
+ group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "OpPhi corner cases", spec));
+
+ return group.release();
+}
+
+// Assembly code used for testing block order is based on GLSL source code:
+//
+// #version 430
+//
+// layout(std140, set = 0, binding = 0) readonly buffer Input {
+// float elements[];
+// } input_data;
+// layout(std140, set = 0, binding = 1) writeonly buffer Output {
+// float elements[];
+// } output_data;
+//
+// void main() {
+// uint x = gl_GlobalInvocationID.x;
+// output_data.elements[x] = input_data.elements[x];
+// if (x > uint(50)) {
+// switch (x % uint(3)) {
+// case 0: output_data.elements[x] += 1.5f; break;
+// case 1: output_data.elements[x] += 42.f; break;
+// case 2: output_data.elements[x] -= 27.f; break;
+// default: break;
+// }
+// } else {
+// output_data.elements[x] = -input_data.elements[x];
+// }
+// }
+tcu::TestCaseGroup* createBlockOrderGroup (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "block_order", "Test block orders"));
+ ComputeShaderSpec spec;
+ de::Random rnd (deStringHash(group->getName()));
+ const int numElements = 100;
+ vector<float> inputFloats (numElements, 0);
+ vector<float> outputFloats (numElements, 0);
+
+ fillRandomScalars(rnd, -100.f, 100.f, &inputFloats[0], numElements);
+
+ for (size_t ndx = 0; ndx <= 50; ++ndx)
+ outputFloats[ndx] = -inputFloats[ndx];
+
+ for (size_t ndx = 51; ndx < numElements; ++ndx)
+ {
+ switch (ndx % 3)
+ {
+ case 0: outputFloats[ndx] = inputFloats[ndx] + 1.5f; break;
+ case 1: outputFloats[ndx] = inputFloats[ndx] + 42.f; break;
+ case 2: outputFloats[ndx] = inputFloats[ndx] - 27.f; break;
+ default: break;
+ }
+ }
+
+ spec.assembly =
+ string(s_ShaderPreamble) +
+
+ "OpSource GLSL 430\n"
+ "OpName %main \"main\"\n"
+ "OpName %id \"gl_GlobalInvocationID\"\n"
+
+ "OpDecorate %id BuiltIn GlobalInvocationId\n"
+
+ + string(s_InputOutputBufferTraits) + string(s_CommonTypes) +
+
+ "%u32ptr = OpTypePointer Function %u32\n"
+ "%u32ptr_input = OpTypePointer Input %u32\n"
+
+ + string(s_InputOutputBuffer) +
+
+ "%id = OpVariable %uvec3ptr Input\n"
+ "%zero = OpConstant %i32 0\n"
+ "%const3 = OpConstant %u32 3\n"
+ "%const50 = OpConstant %u32 50\n"
+ "%constf1p5 = OpConstant %f32 1.5\n"
+ "%constf27 = OpConstant %f32 27.0\n"
+ "%constf42 = OpConstant %f32 42.0\n"
+
+ "%main = OpFunction %void None %voidf\n"
+
+ // entry block.
+ "%entry = OpLabel\n"
+
+ // Create a temporary variable to hold the value of gl_GlobalInvocationID.x.
+ "%xvar = OpVariable %u32ptr Function\n"
+ "%xptr = OpAccessChain %u32ptr_input %id %zero\n"
+ "%x = OpLoad %u32 %xptr\n"
+ " OpStore %xvar %x\n"
+
+ "%cmp = OpUGreaterThan %bool %x %const50\n"
+ " OpSelectionMerge %if_merge None\n"
+ " OpBranchConditional %cmp %if_true %if_false\n"
+
+ // Merge block for switch-statement: placed at the beginning.
+ "%switch_merge = OpLabel\n"
+ " OpBranch %if_merge\n"
+
+ // Case 1 for switch-statement.
+ "%case1 = OpLabel\n"
+ "%x_1 = OpLoad %u32 %xvar\n"
+ "%inloc_1 = OpAccessChain %f32ptr %indata %zero %x_1\n"
+ "%inval_1 = OpLoad %f32 %inloc_1\n"
+ "%addf42 = OpFAdd %f32 %inval_1 %constf42\n"
+ "%outloc_1 = OpAccessChain %f32ptr %outdata %zero %x_1\n"
+ " OpStore %outloc_1 %addf42\n"
+ " OpBranch %switch_merge\n"
+
+ // False branch for if-statement: placed in the middle of switch cases and before true branch.
+ "%if_false = OpLabel\n"
+ "%x_f = OpLoad %u32 %xvar\n"
+ "%inloc_f = OpAccessChain %f32ptr %indata %zero %x_f\n"
+ "%inval_f = OpLoad %f32 %inloc_f\n"
+ "%negate = OpFNegate %f32 %inval_f\n"
+ "%outloc_f = OpAccessChain %f32ptr %outdata %zero %x_f\n"
+ " OpStore %outloc_f %negate\n"
+ " OpBranch %if_merge\n"
+
+ // Merge block for if-statement: placed in the middle of true and false branch.
+ "%if_merge = OpLabel\n"
+ " OpReturn\n"
+
+ // True branch for if-statement: placed in the middle of swtich cases and after the false branch.
+ "%if_true = OpLabel\n"
+ "%xval_t = OpLoad %u32 %xvar\n"
+ "%mod = OpUMod %u32 %xval_t %const3\n"
+ " OpSelectionMerge %switch_merge None\n"
+ " OpSwitch %mod %default 0 %case0 1 %case1 2 %case2\n"
+
+ // Case 2 for switch-statement.
+ "%case2 = OpLabel\n"
+ "%x_2 = OpLoad %u32 %xvar\n"
+ "%inloc_2 = OpAccessChain %f32ptr %indata %zero %x_2\n"
+ "%inval_2 = OpLoad %f32 %inloc_2\n"
+ "%subf27 = OpFSub %f32 %inval_2 %constf27\n"
+ "%outloc_2 = OpAccessChain %f32ptr %outdata %zero %x_2\n"
+ " OpStore %outloc_2 %subf27\n"
+ " OpBranch %switch_merge\n"
+
+ // Default case for switch-statement: placed in the middle of normal cases.
+ "%default = OpLabel\n"
+ " OpBranch %switch_merge\n"
+
+ // Case 0 for switch-statement: out of order.
+ "%case0 = OpLabel\n"
+ "%x_0 = OpLoad %u32 %xvar\n"
+ "%inloc_0 = OpAccessChain %f32ptr %indata %zero %x_0\n"
+ "%inval_0 = OpLoad %f32 %inloc_0\n"
+ "%addf1p5 = OpFAdd %f32 %inval_0 %constf1p5\n"
+ "%outloc_0 = OpAccessChain %f32ptr %outdata %zero %x_0\n"
+ " OpStore %outloc_0 %addf1p5\n"
+ " OpBranch %switch_merge\n"
+
+ " OpFunctionEnd\n";
+ spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
+ spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
+ spec.numWorkGroups = IVec3(numElements, 1, 1);
+
+ group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "various out-of-order blocks", spec));
+
+ return group.release();
+}
+
+struct CaseParameter
+{
+ const char* name;
+ string param;
+
+ CaseParameter (const char* case_, const string& param_) : name(case_), param(param_) {}
+};
+
+tcu::TestCaseGroup* createOpSourceGroup (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opsource", "Tests the OpSource & OpSourceContinued instruction"));
+ vector<CaseParameter> cases;
+ de::Random rnd (deStringHash(group->getName()));
+ const int numElements = 100;
+ vector<float> positiveFloats (numElements, 0);
+ vector<float> negativeFloats (numElements, 0);
+ const StringTemplate shaderTemplate (
+ "OpCapability Shader\n"
+ "OpMemoryModel Logical GLSL450\n"
+
+ "OpEntryPoint GLCompute %main \"main\" %id\n"
+ "OpExecutionMode %main LocalSize 1 1 1\n"
+
+ "${SOURCE}\n"
+
+ "OpName %main \"main\"\n"
+ "OpName %id \"gl_GlobalInvocationID\"\n"
+
+ "OpDecorate %id BuiltIn GlobalInvocationId\n"
+
+ + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
+
+ "%id = OpVariable %uvec3ptr Input\n"
+ "%zero = OpConstant %i32 0\n"
+
+ "%main = OpFunction %void None %voidf\n"
+ "%label = OpLabel\n"
+ "%idval = OpLoad %uvec3 %id\n"
+ "%x = OpCompositeExtract %u32 %idval 0\n"
+ "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
+ "%inval = OpLoad %f32 %inloc\n"
+ "%neg = OpFNegate %f32 %inval\n"
+ "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
+ " OpStore %outloc %neg\n"
+ " OpReturn\n"
+ " OpFunctionEnd\n");
+
+ cases.push_back(CaseParameter("unknown_source", "OpSource Unknown 0"));
+ cases.push_back(CaseParameter("wrong_source", "OpSource OpenCL_C 210"));
+ cases.push_back(CaseParameter("normal_filename", "%fname = OpString \"filename\"\n"
+ "OpSource GLSL 430 %fname"));
+ cases.push_back(CaseParameter("empty_filename", "%fname = OpString \"\"\n"
+ "OpSource GLSL 430 %fname"));
+ cases.push_back(CaseParameter("normal_source_code", "%fname = OpString \"filename\"\n"
+ "OpSource GLSL 430 %fname \"#version 430\nvoid main() {}\""));
+ cases.push_back(CaseParameter("empty_source_code", "%fname = OpString \"filename\"\n"
+ "OpSource GLSL 430 %fname \"\""));
+ cases.push_back(CaseParameter("long_source_code", "%fname = OpString \"filename\"\n"
+ "OpSource GLSL 430 %fname \"" + string(65530, 'x') + "\"")); // word count: 65535
+ cases.push_back(CaseParameter("utf8_source_code", "%fname = OpString \"filename\"\n"
+ "OpSource GLSL 430 %fname \"\xE2\x98\x82\xE2\x98\x85\"")); // umbrella & black star symbol
+ cases.push_back(CaseParameter("normal_sourcecontinued", "%fname = OpString \"filename\"\n"
+ "OpSource GLSL 430 %fname \"#version 430\nvo\"\n"
+ "OpSourceContinued \"id main() {}\""));
+ cases.push_back(CaseParameter("empty_sourcecontinued", "%fname = OpString \"filename\"\n"
+ "OpSource GLSL 430 %fname \"#version 430\nvoid main() {}\"\n"
+ "OpSourceContinued \"\""));
+ cases.push_back(CaseParameter("long_sourcecontinued", "%fname = OpString \"filename\"\n"
+ "OpSource GLSL 430 %fname \"#version 430\nvoid main() {}\"\n"
+ "OpSourceContinued \"" + string(65533, 'x') + "\"")); // word count: 65535
+ cases.push_back(CaseParameter("utf8_sourcecontinued", "%fname = OpString \"filename\"\n"
+ "OpSource GLSL 430 %fname \"#version 430\nvoid main() {}\"\n"
+ "OpSourceContinued \"\xE2\x98\x8E\xE2\x9A\x91\"")); // white telephone & black flag symbol
+ cases.push_back(CaseParameter("multi_sourcecontinued", "%fname = OpString \"filename\"\n"
+ "OpSource GLSL 430 %fname \"#version 430\n\"\n"
+ "OpSourceContinued \"void\"\n"
+ "OpSourceContinued \"main()\"\n"
+ "OpSourceContinued \"{}\""));
+ cases.push_back(CaseParameter("empty_source_before_sourcecontinued", "%fname = OpString \"filename\"\n"
+ "OpSource GLSL 430 %fname \"\"\n"
+ "OpSourceContinued \"#version 430\nvoid main() {}\""));
+
+ fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
+
+ for (size_t ndx = 0; ndx < numElements; ++ndx)
+ negativeFloats[ndx] = -positiveFloats[ndx];
+
+ for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
+ {
+ map<string, string> specializations;
+ ComputeShaderSpec spec;
+
+ specializations["SOURCE"] = cases[caseNdx].param;
+ spec.assembly = shaderTemplate.specialize(specializations);
+ spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
+ spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
+ spec.numWorkGroups = IVec3(numElements, 1, 1);
+
+ group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
+ }
+
+ return group.release();
+}
+
+tcu::TestCaseGroup* createOpSourceExtensionGroup (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opsourceextension", "Tests the OpSource instruction"));
+ vector<CaseParameter> cases;
+ de::Random rnd (deStringHash(group->getName()));
+ const int numElements = 100;
+ vector<float> inputFloats (numElements, 0);
+ vector<float> outputFloats (numElements, 0);
+ const StringTemplate shaderTemplate (
+ string(s_ShaderPreamble) +
+
+ "OpSourceExtension \"${EXTENSION}\"\n"
+
+ "OpName %main \"main\"\n"
+ "OpName %id \"gl_GlobalInvocationID\"\n"
+
+ "OpDecorate %id BuiltIn GlobalInvocationId\n"
+
+ + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
+
+ "%id = OpVariable %uvec3ptr Input\n"
+ "%zero = OpConstant %i32 0\n"
+
+ "%main = OpFunction %void None %voidf\n"
+ "%label = OpLabel\n"
+ "%idval = OpLoad %uvec3 %id\n"
+ "%x = OpCompositeExtract %u32 %idval 0\n"
+ "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
+ "%inval = OpLoad %f32 %inloc\n"
+ "%neg = OpFNegate %f32 %inval\n"
+ "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
+ " OpStore %outloc %neg\n"
+ " OpReturn\n"
+ " OpFunctionEnd\n");
+
+ cases.push_back(CaseParameter("empty_extension", ""));
+ cases.push_back(CaseParameter("real_extension", "GL_ARB_texture_rectangle"));
+ cases.push_back(CaseParameter("fake_extension", "GL_ARB_im_the_ultimate_extension"));
+ cases.push_back(CaseParameter("utf8_extension", "GL_ARB_\xE2\x98\x82\xE2\x98\x85"));
+ cases.push_back(CaseParameter("long_extension", string(65533, 'e'))); // word count: 65535
+
+ fillRandomScalars(rnd, -200.f, 200.f, &inputFloats[0], numElements);
+
+ for (size_t ndx = 0; ndx < numElements; ++ndx)
+ outputFloats[ndx] = -inputFloats[ndx];
+
+ for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
+ {
+ map<string, string> specializations;
+ ComputeShaderSpec spec;
+
+ specializations["EXTENSION"] = cases[caseNdx].param;
+ spec.assembly = shaderTemplate.specialize(specializations);
+ spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
+ spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
+ spec.numWorkGroups = IVec3(numElements, 1, 1);
+
+ group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
+ }
+
+ return group.release();
+}
+
+// Checks that a compute shader can generate a constant null value of various types, without exercising a computation on it.
+tcu::TestCaseGroup* createOpConstantNullGroup (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opconstantnull", "Tests the OpConstantNull instruction"));
+ vector<CaseParameter> cases;
+ de::Random rnd (deStringHash(group->getName()));
+ const int numElements = 100;
+ vector<float> positiveFloats (numElements, 0);
+ vector<float> negativeFloats (numElements, 0);
+ const StringTemplate shaderTemplate (
+ string(s_ShaderPreamble) +
+
+ "OpSource GLSL 430\n"
+ "OpName %main \"main\"\n"
+ "OpName %id \"gl_GlobalInvocationID\"\n"
+
+ "OpDecorate %id BuiltIn GlobalInvocationId\n"
+
+ + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
+
+ "${TYPE}\n"
+ "%null = OpConstantNull %type\n"
+
+ "%id = OpVariable %uvec3ptr Input\n"
+ "%zero = OpConstant %i32 0\n"
+
+ "%main = OpFunction %void None %voidf\n"
+ "%label = OpLabel\n"
+ "%idval = OpLoad %uvec3 %id\n"
+ "%x = OpCompositeExtract %u32 %idval 0\n"
+ "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
+ "%inval = OpLoad %f32 %inloc\n"
+ "%neg = OpFNegate %f32 %inval\n"
+ "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
+ " OpStore %outloc %neg\n"
+ " OpReturn\n"
+ " OpFunctionEnd\n");
+
+ cases.push_back(CaseParameter("bool", "%type = OpTypeBool"));
+ cases.push_back(CaseParameter("sint32", "%type = OpTypeInt 32 1"));
+ cases.push_back(CaseParameter("uint32", "%type = OpTypeInt 32 0"));
+ cases.push_back(CaseParameter("float32", "%type = OpTypeFloat 32"));
+ cases.push_back(CaseParameter("vec4float32", "%type = OpTypeVector %f32 4"));
+ cases.push_back(CaseParameter("vec3bool", "%type = OpTypeVector %bool 3"));
+ cases.push_back(CaseParameter("vec2uint32", "%type = OpTypeVector %u32 2"));
+ cases.push_back(CaseParameter("matrix", "%type = OpTypeMatrix %uvec3 3"));
+ cases.push_back(CaseParameter("array", "%100 = OpConstant %u32 100\n"
+ "%type = OpTypeArray %i32 %100"));
+ cases.push_back(CaseParameter("runtimearray", "%type = OpTypeRuntimeArray %f32"));
+ cases.push_back(CaseParameter("struct", "%type = OpTypeStruct %f32 %i32 %u32"));
+ cases.push_back(CaseParameter("pointer", "%type = OpTypePointer Function %i32"));
+
+ fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
+
+ for (size_t ndx = 0; ndx < numElements; ++ndx)
+ negativeFloats[ndx] = -positiveFloats[ndx];
+
+ for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
+ {
+ map<string, string> specializations;
+ ComputeShaderSpec spec;
+
+ specializations["TYPE"] = cases[caseNdx].param;
+ spec.assembly = shaderTemplate.specialize(specializations);
+ spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
+ spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
+ spec.numWorkGroups = IVec3(numElements, 1, 1);
+
+ group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
+ }
+
+ return group.release();
+}
+
+// Checks that a compute shader can generate a constant composite value of various types, without exercising a computation on it.
+tcu::TestCaseGroup* createOpConstantCompositeGroup (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opconstantcomposite", "Tests the OpConstantComposite instruction"));
+ vector<CaseParameter> cases;
+ de::Random rnd (deStringHash(group->getName()));
+ const int numElements = 100;
+ vector<float> positiveFloats (numElements, 0);
+ vector<float> negativeFloats (numElements, 0);
+ const StringTemplate shaderTemplate (
+ string(s_ShaderPreamble) +
+
+ "OpSource GLSL 430\n"
+ "OpName %main \"main\"\n"
+ "OpName %id \"gl_GlobalInvocationID\"\n"
+
+ "OpDecorate %id BuiltIn GlobalInvocationId\n"
+
+ + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
+
+ "%id = OpVariable %uvec3ptr Input\n"
+ "%zero = OpConstant %i32 0\n"
+
+ "${CONSTANT}\n"
+
+ "%main = OpFunction %void None %voidf\n"
+ "%label = OpLabel\n"
+ "%idval = OpLoad %uvec3 %id\n"
+ "%x = OpCompositeExtract %u32 %idval 0\n"
+ "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
+ "%inval = OpLoad %f32 %inloc\n"
+ "%neg = OpFNegate %f32 %inval\n"
+ "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
+ " OpStore %outloc %neg\n"
+ " OpReturn\n"
+ " OpFunctionEnd\n");
+
+ cases.push_back(CaseParameter("vector", "%five = OpConstant %u32 5\n"
+ "%const = OpConstantComposite %uvec3 %five %zero %five"));
+ cases.push_back(CaseParameter("matrix", "%m3uvec3 = OpTypeMatrix %uvec3 3\n"
+ "%ten = OpConstant %u32 10\n"
+ "%vec = OpConstantComposite %uvec3 %ten %zero %ten\n"
+ "%mat = OpConstantComposite %m3uvec3 %vec %vec %vec"));
+ cases.push_back(CaseParameter("struct", "%m2vec3 = OpTypeMatrix %uvec3 2\n"
+ "%struct = OpTypeStruct %u32 %f32 %uvec3 %m2vec3\n"
+ "%one = OpConstant %u32 1\n"
+ "%point5 = OpConstant %f32 0.5\n"
+ "%vec = OpConstantComposite %uvec3 %one %one %zero\n"
+ "%mat = OpConstantComposite %m2vec3 %vec %vec\n"
+ "%const = OpConstantComposite %one %point5 %vec %mat"));
+ cases.push_back(CaseParameter("nested_struct", "%st1 = OpTypeStruct %u32 %f32\n"
+ "%st2 = OpTypeStruct %i32 %i32\n"
+ "%struct = OpTypeStruct %st1 %st2\n"
+ "%point5 = OpConstant %f32 0.5\n"
+ "%one = OpConstant %u32 1\n"
+ "%ten = OpConstant %i32 10\n"
+ "%st1val = OpConstantComposite %one %point5\n"
+ "%st2val = OpConstantComposite %ten %ten\n"
+ "%const = OpConstantComposite %st1val %st2val"));
+
+ fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
+
+ for (size_t ndx = 0; ndx < numElements; ++ndx)
+ negativeFloats[ndx] = -positiveFloats[ndx];
+
+ for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
+ {
+ map<string, string> specializations;
+ ComputeShaderSpec spec;
+
+ specializations["CONSTANT"] = cases[caseNdx].param;
+ spec.assembly = shaderTemplate.specialize(specializations);
+ spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
+ spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
+ spec.numWorkGroups = IVec3(numElements, 1, 1);
+
+ group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
+ }
+
+ return group.release();
+}
+
+// Checks that constant null/composite values can be used in computation.
+tcu::TestCaseGroup* createOpConstantUsageGroup (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opconstantnullcomposite", "Spotcheck the OpConstantNull & OpConstantComposite instruction"));
+ ComputeShaderSpec spec;
+ de::Random rnd (deStringHash(group->getName()));
+ const int numElements = 100;
+ vector<float> positiveFloats (numElements, 0);
+ vector<float> negativeFloats (numElements, 0);
+
+ fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
+
+ for (size_t ndx = 0; ndx < numElements; ++ndx)
+ negativeFloats[ndx] = -positiveFloats[ndx];
+
+ spec.assembly =
+ "OpCapability Shader\n"
+ "%std450 = OpExtInstImport \"GLSL.std.450\"\n"
+ "OpMemoryModel Logical GLSL450\n"
+ "OpEntryPoint GLCompute %main \"main\" %id\n"
+ "OpExecutionMode %main LocalSize 1 1 1\n"
+
+ "OpSource GLSL 430\n"
+ "OpName %main \"main\"\n"
+ "OpName %id \"gl_GlobalInvocationID\"\n"
+
+ "OpDecorate %id BuiltIn GlobalInvocationId\n"
+
+ + string(s_InputOutputBufferTraits) + string(s_CommonTypes) +
+
+ "%fvec3 = OpTypeVector %f32 3\n"
+ "%fmat = OpTypeMatrix %fvec3 3\n"
+ "%ten = OpConstant %u32 10\n"
+ "%f32arr10 = OpTypeArray %f32 %ten\n"
+ "%fst = OpTypeStruct %f32 %f32\n"
+
+ + string(s_InputOutputBuffer) +
+
+ "%id = OpVariable %uvec3ptr Input\n"
+ "%zero = OpConstant %i32 0\n"
+
+ // Create a bunch of null values
+ "%unull = OpConstantNull %u32\n"
+ "%fnull = OpConstantNull %f32\n"
+ "%vnull = OpConstantNull %fvec3\n"
+ "%mnull = OpConstantNull %fmat\n"
+ "%anull = OpConstantNull %f32arr10\n"
+ "%snull = OpConstantComposite %fst %fnull %fnull\n"
+
+ "%main = OpFunction %void None %voidf\n"
+ "%label = OpLabel\n"
+ "%idval = OpLoad %uvec3 %id\n"
+ "%x = OpCompositeExtract %u32 %idval 0\n"
+ "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
+ "%inval = OpLoad %f32 %inloc\n"
+ "%neg = OpFNegate %f32 %inval\n"
+
+ // Get the abs() of (a certain element of) those null values
+ "%unull_cov = OpConvertUToF %f32 %unull\n"
+ "%unull_abs = OpExtInst %f32 %std450 FAbs %unull_cov\n"
+ "%fnull_abs = OpExtInst %f32 %std450 FAbs %fnull\n"
+ "%vnull_0 = OpCompositeExtract %f32 %vnull 0\n"
+ "%vnull_abs = OpExtInst %f32 %std450 FAbs %vnull_0\n"
+ "%mnull_12 = OpCompositeExtract %f32 %mnull 1 2\n"
+ "%mnull_abs = OpExtInst %f32 %std450 FAbs %mnull_12\n"
+ "%anull_3 = OpCompositeExtract %f32 %anull 3\n"
+ "%anull_abs = OpExtInst %f32 %std450 FAbs %anull_3\n"
+ "%snull_1 = OpCompositeExtract %f32 %snull 1\n"
+ "%snull_abs = OpExtInst %f32 %std450 FAbs %snull_1\n"
+
+ // Add them all
+ "%add1 = OpFAdd %f32 %neg %unull_abs\n"
+ "%add2 = OpFAdd %f32 %add1 %fnull_abs\n"
+ "%add3 = OpFAdd %f32 %add2 %vnull_abs\n"
+ "%add4 = OpFAdd %f32 %add3 %mnull_abs\n"
+ "%add5 = OpFAdd %f32 %add4 %anull_abs\n"
+ "%final = OpFAdd %f32 %add5 %snull_abs\n"
+
+ "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
+ " OpStore %outloc %final\n" // write to output
+ " OpReturn\n"
+ " OpFunctionEnd\n";
+ spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
+ spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
+ spec.numWorkGroups = IVec3(numElements, 1, 1);
+
+ group->addChild(new SpvAsmComputeShaderCase(testCtx, "spotcheck", "Check that values constructed via OpConstantNull & OpConstantComposite can be used", spec));
+
+ return group.release();
+}
+
+// Assembly code used for testing loop control is based on GLSL source code:
+// #version 430
+//
+// layout(std140, set = 0, binding = 0) readonly buffer Input {
+// float elements[];
+// } input_data;
+// layout(std140, set = 0, binding = 1) writeonly buffer Output {
+// float elements[];
+// } output_data;
+//
+// void main() {
+// uint x = gl_GlobalInvocationID.x;
+// output_data.elements[x] = input_data.elements[x];
+// for (uint i = 0; i < 4; ++i)
+// output_data.elements[x] += 1.f;
+// }
+tcu::TestCaseGroup* createLoopControlGroup (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "loop_control", "Tests loop control cases"));
+ vector<CaseParameter> cases;
+ de::Random rnd (deStringHash(group->getName()));
+ const int numElements = 100;
+ vector<float> inputFloats (numElements, 0);
+ vector<float> outputFloats (numElements, 0);
+ const StringTemplate shaderTemplate (
+ string(s_ShaderPreamble) +
+
+ "OpSource GLSL 430\n"
+ "OpName %main \"main\"\n"
+ "OpName %id \"gl_GlobalInvocationID\"\n"
+
+ "OpDecorate %id BuiltIn GlobalInvocationId\n"
+
+ + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
+
+ "%u32ptr = OpTypePointer Function %u32\n"
+
+ "%id = OpVariable %uvec3ptr Input\n"
+ "%zero = OpConstant %i32 0\n"
+ "%one = OpConstant %i32 1\n"
+ "%constf1 = OpConstant %f32 1.0\n"
+ "%four = OpConstant %u32 4\n"
+
+ "%main = OpFunction %void None %voidf\n"
+ "%entry = OpLabel\n"
+ "%i = OpVariable %u32ptr Function\n"
+ " OpStore %i %zero\n"
+
+ "%idval = OpLoad %uvec3 %id\n"
+ "%x = OpCompositeExtract %u32 %idval 0\n"
+ "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
+ "%inval = OpLoad %f32 %inloc\n"
+ "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
+ " OpStore %outloc %inval\n"
+ " OpBranch %loop_entry\n"
+
+ "%loop_entry = OpLabel\n"
+ "%i_val = OpLoad %u32 %i\n"
+ "%cmp_lt = OpULessThan %bool %i_val %four\n"
+ " OpLoopMerge %loop_merge %loop_entry ${CONTROL}\n"
+ " OpBranchConditional %cmp_lt %loop_body %loop_merge\n"
+ "%loop_body = OpLabel\n"
+ "%outval = OpLoad %f32 %outloc\n"
+ "%addf1 = OpFAdd %f32 %outval %constf1\n"
+ " OpStore %outloc %addf1\n"
+ "%new_i = OpIAdd %u32 %i_val %one\n"
+ " OpStore %i %new_i\n"
+ " OpBranch %loop_entry\n"
+ "%loop_merge = OpLabel\n"
+ " OpReturn\n"
+ " OpFunctionEnd\n");
+
+ cases.push_back(CaseParameter("none", "None"));
+ cases.push_back(CaseParameter("unroll", "Unroll"));
+ cases.push_back(CaseParameter("dont_unroll", "DontUnroll"));
+ cases.push_back(CaseParameter("unroll_dont_unroll", "Unroll|DontUnroll"));
+
+ fillRandomScalars(rnd, -100.f, 100.f, &inputFloats[0], numElements);
+
+ for (size_t ndx = 0; ndx < numElements; ++ndx)
+ outputFloats[ndx] = inputFloats[ndx] + 4.f;
+
+ for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
+ {
+ map<string, string> specializations;
+ ComputeShaderSpec spec;
+
+ specializations["CONTROL"] = cases[caseNdx].param;
+ spec.assembly = shaderTemplate.specialize(specializations);
+ spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
+ spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
+ spec.numWorkGroups = IVec3(numElements, 1, 1);
+
+ group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
+ }
+
+ return group.release();
+}
+
+// Assembly code used for testing selection control is based on GLSL source code:
+// #version 430
+//
+// layout(std140, set = 0, binding = 0) readonly buffer Input {
+// float elements[];
+// } input_data;
+// layout(std140, set = 0, binding = 1) writeonly buffer Output {
+// float elements[];
+// } output_data;
+//
+// void main() {
+// uint x = gl_GlobalInvocationID.x;
+// float val = input_data.elements[x];
+// if (val > 10.f)
+// output_data.elements[x] = val + 1.f;
+// else
+// output_data.elements[x] = val - 1.f;
+// }
+tcu::TestCaseGroup* createSelectionControlGroup (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "selection_control", "Tests selection control cases"));
+ vector<CaseParameter> cases;
+ de::Random rnd (deStringHash(group->getName()));
+ const int numElements = 100;
+ vector<float> inputFloats (numElements, 0);
+ vector<float> outputFloats (numElements, 0);
+ const StringTemplate shaderTemplate (
+ string(s_ShaderPreamble) +
+
+ "OpSource GLSL 430\n"
+ "OpName %main \"main\"\n"
+ "OpName %id \"gl_GlobalInvocationID\"\n"
+
+ "OpDecorate %id BuiltIn GlobalInvocationId\n"
+
+ + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
+
+ "%id = OpVariable %uvec3ptr Input\n"
+ "%zero = OpConstant %i32 0\n"
+ "%constf1 = OpConstant %f32 1.0\n"
+ "%constf10 = OpConstant %f32 10.0\n"
+
+ "%main = OpFunction %void None %voidf\n"
+ "%entry = OpLabel\n"
+ "%idval = OpLoad %uvec3 %id\n"
+ "%x = OpCompositeExtract %u32 %idval 0\n"
+ "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
+ "%inval = OpLoad %f32 %inloc\n"
+ "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
+ "%cmp_gt = OpFOrdGreaterThan %bool %inval %constf10\n"
+
+ " OpSelectionMerge %if_end ${CONTROL}\n"
+ " OpBranchConditional %cmp_gt %if_true %if_false\n"
+ "%if_true = OpLabel\n"
+ "%addf1 = OpFAdd %f32 %inval %constf1\n"
+ " OpStore %outloc %addf1\n"
+ " OpBranch %if_end\n"
+ "%if_false = OpLabel\n"
+ "%subf1 = OpFSub %f32 %inval %constf1\n"
+ " OpStore %outloc %subf1\n"
+ " OpBranch %if_end\n"
+ "%if_end = OpLabel\n"
+ " OpReturn\n"
+ " OpFunctionEnd\n");
+
+ cases.push_back(CaseParameter("none", "None"));
+ cases.push_back(CaseParameter("flatten", "Flatten"));
+ cases.push_back(CaseParameter("dont_flatten", "DontFlatten"));
+ cases.push_back(CaseParameter("flatten_dont_flatten", "DontFlatten|Flatten"));
+
+ fillRandomScalars(rnd, -100.f, 100.f, &inputFloats[0], numElements);
+
+ for (size_t ndx = 0; ndx < numElements; ++ndx)
+ outputFloats[ndx] = inputFloats[ndx] + (inputFloats[ndx] > 10.f ? 1.f : -1.f);
+
+ for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
+ {
+ map<string, string> specializations;
+ ComputeShaderSpec spec;
+
+ specializations["CONTROL"] = cases[caseNdx].param;
+ spec.assembly = shaderTemplate.specialize(specializations);
+ spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
+ spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
+ spec.numWorkGroups = IVec3(numElements, 1, 1);
+
+ group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
+ }
+
+ return group.release();
+}
+
+// Assembly code used for testing function control is based on GLSL source code:
+//
+// #version 430
+//
+// layout(std140, set = 0, binding = 0) readonly buffer Input {
+// float elements[];
+// } input_data;
+// layout(std140, set = 0, binding = 1) writeonly buffer Output {
+// float elements[];
+// } output_data;
+//
+// float const10() { return 10.f; }
+//
+// void main() {
+// uint x = gl_GlobalInvocationID.x;
+// output_data.elements[x] = input_data.elements[x] + const10();
+// }
+tcu::TestCaseGroup* createFunctionControlGroup (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "function_control", "Tests function control cases"));
+ vector<CaseParameter> cases;
+ de::Random rnd (deStringHash(group->getName()));
+ const int numElements = 100;
+ vector<float> inputFloats (numElements, 0);
+ vector<float> outputFloats (numElements, 0);
+ const StringTemplate shaderTemplate (
+ string(s_ShaderPreamble) +
+
+ "OpSource GLSL 430\n"
+ "OpName %main \"main\"\n"
+ "OpName %func_const10 \"const10(\"\n"
+ "OpName %id \"gl_GlobalInvocationID\"\n"
+
+ "OpDecorate %id BuiltIn GlobalInvocationId\n"
+
+ + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
+
+ "%f32f = OpTypeFunction %f32\n"
+ "%id = OpVariable %uvec3ptr Input\n"
+ "%zero = OpConstant %i32 0\n"
+ "%constf10 = OpConstant %f32 10.0\n"
+
+ "%main = OpFunction %void None %voidf\n"
+ "%entry = OpLabel\n"
+ "%idval = OpLoad %uvec3 %id\n"
+ "%x = OpCompositeExtract %u32 %idval 0\n"
+ "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
+ "%inval = OpLoad %f32 %inloc\n"
+ "%ret_10 = OpFunctionCall %f32 %func_const10\n"
+ "%fadd = OpFAdd %f32 %inval %ret_10\n"
+ "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
+ " OpStore %outloc %fadd\n"
+ " OpReturn\n"
+ " OpFunctionEnd\n"
+
+ "%func_const10 = OpFunction %f32 ${CONTROL} %f32f\n"
+ "%label = OpLabel\n"
+ " OpReturnValue %constf10\n"
+ " OpFunctionEnd\n");
+
+ cases.push_back(CaseParameter("none", "None"));
+ cases.push_back(CaseParameter("inline", "Inline"));
+ cases.push_back(CaseParameter("dont_inline", "DontInline"));
+ cases.push_back(CaseParameter("pure", "Pure"));
+ cases.push_back(CaseParameter("const", "Const"));
+ cases.push_back(CaseParameter("inline_pure", "Inline|Pure"));
+ cases.push_back(CaseParameter("const_dont_inline", "Const|DontInline"));
+ cases.push_back(CaseParameter("inline_dont_inline", "Inline|DontInline"));
+ cases.push_back(CaseParameter("pure_inline_dont_inline", "Pure|Inline|DontInline"));
+
+ fillRandomScalars(rnd, -100.f, 100.f, &inputFloats[0], numElements);
+
+ for (size_t ndx = 0; ndx < numElements; ++ndx)
+ outputFloats[ndx] = inputFloats[ndx] + 10.f;
+
+ for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
+ {
+ map<string, string> specializations;
+ ComputeShaderSpec spec;
+
+ specializations["CONTROL"] = cases[caseNdx].param;
+ spec.assembly = shaderTemplate.specialize(specializations);
+ spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
+ spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
+ spec.numWorkGroups = IVec3(numElements, 1, 1);
+
+ group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
+ }
+
+ return group.release();
+}
+
+// Checks that we can get undefined values for various types, without exercising a computation with it.
+tcu::TestCaseGroup* createOpUndefGroup (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opundef", "Tests the OpUndef instruction"));
+ vector<CaseParameter> cases;
+ de::Random rnd (deStringHash(group->getName()));
+ const int numElements = 100;
+ vector<float> positiveFloats (numElements, 0);
+ vector<float> negativeFloats (numElements, 0);
+ const StringTemplate shaderTemplate (
+ string(s_ShaderPreamble) +
+
+ "OpSource GLSL 430\n"
+ "OpName %main \"main\"\n"
+ "OpName %id \"gl_GlobalInvocationID\"\n"
+
+ "OpDecorate %id BuiltIn GlobalInvocationId\n"
+
+ + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
+
+ "${TYPE}\n"
+
+ "%id = OpVariable %uvec3ptr Input\n"
+ "%zero = OpConstant %i32 0\n"
+
+ "%main = OpFunction %void None %voidf\n"
+ "%label = OpLabel\n"
+
+ "%undef = OpUndef %type\n"
+
+ "%idval = OpLoad %uvec3 %id\n"
+ "%x = OpCompositeExtract %u32 %idval 0\n"
+
+ "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
+ "%inval = OpLoad %f32 %inloc\n"
+ "%neg = OpFNegate %f32 %inval\n"
+ "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
+ " OpStore %outloc %neg\n"
+ " OpReturn\n"
+ " OpFunctionEnd\n");
+
+ cases.push_back(CaseParameter("bool", "%type = OpTypeBool"));
+ cases.push_back(CaseParameter("sint32", "%type = OpTypeInt 32 1"));
+ cases.push_back(CaseParameter("uint32", "%type = OpTypeInt 32 0"));
+ cases.push_back(CaseParameter("float32", "%type = OpTypeFloat 32"));
+ cases.push_back(CaseParameter("vec4float32", "%type = OpTypeVector %f32 4"));
+ cases.push_back(CaseParameter("vec2uint32", "%type = OpTypeVector %u32 2"));
+ cases.push_back(CaseParameter("matrix", "%type = OpTypeMatrix %uvec3 3"));
+ cases.push_back(CaseParameter("image", "%type = OpTypeImage %f32 2D 0 0 0 0 Unknown"));
+ cases.push_back(CaseParameter("sampler", "%type = OpTypeSampler"));
+ cases.push_back(CaseParameter("sampledimage", "%img = OpTypeImage %f32 2D 0 0 0 0 Unknown\n"
+ "%type = OpTypeSampledImage %img"));
+ cases.push_back(CaseParameter("array", "%100 = OpConstant %u32 100\n"
+ "%type = OpTypeArray %i32 %100"));
+ cases.push_back(CaseParameter("runtimearray", "%type = OpTypeRuntimeArray %f32"));
+ cases.push_back(CaseParameter("struct", "%type = OpTypeStruct %f32 %i32 %u32"));
+ cases.push_back(CaseParameter("pointer", "%type = OpTypePointer Function %i32"));
+ cases.push_back(CaseParameter("function", "%type = OpTypeFunction %void %i32 %f32"));
+
+ fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
+
+ for (size_t ndx = 0; ndx < numElements; ++ndx)
+ negativeFloats[ndx] = -positiveFloats[ndx];
+
+ for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
+ {
+ map<string, string> specializations;
+ ComputeShaderSpec spec;
+
+ specializations["TYPE"] = cases[caseNdx].param;
+ spec.assembly = shaderTemplate.specialize(specializations);
+ spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
+ spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
+ spec.numWorkGroups = IVec3(numElements, 1, 1);
+
+ group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
+ }
+
+ return group.release();
+}
+
+typedef std::pair<std::string, VkShaderStageFlagBits> EntryToStage;
+typedef map<string, vector<EntryToStage> > ModuleMap;
+
+// Context for a specific test instantiation. For example, an instantiation
+// may test colors yellow/magenta/cyan/mauve in a tesselation shader
+// with an entry point named 'main_to_the_main'
+struct InstanceContext
+{
+ // Map of modules to what entry_points we care to use from those modules.
+ ModuleMap moduleMap;
+ RGBA inputColors[4];
+ RGBA outputColors[4];
+ // Concrete SPIR-V code to test via boilerplate specialization.
+ map<string, string> testCodeFragments;
+
+ InstanceContext (const RGBA (&inputs)[4], const RGBA (&outputs)[4], const map<string, string>& testCodeFragments_)
+ : testCodeFragments (testCodeFragments_)
+ {
+ inputColors[0] = inputs[0];
+ inputColors[1] = inputs[1];
+ inputColors[2] = inputs[2];
+ inputColors[3] = inputs[3];
+
+ outputColors[0] = outputs[0];
+ outputColors[1] = outputs[1];
+ outputColors[2] = outputs[2];
+ outputColors[3] = outputs[3];
+ }
+
+ InstanceContext (const InstanceContext& other)
+ : moduleMap (other.moduleMap)
+ , testCodeFragments (other.testCodeFragments)
+ {
+ inputColors[0] = other.inputColors[0];
+ inputColors[1] = other.inputColors[1];
+ inputColors[2] = other.inputColors[2];
+ inputColors[3] = other.inputColors[3];
+
+ outputColors[0] = other.outputColors[0];
+ outputColors[1] = other.outputColors[1];
+ outputColors[2] = other.outputColors[2];
+ outputColors[3] = other.outputColors[3];
+ }
+};
+
+// A description of a shader to be used for a single stage of the graphics pipeline.
+struct ShaderElement
+{
+ // The module that contains this shader entrypoint.
+ const char* moduleName;
+
+ // The name of the entrypoint.
+ const char* entryName;
+
+ // Which shader stage this entry point represents.
+ VkShaderStageFlagBits stage;
+
+ ShaderElement (const char* moduleName_, const char* entryPoint_, VkShaderStageFlagBits shaderStage_)
+ : moduleName(moduleName_)
+ , entryName(entryPoint_)
+ , stage(shaderStage_)
+ {
+ }
+};
+
+void getDefaultColors (RGBA (&colors)[4])
+{
+ colors[0] = RGBA::white();
+ colors[1] = RGBA::red();
+ colors[2] = RGBA::blue();
+ colors[3] = RGBA::green();
+}
+
+// Turns a statically sized array of ShaderElements into an instance-context
+// by setting up the mapping of modules to their contained shaders and stages.
+// The inputs and expected outputs are given by inputColors and outputColors
+template<size_t N>
+InstanceContext createInstanceContext (const ShaderElement (&elements)[N], const RGBA (&inputColors)[4], const RGBA (&outputColors)[4], const map<string, string>& testCodeFragments)
+{
+ InstanceContext ctx (inputColors, outputColors, testCodeFragments);
+ for (size_t i = 0; i < N; ++i)
+ {
+ ctx.moduleMap[elements[i].moduleName].push_back(std::make_pair(elements[i].entryName, elements[i].stage));
+ }
+ return ctx;
+}
+
+// The same as createInstanceContext above, but with default colors.
+template<size_t N>
+InstanceContext createInstanceContext (const ShaderElement (&elements)[N], const map<string, string>& testCodeFragments)
+{
+ RGBA defaultColors[4];
+ getDefaultColors(defaultColors);
+ return createInstanceContext(elements, defaultColors, defaultColors, testCodeFragments);
+}
+
+// For the current InstanceContext, constructs the required modules and shader stage create infos.
+void createPipelineShaderStages (const DeviceInterface& vk, const VkDevice vkDevice, InstanceContext& instance, Context& context, vector<ModuleHandleSp>& modules, vector<VkPipelineShaderStageCreateInfo>& createInfos)
+{
+ for (ModuleMap::const_iterator moduleNdx = instance.moduleMap.begin(); moduleNdx != instance.moduleMap.end(); ++moduleNdx)
+ {
+ const ModuleHandleSp mod(new Unique<VkShaderModule>(createShaderModule(vk, vkDevice, context.getBinaryCollection().get(moduleNdx->first), 0)));
+
+ modules.push_back(ModuleHandleSp(mod));
+
+ for (vector<EntryToStage>::const_iterator shaderNdx = moduleNdx->second.begin(); shaderNdx != moduleNdx->second.end(); ++shaderNdx)
+ {
+ const EntryToStage& stage = *shaderNdx;
+ const VkPipelineShaderStageCreateInfo shaderParam =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkPipelineShaderStageCreateFlags)0,
+ stage.second, // VkShaderStageFlagBits stage;
+ **modules.back(), // VkShaderModule module;
+ stage.first.c_str(), // const char* pName;
+ (const VkSpecializationInfo*)DE_NULL,
+ };
+
+ createInfos.push_back(shaderParam);
+ }
+ }
+}
+
+#define SPIRV_ASSEMBLY_TYPES \
+ "%void = OpTypeVoid\n" \
+ "%bool = OpTypeBool\n" \
+ \
+ "%i32 = OpTypeInt 32 1\n" \
+ "%u32 = OpTypeInt 32 0\n" \
+ \
+ "%f32 = OpTypeFloat 32\n" \
+ "%v3f32 = OpTypeVector %f32 3\n" \
+ "%v4f32 = OpTypeVector %f32 4\n" \
+ \
+ "%v4f32_function = OpTypeFunction %v4f32 %v4f32\n" \
+ "%fun = OpTypeFunction %void\n" \
+ \
+ "%ip_f32 = OpTypePointer Input %f32\n" \
+ "%ip_i32 = OpTypePointer Input %i32\n" \
+ "%ip_v3f32 = OpTypePointer Input %v3f32\n" \
+ "%ip_v4f32 = OpTypePointer Input %v4f32\n" \
+ \
+ "%op_f32 = OpTypePointer Output %f32\n" \
+ "%op_v4f32 = OpTypePointer Output %v4f32\n"
+
+#define SPIRV_ASSEMBLY_CONSTANTS \
+ "%c_f32_1 = OpConstant %f32 1\n" \
+ "%c_i32_0 = OpConstant %i32 0\n" \
+ "%c_i32_1 = OpConstant %i32 1\n" \
+ "%c_i32_2 = OpConstant %i32 2\n" \
+ "%c_u32_0 = OpConstant %u32 0\n" \
+ "%c_u32_1 = OpConstant %u32 1\n" \
+ "%c_u32_2 = OpConstant %u32 2\n" \
+ "%c_u32_3 = OpConstant %u32 3\n" \
+ "%c_u32_32 = OpConstant %u32 32\n" \
+ "%c_u32_4 = OpConstant %u32 4\n"
+
+#define SPIRV_ASSEMBLY_ARRAYS \
+ "%a1f32 = OpTypeArray %f32 %c_u32_1\n" \
+ "%a2f32 = OpTypeArray %f32 %c_u32_2\n" \
+ "%a3v4f32 = OpTypeArray %v4f32 %c_u32_3\n" \
+ "%a4f32 = OpTypeArray %f32 %c_u32_4\n" \
+ "%a32v4f32 = OpTypeArray %v4f32 %c_u32_32\n" \
+ "%ip_a3v4f32 = OpTypePointer Input %a3v4f32\n" \
+ "%ip_a32v4f32 = OpTypePointer Input %a32v4f32\n" \
+ "%op_a2f32 = OpTypePointer Output %a2f32\n" \
+ "%op_a3v4f32 = OpTypePointer Output %a3v4f32\n" \
+ "%op_a4f32 = OpTypePointer Output %a4f32\n"
+
+// Creates vertex-shader assembly by specializing a boilerplate StringTemplate
+// on fragments, which must (at least) map "testfun" to an OpFunction definition
+// for %test_code that takes and returns a %v4f32. Boilerplate IDs are prefixed
+// with "BP_" to avoid collisions with fragments.
+//
+// It corresponds roughly to this GLSL:
+//;
+// layout(location = 0) in vec4 position;
+// layout(location = 1) in vec4 color;
+// layout(location = 1) out highp vec4 vtxColor;
+// void main (void) { gl_Position = position; vtxColor = test_func(color); }
+string makeVertexShaderAssembly(const map<string, string>& fragments)
+{
+// \todo [2015-11-23 awoloszyn] Remove OpName once these have stabalized
+ static const char vertexShaderBoilerplate[] =
+ "OpCapability Shader\n"
+ "OpMemoryModel Logical GLSL450\n"
+ "OpEntryPoint Vertex %4 \"main\" %BP_Position %BP_vtxColor %BP_color "
+ "%BP_vtxPosition %BP_vertex_id %BP_instance_id\n"
+ "${debug:opt}\n"
+ "OpName %main \"main\"\n"
+ "OpName %BP_vtxPosition \"vtxPosition\"\n"
+ "OpName %BP_Position \"position\"\n"
+ "OpName %BP_vtxColor \"vtxColor\"\n"
+ "OpName %BP_color \"color\"\n"
+ "OpName %vertex_id \"gl_VertexID\"\n"
+ "OpName %instance_id \"gl_InstanceID\"\n"
+ "OpName %test_code \"testfun(vf4;\"\n"
+ "OpDecorate %BP_vtxPosition Location 2\n"
+ "OpDecorate %BP_Position Location 0\n"
+ "OpDecorate %BP_vtxColor Location 1\n"
+ "OpDecorate %BP_color Location 1\n"
+ "OpDecorate %BP_vertex_id BuiltIn VertexId\n"
+ "OpDecorate %BP_instance_id BuiltIn InstanceId\n"
+ SPIRV_ASSEMBLY_TYPES
+ SPIRV_ASSEMBLY_CONSTANTS
+ SPIRV_ASSEMBLY_ARRAYS
+ "%BP_vtxPosition = OpVariable %op_v4f32 Output\n"
+ "%BP_Position = OpVariable %ip_v4f32 Input\n"
+ "%BP_vtxColor = OpVariable %op_v4f32 Output\n"
+ "%BP_color = OpVariable %ip_v4f32 Input\n"
+ "%BP_vertex_id = OpVariable %ip_i32 Input\n"
+ "%BP_instance_id = OpVariable %ip_i32 Input\n"
+ "%main = OpFunction %void None %fun\n"
+ "%BP_label = OpLabel\n"
+ "%BP_tmp_position = OpLoad %v4f32 %BP_Position\n"
+ "OpStore %BP_vtxPosition %BP_tmp_position\n"
+ "%BP_tmp_color = OpLoad %v4f32 %BP_color\n"
+ "%BP_clr_transformed = OpFunctionCall %v4f32 %test_code %BP_tmp_color\n"
+ "OpStore %BP_vtxColor %BP_clr_transformed\n"
+ "OpReturn\n"
+ "OpFunctionEnd\n"
+ "${testfun}\n";
+ return tcu::StringTemplate(vertexShaderBoilerplate).specialize(fragments);
+}
+
+// Creates tess-control-shader assembly by specializing a boilerplate
+// StringTemplate on fragments, which must (at least) map "testfun" to an
+// OpFunction definition for %test_code that takes and returns a %v4f32.
+// Boilerplate IDs are prefixed with "BP_" to avoid collisions with fragments.
+//
+// It roughly corresponds to the following GLSL.
+//
+// #version 450
+// layout(vertices = 3) out;
+// layout(location = 1) in vec4 in_color[];
+// layout(location = 2) in vec4 in_position[];
+// layout(location = 1) out vec4 out_color[];
+// layout(location = 2) out vec4 out_position[];
+//
+// void main() {
+// out_color[gl_InvocationID] = testfun(in_color[gl_InvocationID]);
+// out_position[gl_InvocationID] = in_position[gl_InvocationID];
+// if (gl_InvocationID == 0) {
+// gl_TessLevelOuter[0] = 1.0;
+// gl_TessLevelOuter[1] = 1.0;
+// gl_TessLevelOuter[2] = 1.0;
+// gl_TessLevelInner[0] = 1.0;
+// }
+// }
+string makeTessControlShaderAssembly (const map<string, string>& fragments)
+{
+ static const char tessControlShaderBoilerplate[] =
+ "OpCapability Tessellation\n"
+ "OpMemoryModel Logical GLSL450\n"
+ "OpEntryPoint TessellationControl %BP_main \"main\" %BP_out_color %BP_gl_InvocationID %BP_in_color %BP_out_position %BP_in_position %BP_gl_TessLevelOuter %BP_gl_TessLevelInner\n"
+ "OpExecutionMode %BP_main OutputVertices 3\n"
+ "${debug:opt}\n"
+ "OpName %BP_main \"main\"\n"
+ "OpName %BP_out_color \"out_color\"\n"
+ "OpName %BP_gl_InvocationID \"gl_InvocationID\"\n"
+ "OpName %BP_in_color \"in_color\"\n"
+ "OpName %BP_out_position \"out_position\"\n"
+ "OpName %BP_in_position \"in_position\"\n"
+ "OpName %BP_gl_TessLevelOuter \"gl_TessLevelOuter\"\n"
+ "OpName %BP_gl_TessLevelInner \"gl_TessLevelInner\"\n"
+ "OpName %test_code \"testfun(vf4;\"\n"
+ "OpDecorate %BP_out_color Location 1\n"
+ "OpDecorate %BP_gl_InvocationID BuiltIn InvocationId\n"
+ "OpDecorate %BP_in_color Location 1\n"
+ "OpDecorate %BP_out_position Location 2\n"
+ "OpDecorate %BP_in_position Location 2\n"
+ "OpDecorate %BP_gl_TessLevelOuter Patch\n"
+ "OpDecorate %BP_gl_TessLevelOuter BuiltIn TessLevelOuter\n"
+ "OpDecorate %BP_gl_TessLevelInner Patch\n"
+ "OpDecorate %BP_gl_TessLevelInner BuiltIn TessLevelInner\n"
+ SPIRV_ASSEMBLY_TYPES
+ SPIRV_ASSEMBLY_CONSTANTS
+ SPIRV_ASSEMBLY_ARRAYS
+ "%BP_out_color = OpVariable %op_a3v4f32 Output\n"
+ "%BP_gl_InvocationID = OpVariable %ip_i32 Input\n"
+ "%BP_in_color = OpVariable %ip_a32v4f32 Input\n"
+ "%BP_out_position = OpVariable %op_a3v4f32 Output\n"
+ "%BP_in_position = OpVariable %ip_a32v4f32 Input\n"
+ "%BP_gl_TessLevelOuter = OpVariable %op_a4f32 Output\n"
+ "%BP_gl_TessLevelInner = OpVariable %op_a2f32 Output\n"
+
+ "%BP_main = OpFunction %void None %fun\n"
+ "%BP_label = OpLabel\n"
+
+ "%BP_invocation_id = OpLoad %i32 %BP_gl_InvocationID\n"
+
+ "%BP_in_color_ptr = OpAccessChain %ip_v4f32 %BP_in_color %BP_invocation_id\n"
+ "%BP_in_position_ptr = OpAccessChain %ip_v4f32 %BP_in_position %BP_invocation_id\n"
+
+ "%BP_in_color_val = OpLoad %v4f32 %BP_in_color_ptr\n"
+ "%BP_in_position_val = OpLoad %v4f32 %BP_in_position_ptr\n"
+
+ "%BP_clr_transformed = OpFunctionCall %v4f32 %test_code %BP_in_color_val\n"
+
+ "%BP_out_color_ptr = OpAccessChain %op_v4f32 %BP_out_color %BP_invocation_id\n"
+ "%BP_out_position_ptr = OpAccessChain %op_v4f32 %BP_out_position %BP_invocation_id\n"
+
+ "OpStore %BP_out_color_ptr %BP_clr_transformed\n"
+ "OpStore %BP_out_position_ptr %BP_in_position_val\n"
+
+ "%BP_is_first_invocation = OpIEqual %bool %BP_invocation_id %c_i32_0\n"
+ "OpSelectionMerge %BP_merge_label None\n"
+ "OpBranchConditional %BP_is_first_invocation %BP_first_invocation %BP_merge_label\n"
+
+ "%BP_first_invocation = OpLabel\n"
+ "%BP_tess_outer_0 = OpAccessChain %op_f32 %BP_gl_TessLevelOuter %c_i32_0\n"
+ "%BP_tess_outer_1 = OpAccessChain %op_f32 %BP_gl_TessLevelOuter %c_i32_1\n"
+ "%BP_tess_outer_2 = OpAccessChain %op_f32 %BP_gl_TessLevelOuter %c_i32_2\n"
+ "%BP_tess_inner = OpAccessChain %op_f32 %BP_gl_TessLevelInner %c_i32_0\n"
+
+ "OpStore %BP_tess_outer_0 %c_f32_1\n"
+ "OpStore %BP_tess_outer_1 %c_f32_1\n"
+ "OpStore %BP_tess_outer_2 %c_f32_1\n"
+ "OpStore %BP_tess_inner %c_f32_1\n"
+
+ "OpBranch %BP_merge_label\n"
+ "%BP_merge_label = OpLabel\n"
+ "OpReturn\n"
+ "OpFunctionEnd\n"
+ "${testfun}\n";
+ return tcu::StringTemplate(tessControlShaderBoilerplate).specialize(fragments);
+}
+
+// Creates tess-evaluation-shader assembly by specializing a boilerplate
+// StringTemplate on fragments, which must (at least) map "testfun" to an
+// OpFunction definition for %test_code that takes and returns a %v4f32.
+// Boilerplate IDs are prefixed with "BP_" to avoid collisions with fragments.
+//
+// It roughly corresponds to the following glsl.
+//
+// #version 450
+//
+// layout(triangles, equal_spacing, ccw) in;
+// layout(location = 1) in vec4 in_color[];
+// layout(location = 2) in vec4 in_position[];
+// layout(location = 1) out vec4 out_color;
+//
+// #define interpolate(val)
+// vec4(gl_TessCoord.x) * val[0] + vec4(gl_TessCoord.y) * val[1] +
+// vec4(gl_TessCoord.z) * val[2]
+//
+// void main() {
+// gl_Position = vec4(gl_TessCoord.x) * in_position[0] +
+// vec4(gl_TessCoord.y) * in_position[1] +
+// vec4(gl_TessCoord.z) * in_position[2];
+// out_color = testfun(interpolate(in_color));
+// }
+string makeTessEvalShaderAssembly(const map<string, string>& fragments)
+{
+ static const char tessEvalBoilerplate[] =
+ "OpCapability Tessellation\n"
+ "OpMemoryModel Logical GLSL450\n"
+ "OpEntryPoint TessellationEvaluation %BP_main \"main\" %BP_stream %BP_gl_tessCoord %BP_in_position %BP_out_color %BP_in_color \n"
+ "OpExecutionMode %BP_main Triangles\n"
+ "${debug:opt}\n"
+ "OpName %BP_main \"main\"\n"
+ "OpName %BP_per_vertex_out \"gl_PerVertex\"\n"
+ "OpMemberName %BP_per_vertex_out 0 \"gl_Position\"\n"
+ "OpMemberName %BP_per_vertex_out 1 \"gl_PointSize\"\n"
+ "OpMemberName %BP_per_vertex_out 2 \"gl_ClipDistance\"\n"
+ "OpMemberName %BP_per_vertex_out 3 \"gl_CullDistance\"\n"
+ "OpName %BP_stream \"\"\n"
+ "OpName %BP_gl_tessCoord \"gl_TessCoord\"\n"
+ "OpName %BP_in_position \"in_position\"\n"
+ "OpName %BP_out_color \"out_color\"\n"
+ "OpName %BP_in_color \"in_color\"\n"
+ "OpName %test_code \"testfun(vf4;\"\n"
+ "OpMemberDecorate %BP_per_vertex_out 0 BuiltIn Position\n"
+ "OpMemberDecorate %BP_per_vertex_out 1 BuiltIn PointSize\n"
+ "OpMemberDecorate %BP_per_vertex_out 2 BuiltIn ClipDistance\n"
+ "OpMemberDecorate %BP_per_vertex_out 3 BuiltIn CullDistance\n"
+ "OpDecorate %BP_per_vertex_out Block\n"
+ "OpDecorate %BP_gl_tessCoord BuiltIn TessCoord\n"
+ "OpDecorate %BP_in_position Location 2\n"
+ "OpDecorate %BP_out_color Location 1\n"
+ "OpDecorate %BP_in_color Location 1\n"
+ SPIRV_ASSEMBLY_TYPES
+ SPIRV_ASSEMBLY_CONSTANTS
+ SPIRV_ASSEMBLY_ARRAYS
+ "%BP_per_vertex_out = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
+ "%BP_op_per_vertex_out = OpTypePointer Output %BP_per_vertex_out\n"
+ "%BP_stream = OpVariable %BP_op_per_vertex_out Output\n"
+ "%BP_gl_tessCoord = OpVariable %ip_v3f32 Input\n"
+ "%BP_in_position = OpVariable %ip_a32v4f32 Input\n"
+ "%BP_out_color = OpVariable %op_v4f32 Output\n"
+ "%BP_in_color = OpVariable %ip_a32v4f32 Input\n"
+ "%BP_main = OpFunction %void None %fun\n"
+ "%BP_label = OpLabel\n"
+ "%BP_tc_0_ptr = OpAccessChain %ip_f32 %BP_gl_tessCoord %c_u32_0\n"
+ "%BP_tc_1_ptr = OpAccessChain %ip_f32 %BP_gl_tessCoord %c_u32_1\n"
+ "%BP_tc_2_ptr = OpAccessChain %ip_f32 %BP_gl_tessCoord %c_u32_2\n"
+
+ "%BP_tc_0 = OpLoad %f32 %BP_tc_0_ptr\n"
+ "%BP_tc_1 = OpLoad %f32 %BP_tc_1_ptr\n"
+ "%BP_tc_2 = OpLoad %f32 %BP_tc_2_ptr\n"
+
+ "%BP_in_pos_0_ptr = OpAccessChain %ip_v4f32 %BP_in_position %c_i32_0\n"
+ "%BP_in_pos_1_ptr = OpAccessChain %ip_v4f32 %BP_in_position %c_i32_1\n"
+ "%BP_in_pos_2_ptr = OpAccessChain %ip_v4f32 %BP_in_position %c_i32_2\n"
+
+ "%BP_in_pos_0 = OpLoad %v4f32 %BP_in_pos_0_ptr\n"
+ "%BP_in_pos_1 = OpLoad %v4f32 %BP_in_pos_1_ptr\n"
+ "%BP_in_pos_2 = OpLoad %v4f32 %BP_in_pos_2_ptr\n"
+
+ "%BP_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %BP_tc_0 %BP_in_pos_0\n"
+ "%BP_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %BP_tc_1 %BP_in_pos_1\n"
+ "%BP_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %BP_tc_2 %BP_in_pos_2\n"
+
+ "%BP_out_pos_ptr = OpAccessChain %op_v4f32 %BP_stream %c_i32_0\n"
+
+ "%BP_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %BP_in_pos_0_weighted %BP_in_pos_1_weighted\n"
+ "%BP_computed_out = OpFAdd %v4f32 %BP_in_pos_0_plus_pos_1 %BP_in_pos_2_weighted\n"
+ "OpStore %BP_out_pos_ptr %BP_computed_out\n"
+
+ "%BP_in_clr_0_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_0\n"
+ "%BP_in_clr_1_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_1\n"
+ "%BP_in_clr_2_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_2\n"
+
+ "%BP_in_clr_0 = OpLoad %v4f32 %BP_in_clr_0_ptr\n"
+ "%BP_in_clr_1 = OpLoad %v4f32 %BP_in_clr_1_ptr\n"
+ "%BP_in_clr_2 = OpLoad %v4f32 %BP_in_clr_2_ptr\n"
+
+ "%BP_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %BP_tc_0 %BP_in_clr_0\n"
+ "%BP_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %BP_tc_1 %BP_in_clr_1\n"
+ "%BP_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %BP_tc_2 %BP_in_clr_2\n"
+
+ "%BP_in_clr_0_plus_col_1 = OpFAdd %v4f32 %BP_in_clr_0_weighted %BP_in_clr_1_weighted\n"
+ "%BP_computed_clr = OpFAdd %v4f32 %BP_in_clr_0_plus_col_1 %BP_in_clr_2_weighted\n"
+ "%BP_clr_transformed = OpFunctionCall %v4f32 %test_code %BP_computed_clr\n"
+
+ "OpStore %BP_out_color %BP_clr_transformed\n"
+ "OpReturn\n"
+ "OpFunctionEnd\n"
+ "${testfun}\n";
+ return tcu::StringTemplate(tessEvalBoilerplate).specialize(fragments);
+}
+
+// Creates geometry-shader assembly by specializing a boilerplate StringTemplate
+// on fragments, which must (at least) map "testfun" to an OpFunction definition
+// for %test_code that takes and returns a %v4f32. Boilerplate IDs are prefixed
+// with "BP_" to avoid collisions with fragments.
+//
+// Derived from this GLSL:
+//
+// #version 450
+// layout(triangles) in;
+// layout(triangle_strip, max_vertices = 3) out;
+//
+// layout(location = 1) in vec4 in_color[];
+// layout(location = 1) out vec4 out_color;
+//
+// void main() {
+// gl_Position = gl_in[0].gl_Position;
+// out_color = test_fun(in_color[0]);
+// EmitVertex();
+// gl_Position = gl_in[1].gl_Position;
+// out_color = test_fun(in_color[1]);
+// EmitVertex();
+// gl_Position = gl_in[2].gl_Position;
+// out_color = test_fun(in_color[2]);
+// EmitVertex();
+// EndPrimitive();
+// }
+string makeGeometryShaderAssembly(const map<string, string>& fragments)
+{
+ static const char geometryShaderBoilerplate[] =
+ "OpCapability Geometry\n"
+ "OpMemoryModel Logical GLSL450\n"
+ "OpEntryPoint Geometry %BP_main \"main\" %BP_out_gl_position %BP_gl_in %BP_out_color %BP_in_color\n"
+ "OpExecutionMode %BP_main Triangles\n"
+ "OpExecutionMode %BP_main Invocations 0\n"
+ "OpExecutionMode %BP_main OutputTriangleStrip\n"
+ "OpExecutionMode %BP_main OutputVertices 3\n"
+ "${debug:opt}\n"
+ "OpName %BP_main \"main\"\n"
+ "OpName %BP_per_vertex_in \"gl_PerVertex\"\n"
+ "OpMemberName %BP_per_vertex_in 0 \"gl_Position\"\n"
+ "OpMemberName %BP_per_vertex_in 1 \"gl_PointSize\"\n"
+ "OpMemberName %BP_per_vertex_in 2 \"gl_ClipDistance\"\n"
+ "OpMemberName %BP_per_vertex_in 3 \"gl_CullDistance\"\n"
+ "OpName %BP_gl_in \"gl_in\"\n"
+ "OpName %BP_out_color \"out_color\"\n"
+ "OpName %BP_in_color \"in_color\"\n"
+ "OpName %test_code \"testfun(vf4;\"\n"
+ "OpDecorate %BP_out_gl_position BuiltIn Position\n"
+ "OpMemberDecorate %BP_per_vertex_in 0 BuiltIn Position\n"
+ "OpMemberDecorate %BP_per_vertex_in 1 BuiltIn PointSize\n"
+ "OpMemberDecorate %BP_per_vertex_in 2 BuiltIn ClipDistance\n"
+ "OpMemberDecorate %BP_per_vertex_in 3 BuiltIn CullDistance\n"
+ "OpDecorate %BP_per_vertex_in Block\n"
+ "OpDecorate %BP_out_color Location 1\n"
+ "OpDecorate %BP_out_color Stream 0\n"
+ "OpDecorate %BP_in_color Location 1\n"
+ SPIRV_ASSEMBLY_TYPES
+ SPIRV_ASSEMBLY_CONSTANTS
+ SPIRV_ASSEMBLY_ARRAYS
+ "%BP_per_vertex_in = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
+ "%BP_a3_per_vertex_in = OpTypeArray %BP_per_vertex_in %c_u32_3\n"
+ "%BP_ip_a3_per_vertex_in = OpTypePointer Input %BP_a3_per_vertex_in\n"
+
+ "%BP_gl_in = OpVariable %BP_ip_a3_per_vertex_in Input\n"
+ "%BP_out_color = OpVariable %op_v4f32 Output\n"
+ "%BP_in_color = OpVariable %ip_a3v4f32 Input\n"
+ "%BP_out_gl_position = OpVariable %op_v4f32 Output\n"
+
+ "%BP_main = OpFunction %void None %fun\n"
+ "%BP_label = OpLabel\n"
+ "%BP_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_0 %c_i32_0\n"
+ "%BP_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_1 %c_i32_0\n"
+ "%BP_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_2 %c_i32_0\n"
+
+ "%BP_in_position_0 = OpLoad %v4f32 %BP_gl_in_0_gl_position\n"
+ "%BP_in_position_1 = OpLoad %v4f32 %BP_gl_in_1_gl_position\n"
+ "%BP_in_position_2 = OpLoad %v4f32 %BP_gl_in_2_gl_position \n"
+
+ "%BP_in_color_0_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_0\n"
+ "%BP_in_color_1_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_1\n"
+ "%BP_in_color_2_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_2\n"
+
+ "%BP_in_color_0 = OpLoad %v4f32 %BP_in_color_0_ptr\n"
+ "%BP_in_color_1 = OpLoad %v4f32 %BP_in_color_1_ptr\n"
+ "%BP_in_color_2 = OpLoad %v4f32 %BP_in_color_2_ptr\n"
+
+ "%BP_transformed_in_color_0 = OpFunctionCall %v4f32 %test_code %BP_in_color_0\n"
+ "%BP_transformed_in_color_1 = OpFunctionCall %v4f32 %test_code %BP_in_color_1\n"
+ "%BP_transformed_in_color_2 = OpFunctionCall %v4f32 %test_code %BP_in_color_2\n"
+
+ "OpStore %BP_out_gl_position %BP_in_position_0\n"
+ "OpStore %BP_out_color %BP_transformed_in_color_0\n"
+ "OpEmitVertex\n"
+
+ "OpStore %BP_out_gl_position %BP_in_position_1\n"
+ "OpStore %BP_out_color %BP_transformed_in_color_1\n"
+ "OpEmitVertex\n"
+
+ "OpStore %BP_out_gl_position %BP_in_position_2\n"
+ "OpStore %BP_out_color %BP_transformed_in_color_2\n"
+ "OpEmitVertex\n"
+
+ "OpEndPrimitive\n"
+ "OpReturn\n"
+ "OpFunctionEnd\n"
+ "${testfun}\n";
+ return tcu::StringTemplate(geometryShaderBoilerplate).specialize(fragments);
+}
+
+// Creates fragment-shader assembly by specializing a boilerplate StringTemplate
+// on fragments, which must (at least) map "testfun" to an OpFunction definition
+// for %test_code that takes and returns a %v4f32. Boilerplate IDs are prefixed
+// with "BP_" to avoid collisions with fragments.
+//
+// Derived from this GLSL:
+//
+// layout(location = 1) in highp vec4 vtxColor;
+// layout(location = 0) out highp vec4 fragColor;
+// highp vec4 testfun(highp vec4 x) { return x; }
+// void main(void) { fragColor = testfun(vtxColor); }
+//
+// with modifications including passing vtxColor by value and ripping out
+// testfun() definition.
+string makeFragmentShaderAssembly(const map<string, string>& fragments)
+{
+ static const char fragmentShaderBoilerplate[] =
+ "OpCapability Shader\n"
+ "OpMemoryModel Logical GLSL450\n"
+ "OpEntryPoint Fragment %BP_main \"main\" %BP_vtxColor %BP_fragColor\n"
+ "OpExecutionMode %BP_main OriginUpperLeft\n"
+ "${debug:opt}\n"
+ "OpName %BP_main \"main\"\n"
+ "OpName %BP_fragColor \"fragColor\"\n"
+ "OpName %BP_vtxColor \"vtxColor\"\n"
+ "OpName %test_code \"testfun(vf4;\"\n"
+ "OpDecorate %BP_fragColor Location 0\n"
+ "OpDecorate %BP_vtxColor Location 1\n"
+ SPIRV_ASSEMBLY_TYPES
+ SPIRV_ASSEMBLY_CONSTANTS
+ SPIRV_ASSEMBLY_ARRAYS
+ "%BP_fragColor = OpVariable %op_v4f32 Output\n"
+ "%BP_vtxColor = OpVariable %ip_v4f32 Input\n"
+ "%BP_main = OpFunction %void None %fun\n"
+ "%BP_label_main = OpLabel\n"
+ "%BP_tmp1 = OpLoad %v4f32 %BP_vtxColor\n"
+ "%BP_tmp2 = OpFunctionCall %v4f32 %test_code %BP_tmp1\n"
+ "OpStore %BP_fragColor %BP_tmp2\n"
+ "OpReturn\n"
+ "OpFunctionEnd\n"
+ "${testfun}\n";
+ return tcu::StringTemplate(fragmentShaderBoilerplate).specialize(fragments);
+}
+
+// Creates fragments that specialize into a simple pass-through shader (of any kind).
+map<string, string> passthruFragments(void)
+{
+ map<string, string> fragments;
+ fragments["testfun"] =
+ // A %test_code function that returns its argument unchanged.
+ "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+ "%param1 = OpFunctionParameter %v4f32\n"
+ "%label_testfun = OpLabel\n"
+ "OpReturnValue %param1\n"
+ "OpFunctionEnd\n";
+ return fragments;
+}
+
+// Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
+// Vertex shader gets custom code from context, the rest are pass-through.
+void addShaderCodeCustomVertex(vk::SourceCollections& dst, InstanceContext context) {
+ map<string, string> passthru = passthruFragments();
+ dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(context.testCodeFragments);
+ dst.spirvAsmSources.add("tessc") << makeTessControlShaderAssembly(passthru);
+ dst.spirvAsmSources.add("tesse") << makeTessEvalShaderAssembly(passthru);
+ dst.spirvAsmSources.add("geom") << makeGeometryShaderAssembly(passthru);
+ dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(passthru);
+}
+
+// Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
+// Tessellation control shader gets custom code from context, the rest are
+// pass-through.
+void addShaderCodeCustomTessControl(vk::SourceCollections& dst, InstanceContext context) {
+ map<string, string> passthru = passthruFragments();
+ dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(passthru);
+ dst.spirvAsmSources.add("tessc") << makeTessControlShaderAssembly(context.testCodeFragments);
+ dst.spirvAsmSources.add("tesse") << makeTessEvalShaderAssembly(passthru);
+ dst.spirvAsmSources.add("geom") << makeGeometryShaderAssembly(passthru);
+ dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(passthru);
+}
+
+// Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
+// Tessellation evaluation shader gets custom code from context, the rest are
+// pass-through.
+void addShaderCodeCustomTessEval(vk::SourceCollections& dst, InstanceContext context) {
+ map<string, string> passthru = passthruFragments();
+ dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(passthru);
+ dst.spirvAsmSources.add("tessc") << makeTessControlShaderAssembly(passthru);
+ dst.spirvAsmSources.add("tesse") << makeTessEvalShaderAssembly(context.testCodeFragments);
+ dst.spirvAsmSources.add("geom") << makeGeometryShaderAssembly(passthru);
+ dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(passthru);
+}
+
+// Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
+// Geometry shader gets custom code from context, the rest are pass-through.
+void addShaderCodeCustomGeometry(vk::SourceCollections& dst, InstanceContext context) {
+ map<string, string> passthru = passthruFragments();
+ dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(passthru);
+ dst.spirvAsmSources.add("tessc") << makeTessControlShaderAssembly(passthru);
+ dst.spirvAsmSources.add("tesse") << makeTessEvalShaderAssembly(passthru);
+ dst.spirvAsmSources.add("geom") << makeGeometryShaderAssembly(context.testCodeFragments);
+ dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(passthru);
+}
+
+// Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
+// Fragment shader gets custom code from context, the rest are pass-through.
+void addShaderCodeCustomFragment(vk::SourceCollections& dst, InstanceContext context) {
+ map<string, string> passthru = passthruFragments();
+ dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(passthru);
+ dst.spirvAsmSources.add("tessc") << makeTessControlShaderAssembly(passthru);
+ dst.spirvAsmSources.add("tesse") << makeTessEvalShaderAssembly(passthru);
+ dst.spirvAsmSources.add("geom") << makeGeometryShaderAssembly(passthru);
+ dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(context.testCodeFragments);
+}
+
+// Sets up and runs a Vulkan pipeline, then spot-checks the resulting image.
+// Feeds the pipeline a set of colored triangles, which then must occur in the
+// rendered image. The surface is cleared before executing the pipeline, so
+// whatever the shaders draw can be directly spot-checked.
+TestStatus runAndVerifyDefaultPipeline (Context& context, InstanceContext instance)
+{
+ const VkDevice vkDevice = context.getDevice();
+ const DeviceInterface& vk = context.getDeviceInterface();
+ const VkQueue queue = context.getUniversalQueue();
+ const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
+ const tcu::IVec2 renderSize (256, 256);
+ vector<ModuleHandleSp> modules;
+ map<VkShaderStageFlagBits, VkShaderModule> moduleByStage;
+ const int testSpecificSeed = 31354125;
+ const int seed = context.getTestContext().getCommandLine().getBaseSeed() ^ testSpecificSeed;
+ de::Random(seed).shuffle(instance.inputColors, instance.inputColors+4);
+ de::Random(seed).shuffle(instance.outputColors, instance.outputColors+4);
+ const Vec4 vertexData[] =
+ {
+ // Upper left corner:
+ Vec4(-1.0f, -1.0f, 0.0f, 1.0f), instance.inputColors[0].toVec(),
+ Vec4(-0.5f, -1.0f, 0.0f, 1.0f), instance.inputColors[0].toVec(),
+ Vec4(-1.0f, -0.5f, 0.0f, 1.0f), instance.inputColors[0].toVec(),
+
+ // Upper right corner:
+ Vec4(+0.5f, -1.0f, 0.0f, 1.0f), instance.inputColors[1].toVec(),
+ Vec4(+1.0f, -1.0f, 0.0f, 1.0f), instance.inputColors[1].toVec(),
+ Vec4(+1.0f, -0.5f, 0.0f, 1.0f), instance.inputColors[1].toVec(),
+
+ // Lower left corner:
+ Vec4(-1.0f, +0.5f, 0.0f, 1.0f), instance.inputColors[2].toVec(),
+ Vec4(-0.5f, +1.0f, 0.0f, 1.0f), instance.inputColors[2].toVec(),
+ Vec4(-1.0f, +1.0f, 0.0f, 1.0f), instance.inputColors[2].toVec(),
+
+ // Lower right corner:
+ Vec4(+1.0f, +0.5f, 0.0f, 1.0f), instance.inputColors[3].toVec(),
+ Vec4(+1.0f, +1.0f, 0.0f, 1.0f), instance.inputColors[3].toVec(),
+ Vec4(+0.5f, +1.0f, 0.0f, 1.0f), instance.inputColors[3].toVec()
+ };
+ const size_t singleVertexDataSize = 2 * sizeof(Vec4);
+ const size_t vertexCount = sizeof(vertexData) / singleVertexDataSize;
+
+ const VkBufferCreateInfo vertexBufferParams =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkBufferCreateFlags flags;
+ (VkDeviceSize)sizeof(vertexData), // VkDeviceSize size;
+ VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
+ VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
+ 1u, // deUint32 queueFamilyCount;
+ &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
+ };
+ const Unique<VkBuffer> vertexBuffer (createBuffer(vk, vkDevice, &vertexBufferParams));
+ const UniquePtr<Allocation> vertexBufferMemory (context.getDefaultAllocator().allocate(getBufferMemoryRequirements(vk, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible));
+
+ VK_CHECK(vk.bindBufferMemory(vkDevice, *vertexBuffer, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset()));
+
+ const VkDeviceSize imageSizeBytes = (VkDeviceSize)(sizeof(deUint32)*renderSize.x()*renderSize.y());
+ const VkBufferCreateInfo readImageBufferParams =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkBufferCreateFlags flags;
+ imageSizeBytes, // VkDeviceSize size;
+ VK_BUFFER_USAGE_TRANSFER_DST_BIT, // VkBufferUsageFlags usage;
+ VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
+ 1u, // deUint32 queueFamilyCount;
+ &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
+ };
+ const Unique<VkBuffer> readImageBuffer (createBuffer(vk, vkDevice, &readImageBufferParams));
+ const UniquePtr<Allocation> readImageBufferMemory (context.getDefaultAllocator().allocate(getBufferMemoryRequirements(vk, vkDevice, *readImageBuffer), MemoryRequirement::HostVisible));
+
+ VK_CHECK(vk.bindBufferMemory(vkDevice, *readImageBuffer, readImageBufferMemory->getMemory(), readImageBufferMemory->getOffset()));
+
+ const VkImageCreateInfo imageParams =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkImageCreateFlags flags;
+ VK_IMAGE_TYPE_2D, // VkImageType imageType;
+ VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format;
+ { renderSize.x(), renderSize.y(), 1 }, // VkExtent3D extent;
+ 1u, // deUint32 mipLevels;
+ 1u, // deUint32 arraySize;
+ VK_SAMPLE_COUNT_1_BIT, // deUint32 samples;
+ VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
+ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
+ VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
+ 1u, // deUint32 queueFamilyCount;
+ &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
+ VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
+ };
+
+ const Unique<VkImage> image (createImage(vk, vkDevice, &imageParams));
+ const UniquePtr<Allocation> imageMemory (context.getDefaultAllocator().allocate(getImageMemoryRequirements(vk, vkDevice, *image), MemoryRequirement::Any));
+
+ VK_CHECK(vk.bindImageMemory(vkDevice, *image, imageMemory->getMemory(), imageMemory->getOffset()));
+
+ const VkAttachmentDescription colorAttDesc =
+ {
+ 0u, // VkAttachmentDescriptionFlags flags;
+ VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format;
+ VK_SAMPLE_COUNT_1_BIT, // deUint32 samples;
+ VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
+ VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
+ VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
+ VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout;
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
+ };
+ const VkAttachmentReference colorAttRef =
+ {
+ 0u, // deUint32 attachment;
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout;
+ };
+ const VkSubpassDescription subpassDesc =
+ {
+ 0u, // VkSubpassDescriptionFlags flags;
+ VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
+ 0u, // deUint32 inputCount;
+ DE_NULL, // const VkAttachmentReference* pInputAttachments;
+ 1u, // deUint32 colorCount;
+ &colorAttRef, // const VkAttachmentReference* pColorAttachments;
+ DE_NULL, // const VkAttachmentReference* pResolveAttachments;
+ DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
+ 0u, // deUint32 preserveCount;
+ DE_NULL, // const VkAttachmentReference* pPreserveAttachments;
+ };
+ const VkRenderPassCreateInfo renderPassParams =
+ {
+ VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkRenderPassCreateFlags)0,
+ 1u, // deUint32 attachmentCount;
+ &colorAttDesc, // const VkAttachmentDescription* pAttachments;
+ 1u, // deUint32 subpassCount;
+ &subpassDesc, // const VkSubpassDescription* pSubpasses;
+ 0u, // deUint32 dependencyCount;
+ DE_NULL, // const VkSubpassDependency* pDependencies;
+ };
+ const Unique<VkRenderPass> renderPass (createRenderPass(vk, vkDevice, &renderPassParams));
+
+ const VkImageViewCreateInfo colorAttViewParams =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkImageViewCreateFlags flags;
+ *image, // VkImage image;
+ VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
+ VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format;
+ {
+ VK_COMPONENT_SWIZZLE_R,
+ VK_COMPONENT_SWIZZLE_G,
+ VK_COMPONENT_SWIZZLE_B,
+ VK_COMPONENT_SWIZZLE_A
+ }, // VkChannelMapping channels;
+ {
+ VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
+ 0u, // deUint32 baseMipLevel;
+ 1u, // deUint32 mipLevels;
+ 0u, // deUint32 baseArrayLayer;
+ 1u, // deUint32 arraySize;
+ }, // VkImageSubresourceRange subresourceRange;
+ };
+ const Unique<VkImageView> colorAttView (createImageView(vk, vkDevice, &colorAttViewParams));
+
+ // Pipeline layout
+ const VkPipelineLayoutCreateInfo pipelineLayoutParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkPipelineLayoutCreateFlags)0,
+ 0u, // deUint32 descriptorSetCount;
+ DE_NULL, // const VkDescriptorSetLayout* pSetLayouts;
+ 0u, // deUint32 pushConstantRangeCount;
+ DE_NULL, // const VkPushConstantRange* pPushConstantRanges;
+ };
+ const Unique<VkPipelineLayout> pipelineLayout (createPipelineLayout(vk, vkDevice, &pipelineLayoutParams));
+
+ // Pipeline
+ vector<VkPipelineShaderStageCreateInfo> shaderStageParams;
+
+ createPipelineShaderStages(vk, vkDevice, instance, context, modules, shaderStageParams);
+
+ const VkPipelineDepthStencilStateCreateInfo depthStencilParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkPipelineDepthStencilStateCreateFlags)0,
+ DE_FALSE, // deUint32 depthTestEnable;
+ DE_FALSE, // deUint32 depthWriteEnable;
+ VK_COMPARE_OP_ALWAYS, // VkCompareOp depthCompareOp;
+ DE_FALSE, // deUint32 depthBoundsTestEnable;
+ DE_FALSE, // deUint32 stencilTestEnable;
+ {
+ VK_STENCIL_OP_KEEP, // VkStencilOp stencilFailOp;
+ VK_STENCIL_OP_KEEP, // VkStencilOp stencilPassOp;
+ VK_STENCIL_OP_KEEP, // VkStencilOp stencilDepthFailOp;
+ VK_COMPARE_OP_ALWAYS, // VkCompareOp stencilCompareOp;
+ 0u, // deUint32 stencilCompareMask;
+ 0u, // deUint32 stencilWriteMask;
+ 0u, // deUint32 stencilReference;
+ }, // VkStencilOpState front;
+ {
+ VK_STENCIL_OP_KEEP, // VkStencilOp stencilFailOp;
+ VK_STENCIL_OP_KEEP, // VkStencilOp stencilPassOp;
+ VK_STENCIL_OP_KEEP, // VkStencilOp stencilDepthFailOp;
+ VK_COMPARE_OP_ALWAYS, // VkCompareOp stencilCompareOp;
+ 0u, // deUint32 stencilCompareMask;
+ 0u, // deUint32 stencilWriteMask;
+ 0u, // deUint32 stencilReference;
+ }, // VkStencilOpState back;
+ -1.0f, // float minDepthBounds;
+ +1.0f, // float maxDepthBounds;
+ };
+ const VkViewport viewport0 =
+ {
+ 0.0f, // float originX;
+ 0.0f, // float originY;
+ (float)renderSize.x(), // float width;
+ (float)renderSize.y(), // float height;
+ 0.0f, // float minDepth;
+ 1.0f, // float maxDepth;
+ };
+ const VkRect2D scissor0 =
+ {
+ {
+ 0u, // deInt32 x;
+ 0u, // deInt32 y;
+ }, // VkOffset2D offset;
+ {
+ renderSize.x(), // deInt32 width;
+ renderSize.y(), // deInt32 height;
+ }, // VkExtent2D extent;
+ };
+ const VkPipelineViewportStateCreateInfo viewportParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkPipelineViewportStateCreateFlags)0,
+ 1u, // deUint32 viewportCount;
+ &viewport0,
+ 1u,
+ &scissor0
+ };
+ const VkSampleMask sampleMask = ~0u;
+ const VkPipelineMultisampleStateCreateInfo multisampleParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkPipelineMultisampleStateCreateFlags)0,
+ VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterSamples;
+ DE_FALSE, // deUint32 sampleShadingEnable;
+ 0.0f, // float minSampleShading;
+ &sampleMask, // const VkSampleMask* pSampleMask;
+ DE_FALSE, // VkBool32 alphaToCoverageEnable;
+ DE_FALSE, // VkBool32 alphaToOneEnable;
+ };
+ const VkPipelineRasterizationStateCreateInfo rasterParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkPipelineRasterizationStateCreateFlags)0,
+ DE_TRUE, // deUint32 depthClipEnable;
+ DE_FALSE, // deUint32 rasterizerDiscardEnable;
+ VK_POLYGON_MODE_FILL, // VkFillMode fillMode;
+ VK_CULL_MODE_NONE, // VkCullMode cullMode;
+ VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
+ VK_FALSE, // VkBool32 depthBiasEnable;
+ 0.0f, // float depthBias;
+ 0.0f, // float depthBiasClamp;
+ 0.0f, // float slopeScaledDepthBias;
+ 1.0f, // float lineWidth;
+ };
+ const VkPipelineInputAssemblyStateCreateInfo inputAssemblyParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkPipelineInputAssemblyStateCreateFlags)0,
+ VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, // VkPrimitiveTopology topology;
+ DE_FALSE, // deUint32 primitiveRestartEnable;
+ };
+ const VkVertexInputBindingDescription vertexBinding0 =
+ {
+ 0u, // deUint32 binding;
+ deUint32(singleVertexDataSize), // deUint32 strideInBytes;
+ VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate stepRate;
+ };
+ const VkVertexInputAttributeDescription vertexAttrib0[2] =
+ {
+ {
+ 0u, // deUint32 location;
+ 0u, // deUint32 binding;
+ VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
+ 0u // deUint32 offsetInBytes;
+ },
+ {
+ 1u, // deUint32 location;
+ 0u, // deUint32 binding;
+ VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
+ sizeof(Vec4), // deUint32 offsetInBytes;
+ }
+ };
+
+ const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkPipelineVertexInputStateCreateFlags)0,
+ 1u, // deUint32 bindingCount;
+ &vertexBinding0, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
+ 2u, // deUint32 attributeCount;
+ vertexAttrib0, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
+ };
+ const VkPipelineColorBlendAttachmentState attBlendParams =
+ {
+ DE_FALSE, // deUint32 blendEnable;
+ VK_BLEND_FACTOR_ONE, // VkBlend srcBlendColor;
+ VK_BLEND_FACTOR_ZERO, // VkBlend destBlendColor;
+ VK_BLEND_OP_ADD, // VkBlendOp blendOpColor;
+ VK_BLEND_FACTOR_ONE, // VkBlend srcBlendAlpha;
+ VK_BLEND_FACTOR_ZERO, // VkBlend destBlendAlpha;
+ VK_BLEND_OP_ADD, // VkBlendOp blendOpAlpha;
+ (VK_COLOR_COMPONENT_R_BIT|
+ VK_COLOR_COMPONENT_G_BIT|
+ VK_COLOR_COMPONENT_B_BIT|
+ VK_COLOR_COMPONENT_A_BIT), // VkChannelFlags channelWriteMask;
+ };
+ const VkPipelineColorBlendStateCreateInfo blendParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkPipelineColorBlendStateCreateFlags)0,
+ DE_FALSE, // VkBool32 logicOpEnable;
+ VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
+ 1u, // deUint32 attachmentCount;
+ &attBlendParams, // const VkPipelineColorBlendAttachmentState* pAttachments;
+ { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConst[4];
+ };
+ const VkPipelineDynamicStateCreateInfo dynamicStateInfo =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkPipelineDynamicStateCreateFlags)0,
+ 0u, // deUint32 dynamicStateCount;
+ DE_NULL // const VkDynamicState* pDynamicStates;
+ };
+
+ const VkPipelineTessellationStateCreateInfo tessellationState =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,
+ DE_NULL,
+ (VkPipelineTesselationStateCreateFlags)0,
+ 3u
+ };
+
+ const VkGraphicsPipelineCreateInfo pipelineParams =
+ {
+ VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPipelineCreateFlags flags;
+ (deUint32)shaderStageParams.size(), // deUint32 stageCount;
+ &shaderStageParams[0], // const VkPipelineShaderStageCreateInfo* pStages;
+ &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
+ &inputAssemblyParams, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
+ &tessellationState, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
+ &viewportParams, // const VkPipelineViewportStateCreateInfo* pViewportState;
+ &rasterParams, // const VkPipelineRasterStateCreateInfo* pRasterState;
+ &multisampleParams, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
+ &depthStencilParams, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
+ &blendParams, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
+ &dynamicStateInfo, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
+ *pipelineLayout, // VkPipelineLayout layout;
+ *renderPass, // VkRenderPass renderPass;
+ 0u, // deUint32 subpass;
+ DE_NULL, // VkPipeline basePipelineHandle;
+ 0u, // deInt32 basePipelineIndex;
+ };
+
+ const Unique<VkPipeline> pipeline (createGraphicsPipeline(vk, vkDevice, DE_NULL, &pipelineParams));
+
+ // Framebuffer
+ const VkFramebufferCreateInfo framebufferParams =
+ {
+ VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkFramebufferCreateFlags)0,
+ *renderPass, // VkRenderPass renderPass;
+ 1u, // deUint32 attachmentCount;
+ &*colorAttView, // const VkImageView* pAttachments;
+ (deUint32)renderSize.x(), // deUint32 width;
+ (deUint32)renderSize.y(), // deUint32 height;
+ 1u, // deUint32 layers;
+ };
+ const Unique<VkFramebuffer> framebuffer (createFramebuffer(vk, vkDevice, &framebufferParams));
+
+ const VkCommandPoolCreateInfo cmdPoolParams =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCmdPoolCreateFlags flags;
+ queueFamilyIndex, // deUint32 queueFamilyIndex;
+ };
+ const Unique<VkCommandPool> cmdPool (createCommandPool(vk, vkDevice, &cmdPoolParams));
+
+ // Command buffer
+ const VkCommandBufferAllocateInfo cmdBufParams =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ *cmdPool, // VkCmdPool pool;
+ VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCmdBufferLevel level;
+ 1u, // deUint32 count;
+ };
+ const Unique<VkCommandBuffer> cmdBuf (allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
+
+ const VkCommandBufferBeginInfo cmdBufBeginParams =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ (VkCommandBufferUsageFlags)0,
+ DE_NULL, // VkRenderPass renderPass;
+ 0u, // deUint32 subpass;
+ DE_NULL, // VkFramebuffer framebuffer;
+ VK_FALSE, // VkBool32 occlusionQueryEnable;
+ (VkQueryControlFlags)0,
+ (VkQueryPipelineStatisticFlags)0,
+ };
+
+ // Record commands
+ VK_CHECK(vk.beginCommandBuffer(*cmdBuf, &cmdBufBeginParams));
+
+ {
+ const VkMemoryBarrier vertFlushBarrier =
+ {
+ VK_STRUCTURE_TYPE_MEMORY_BARRIER, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ VK_ACCESS_HOST_WRITE_BIT, // VkMemoryOutputFlags outputMask;
+ VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, // VkMemoryInputFlags inputMask;
+ };
+ const VkImageMemoryBarrier colorAttBarrier =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkMemoryOutputFlags outputMask;
+ VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkMemoryInputFlags inputMask;
+ VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
+ queueFamilyIndex, // deUint32 srcQueueFamilyIndex;
+ queueFamilyIndex, // deUint32 destQueueFamilyIndex;
+ *image, // VkImage image;
+ {
+ VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspect aspect;
+ 0u, // deUint32 baseMipLevel;
+ 1u, // deUint32 mipLevels;
+ 0u, // deUint32 baseArraySlice;
+ 1u, // deUint32 arraySize;
+ } // VkImageSubresourceRange subresourceRange;
+ };
+ const void* barriers[] = { &vertFlushBarrier, &colorAttBarrier };
+ vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, DE_FALSE, (deUint32)DE_LENGTH_OF_ARRAY(barriers), barriers);
+ }
+
+ {
+ const VkClearValue clearValue = makeClearValueColorF32(0.125f, 0.25f, 0.75f, 1.0f);
+ const VkRenderPassBeginInfo passBeginParams =
+ {
+ VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ *renderPass, // VkRenderPass renderPass;
+ *framebuffer, // VkFramebuffer framebuffer;
+ { { 0, 0 }, { renderSize.x(), renderSize.y() } }, // VkRect2D renderArea;
+ 1u, // deUint32 clearValueCount;
+ &clearValue, // const VkClearValue* pClearValues;
+ };
+ vk.cmdBeginRenderPass(*cmdBuf, &passBeginParams, VK_SUBPASS_CONTENTS_INLINE);
+ }
+
+ vk.cmdBindPipeline(*cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
+ {
+ const VkDeviceSize bindingOffset = 0;
+ vk.cmdBindVertexBuffers(*cmdBuf, 0u, 1u, &vertexBuffer.get(), &bindingOffset);
+ }
+ vk.cmdDraw(*cmdBuf, deUint32(vertexCount), 1u /*run pipeline once*/, 0u /*first vertex*/, 0u /*first instanceIndex*/);
+ vk.cmdEndRenderPass(*cmdBuf);
+
+ {
+ const VkImageMemoryBarrier renderFinishBarrier =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkMemoryOutputFlags outputMask;
+ VK_ACCESS_TRANSFER_READ_BIT, // VkMemoryInputFlags inputMask;
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout;
+ queueFamilyIndex, // deUint32 srcQueueFamilyIndex;
+ queueFamilyIndex, // deUint32 destQueueFamilyIndex;
+ *image, // VkImage image;
+ {
+ VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
+ 0u, // deUint32 baseMipLevel;
+ 1u, // deUint32 mipLevels;
+ 0u, // deUint32 baseArraySlice;
+ 1u, // deUint32 arraySize;
+ } // VkImageSubresourceRange subresourceRange;
+ };
+ const void* barriers[] = { &renderFinishBarrier };
+ vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, DE_FALSE, (deUint32)DE_LENGTH_OF_ARRAY(barriers), barriers);
+ }
+
+ {
+ const VkBufferImageCopy copyParams =
+ {
+ (VkDeviceSize)0u, // VkDeviceSize bufferOffset;
+ (deUint32)renderSize.x(), // deUint32 bufferRowLength;
+ (deUint32)renderSize.y(), // deUint32 bufferImageHeight;
+ {
+ VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspect aspect;
+ 0u, // deUint32 mipLevel;
+ 0u, // deUint32 arrayLayer;
+ 1u, // deUint32 arraySize;
+ }, // VkImageSubresourceCopy imageSubresource;
+ { 0u, 0u, 0u }, // VkOffset3D imageOffset;
+ { renderSize.x(), renderSize.y(), 1u } // VkExtent3D imageExtent;
+ };
+ vk.cmdCopyImageToBuffer(*cmdBuf, *image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *readImageBuffer, 1u, ©Params);
+ }
+
+ {
+ const VkBufferMemoryBarrier copyFinishBarrier =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ VK_ACCESS_TRANSFER_WRITE_BIT, // VkMemoryOutputFlags outputMask;
+ VK_ACCESS_HOST_READ_BIT, // VkMemoryInputFlags inputMask;
+ queueFamilyIndex, // deUint32 srcQueueFamilyIndex;
+ queueFamilyIndex, // deUint32 destQueueFamilyIndex;
+ *readImageBuffer, // VkBuffer buffer;
+ 0u, // VkDeviceSize offset;
+ imageSizeBytes // VkDeviceSize size;
+ };
+ const void* barriers[] = { ©FinishBarrier };
+ vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, DE_FALSE, (deUint32)DE_LENGTH_OF_ARRAY(barriers), barriers);
+ }
+
+ VK_CHECK(vk.endCommandBuffer(*cmdBuf));
+
+ // Upload vertex data
+ {
+ const VkMappedMemoryRange range =
+ {
+ VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ vertexBufferMemory->getMemory(), // VkDeviceMemory mem;
+ 0, // VkDeviceSize offset;
+ (VkDeviceSize)sizeof(vertexData), // VkDeviceSize size;
+ };
+ void* vertexBufPtr = vertexBufferMemory->getHostPtr();
+
+ deMemcpy(vertexBufPtr, &vertexData[0], sizeof(vertexData));
+ VK_CHECK(vk.flushMappedMemoryRanges(vkDevice, 1u, &range));
+ }
+
+ // Submit & wait for completion
+ {
+ const VkFenceCreateInfo fenceParams =
+ {
+ VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkFenceCreateFlags flags;
+ };
+ const Unique<VkFence> fence (createFence(vk, vkDevice, &fenceParams));
+ const VkSubmitInfo submitInfo =
+ {
+ VK_STRUCTURE_TYPE_SUBMIT_INFO,
+ DE_NULL,
+ 0u,
+ (const VkSemaphore*)DE_NULL,
+ 1u,
+ &cmdBuf.get(),
+ 0u,
+ (const VkSemaphore*)DE_NULL,
+ };
+
+ VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence));
+ VK_CHECK(vk.waitForFences(vkDevice, 1u, &fence.get(), DE_TRUE, ~0ull));
+ }
+
+ const void* imagePtr = readImageBufferMemory->getHostPtr();
+ const tcu::ConstPixelBufferAccess pixelBuffer(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8),
+ renderSize.x(), renderSize.y(), 1, imagePtr);
+ // Log image
+ {
+ const VkMappedMemoryRange range =
+ {
+ VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ readImageBufferMemory->getMemory(), // VkDeviceMemory mem;
+ 0, // VkDeviceSize offset;
+ imageSizeBytes, // VkDeviceSize size;
+ };
+
+ VK_CHECK(vk.invalidateMappedMemoryRanges(vkDevice, 1u, &range));
+ context.getTestContext().getLog() << TestLog::Image("Result", "Result", pixelBuffer);
+ }
+
+ const RGBA threshold(1, 1, 1, 1);
+ const RGBA upperLeft(pixelBuffer.getPixel(1, 1));
+ if (!tcu::compareThreshold(upperLeft, instance.outputColors[0], threshold))
+ return TestStatus::fail("Upper left corner mismatch");
+
+ const RGBA upperRight(pixelBuffer.getPixel(pixelBuffer.getWidth() - 1, 1));
+ if (!tcu::compareThreshold(upperRight, instance.outputColors[1], threshold))
+ return TestStatus::fail("Upper right corner mismatch");
+
+ const RGBA lowerLeft(pixelBuffer.getPixel(1, pixelBuffer.getHeight() - 1));
+ if (!tcu::compareThreshold(lowerLeft, instance.outputColors[2], threshold))
+ return TestStatus::fail("Lower left corner mismatch");
+
+ const RGBA lowerRight(pixelBuffer.getPixel(pixelBuffer.getWidth() - 1, pixelBuffer.getHeight() - 1));
+ if (!tcu::compareThreshold(lowerRight, instance.outputColors[3], threshold))
+ return TestStatus::fail("Lower right corner mismatch");
+
+ return TestStatus::pass("Rendered output matches input");
+}
+
+void createTestsForAllStages(const std::string& name,
+ const RGBA (&inputColors)[4],
+ const RGBA (&outputColors)[4],
+ const map<string, string>& testCodeFragments,
+ tcu::TestCaseGroup* tests)
+{
+ const ShaderElement pipelineStages[] =
+ {
+ ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT),
+ ShaderElement("tessc", "main", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT),
+ ShaderElement("tesse", "main", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT),
+ ShaderElement("geom", "main", VK_SHADER_STAGE_GEOMETRY_BIT),
+ ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT),
+ };
+
+ addFunctionCaseWithPrograms<InstanceContext>(tests, name + "-vert", "", addShaderCodeCustomVertex, runAndVerifyDefaultPipeline,
+ createInstanceContext(pipelineStages, inputColors, outputColors, testCodeFragments));
+
+ addFunctionCaseWithPrograms<InstanceContext>(tests, name + "-tessc", "", addShaderCodeCustomTessControl, runAndVerifyDefaultPipeline,
+ createInstanceContext(pipelineStages, inputColors, outputColors, testCodeFragments));
+
+ addFunctionCaseWithPrograms<InstanceContext>(tests, name + "-tesse", "", addShaderCodeCustomTessEval, runAndVerifyDefaultPipeline,
+ createInstanceContext(pipelineStages, inputColors, outputColors, testCodeFragments));
+
+ addFunctionCaseWithPrograms<InstanceContext>(tests, name + "-geom", "", addShaderCodeCustomGeometry, runAndVerifyDefaultPipeline,
+ createInstanceContext(pipelineStages, inputColors, outputColors, testCodeFragments));
+
+ addFunctionCaseWithPrograms<InstanceContext>(tests, name + "-frag", "", addShaderCodeCustomFragment, runAndVerifyDefaultPipeline,
+ createInstanceContext(pipelineStages, inputColors, outputColors, testCodeFragments));
+}
+} // anonymous
+
+tcu::TestCaseGroup* createInstructionTests (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> instructionTests (new tcu::TestCaseGroup(testCtx, "instruction", "Instructions with special opcodes/operands"));
+
+ instructionTests->addChild(createOpNopGroup(testCtx));
+ instructionTests->addChild(createOpLineGroup(testCtx));
+ instructionTests->addChild(createOpNoLineGroup(testCtx));
+ instructionTests->addChild(createOpConstantNullGroup(testCtx));
+ instructionTests->addChild(createOpConstantCompositeGroup(testCtx));
+ instructionTests->addChild(createOpConstantUsageGroup(testCtx));
+ instructionTests->addChild(createOpSourceGroup(testCtx));
+ instructionTests->addChild(createOpSourceExtensionGroup(testCtx));
+ instructionTests->addChild(createDecorationGroupGroup(testCtx));
+ instructionTests->addChild(createOpPhiGroup(testCtx));
+ instructionTests->addChild(createLoopControlGroup(testCtx));
+ instructionTests->addChild(createFunctionControlGroup(testCtx));
+ instructionTests->addChild(createSelectionControlGroup(testCtx));
+ instructionTests->addChild(createBlockOrderGroup(testCtx));
+ instructionTests->addChild(createOpUndefGroup(testCtx));
+ instructionTests->addChild(createOpUnreachableGroup(testCtx));
+
+ RGBA defaultColors[4];
+ getDefaultColors(defaultColors);
+ de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "graphics-assembly", "Test the graphics pipeline"));
+ createTestsForAllStages("passthru", defaultColors, defaultColors, passthruFragments(), group.get());
+ instructionTests->addChild(group.release());
+ return instructionTests.release();
+}
+
+} // SpirVAssembly
+} // vkt
--- /dev/null
+#ifndef _VKTSPVASMINSTRUCTIONTESTS_HPP
+#define _VKTSPVASMINSTRUCTIONTESTS_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief SPIR-V Assembly Tests for Instructions (special opcode/operand)
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+namespace SpirVAssembly
+{
+
+tcu::TestCaseGroup* createInstructionTests (tcu::TestContext& testCtx);
+
+} // SpirVAssembly
+} // vkt
+
+#endif // _VKTSPVASMINSTRUCTIONTESTS_HPP
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief SPIR-V Assembly Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktSpvAsmTests.hpp"
+
+#include "deUniquePtr.hpp"
+
+#include "vktSpvAsmInstructionTests.hpp"
+
+namespace vkt
+{
+namespace SpirVAssembly
+{
+
+tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> spirVAssemblyTests (new tcu::TestCaseGroup(testCtx, "spirv_assembly", "SPIR-V Assembly tests"));
+
+ spirVAssemblyTests->addChild(createInstructionTests(testCtx));
+ // \todo [2015-09-28 antiagainst] control flow
+ // \todo [2015-09-28 antiagainst] multiple entry points for the same shader stage
+ // \todo [2015-09-28 antiagainst] multiple shaders in the same module
+
+ return spirVAssemblyTests.release();
+}
+
+} // SpirVAssembly
+} // vkt
--- /dev/null
+#ifndef _VKTSPVASMTESTS_HPP
+#define _VKTSPVASMTESTS_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief SPIR-V Assembly Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+namespace SpirVAssembly
+{
+
+tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx);
+
+} // SpirVAssembly
+} // vkt
+
+#endif // _VKTSPVASMTESTS_HPP
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Utility for pre-compiling source programs to SPIR-V
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuCommandLine.hpp"
+#include "tcuPlatform.hpp"
+#include "tcuResource.hpp"
+#include "tcuTestLog.hpp"
+#include "tcuTestHierarchyIterator.hpp"
+#include "deUniquePtr.hpp"
+#include "vkPrograms.hpp"
+#include "vkBinaryRegistry.hpp"
+#include "vktTestCase.hpp"
+#include "vktTestPackage.hpp"
+#include "deUniquePtr.hpp"
+#include "deCommandLine.hpp"
+
+#include <iostream>
+
+using std::vector;
+using std::string;
+using de::UniquePtr;
+using de::MovePtr;
+
+namespace vkt
+{
+
+tcu::TestPackageRoot* createRoot (tcu::TestContext& testCtx)
+{
+ vector<tcu::TestNode*> children;
+ children.push_back(new TestPackage(testCtx));
+ return new tcu::TestPackageRoot(testCtx, children);
+}
+
+enum BuildMode
+{
+ BUILDMODE_BUILD = 0,
+ BUILDMODE_VERIFY,
+
+ BUILDMODE_LAST
+};
+
+struct BuildStats
+{
+ int numSucceeded;
+ int numFailed;
+
+ BuildStats (void)
+ : numSucceeded (0)
+ , numFailed (0)
+ {
+ }
+};
+
+namespace // anonymous
+{
+
+vk::ProgramBinary* compileProgram (const glu::ProgramSources& source, glu::ShaderProgramInfo* buildInfo)
+{
+ return vk::buildProgram(source, vk::PROGRAM_FORMAT_SPIRV, buildInfo);
+}
+
+vk::ProgramBinary* compileProgram (const vk::SpirVAsmSource& source, vk::SpirVProgramInfo* buildInfo)
+{
+ return vk::assembleProgram(source, buildInfo);
+}
+
+void writeVerboseLogs (const glu::ShaderProgramInfo& buildInfo)
+{
+ for (size_t shaderNdx = 0; shaderNdx < buildInfo.shaders.size(); shaderNdx++)
+ {
+ const glu::ShaderInfo& shaderInfo = buildInfo.shaders[shaderNdx];
+ const char* const shaderName = getShaderTypeName(shaderInfo.type);
+
+ tcu::print("%s source:\n---\n%s\n---\n", shaderName, shaderInfo.source.c_str());
+ tcu::print("%s compile log:\n---\n%s\n---\n", shaderName, shaderInfo.infoLog.c_str());
+ }
+}
+
+void writeVerboseLogs (const vk::SpirVProgramInfo& buildInfo)
+{
+ tcu::print("source:\n---\n%s\n---\n", buildInfo.source->program.str().c_str());
+ tcu::print("compile log:\n---\n%s\n---\n", buildInfo.infoLog.c_str());
+}
+
+template <typename InfoType, typename IteratorType>
+void buildProgram (const std::string& casePath,
+ bool printLogs,
+ IteratorType iter,
+ BuildMode mode,
+ BuildStats* stats,
+ vk::BinaryRegistryReader* reader,
+ vk::BinaryRegistryWriter* writer)
+{
+ InfoType buildInfo;
+ try
+ {
+ const vk::ProgramIdentifier progId (casePath, iter.getName());
+ const UniquePtr<vk::ProgramBinary> binary (compileProgram(iter.getProgram(), &buildInfo));
+
+ if (mode == BUILDMODE_BUILD)
+ writer->storeProgram(progId, *binary);
+ else
+ {
+ DE_ASSERT(mode == BUILDMODE_VERIFY);
+
+ const UniquePtr<vk::ProgramBinary> storedBinary (reader->loadProgram(progId));
+
+ if (binary->getSize() != storedBinary->getSize())
+ throw tcu::Exception("Binary size doesn't match");
+
+ if (deMemCmp(binary->getBinary(), storedBinary->getBinary(), binary->getSize()))
+ throw tcu::Exception("Binary contents don't match");
+ }
+
+ tcu::print(" OK: %s\n", iter.getName().c_str());
+ stats->numSucceeded += 1;
+ }
+ catch (const std::exception& e)
+ {
+ tcu::print(" ERROR: %s: %s\n", iter.getName().c_str(), e.what());
+ if (printLogs)
+ {
+ writeVerboseLogs(buildInfo);
+ }
+ stats->numFailed += 1;
+ }
+}
+
+} // anonymous
+BuildStats buildPrograms (tcu::TestContext& testCtx, const std::string& dstPath, BuildMode mode, bool verbose)
+{
+ const UniquePtr<tcu::TestPackageRoot> root (createRoot(testCtx));
+ tcu::DefaultHierarchyInflater inflater (testCtx);
+ tcu::TestHierarchyIterator iterator (*root, inflater, testCtx.getCommandLine());
+ const tcu::DirArchive srcArchive (dstPath.c_str());
+ UniquePtr<vk::BinaryRegistryWriter> writer (mode == BUILDMODE_BUILD ? new vk::BinaryRegistryWriter(dstPath) : DE_NULL);
+ UniquePtr<vk::BinaryRegistryReader> reader (mode == BUILDMODE_VERIFY ? new vk::BinaryRegistryReader(srcArchive, "") : DE_NULL);
+ BuildStats stats;
+ const bool printLogs = verbose;
+
+ while (iterator.getState() != tcu::TestHierarchyIterator::STATE_FINISHED)
+ {
+ if (iterator.getState() == tcu::TestHierarchyIterator::STATE_ENTER_NODE &&
+ tcu::isTestNodeTypeExecutable(iterator.getNode()->getNodeType()))
+ {
+ const TestCase* const testCase = dynamic_cast<TestCase*>(iterator.getNode());
+ const string casePath = iterator.getNodePath();
+ vk::SourceCollections progs;
+
+ tcu::print("%s\n", casePath.c_str());
+
+ testCase->initPrograms(progs);
+
+ for (vk::GlslSourceCollection::Iterator progIter = progs.glslSources.begin(); progIter != progs.glslSources.end(); ++progIter)
+ {
+ buildProgram<glu::ShaderProgramInfo, vk::GlslSourceCollection::Iterator>(casePath, printLogs, progIter, mode, &stats, reader.get(), writer.get());
+ }
+
+ for (vk::SpirVAsmCollection::Iterator progIter = progs.spirvAsmSources.begin(); progIter != progs.spirvAsmSources.end(); ++progIter)
+ {
+ buildProgram<vk::SpirVProgramInfo, vk::SpirVAsmCollection::Iterator>(casePath, printLogs, progIter, mode, &stats, reader.get(), writer.get());
+ }
+ }
+
+ iterator.next();
+ }
+
+ if (mode == BUILDMODE_BUILD)
+ writer->writeIndex();
+
+ return stats;
+}
+
+} // vkt
+
+namespace opt
+{
+
+DE_DECLARE_COMMAND_LINE_OPT(DstPath, std::string);
+DE_DECLARE_COMMAND_LINE_OPT(Mode, vkt::BuildMode);
+DE_DECLARE_COMMAND_LINE_OPT(Verbose, bool);
+DE_DECLARE_COMMAND_LINE_OPT(Cases, std::string);
+
+} // opt
+
+void registerOptions (de::cmdline::Parser& parser)
+{
+ using de::cmdline::Option;
+ using de::cmdline::NamedValue;
+
+ static const NamedValue<vkt::BuildMode> s_modes[] =
+ {
+ { "build", vkt::BUILDMODE_BUILD },
+ { "verify", vkt::BUILDMODE_VERIFY }
+ };
+
+ parser << Option<opt::DstPath> ("d", "dst-path", "Destination path", "out")
+ << Option<opt::Mode> ("m", "mode", "Build mode", s_modes, "build")
+ << Option<opt::Verbose> ("v", "verbose", "Verbose output")
+ << Option<opt::Cases> ("n", "deqp-case", "Case path filter (works as in test binaries)");
+}
+
+int main (int argc, const char* argv[])
+{
+ de::cmdline::CommandLine cmdLine;
+ tcu::CommandLine deqpCmdLine;
+
+ {
+ de::cmdline::Parser parser;
+ registerOptions(parser);
+ if (!parser.parse(argc, argv, &cmdLine, std::cerr))
+ {
+ parser.help(std::cout);
+ return -1;
+ }
+ }
+
+ {
+ vector<const char*> deqpArgv;
+
+ deqpArgv.push_back("unused");
+
+ if (cmdLine.hasOption<opt::Cases>())
+ {
+ deqpArgv.push_back("--deqp-case");
+ deqpArgv.push_back(cmdLine.getOption<opt::Cases>().c_str());
+ }
+
+ if (!deqpCmdLine.parse((int)deqpArgv.size(), &deqpArgv[0]))
+ return -1;
+ }
+
+ try
+ {
+ tcu::DirArchive archive (".");
+ tcu::TestLog log (deqpCmdLine.getLogFileName(), deqpCmdLine.getLogFlags());
+ tcu::Platform platform;
+ tcu::TestContext testCtx (platform, archive, log, deqpCmdLine, DE_NULL);
+
+ const vkt::BuildStats stats = vkt::buildPrograms(testCtx,
+ cmdLine.getOption<opt::DstPath>(),
+ cmdLine.getOption<opt::Mode>(),
+ cmdLine.getOption<opt::Verbose>());
+
+ tcu::print("DONE: %d passed, %d failed\n", stats.numSucceeded, stats.numFailed);
+
+ return stats.numFailed == 0 ? 0 : -1;
+ }
+ catch (const std::exception& e)
+ {
+ tcu::die("%s", e.what());
+ }
+}
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Platform information tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktInfo.hpp"
+
+#include "vktTestCaseUtil.hpp"
+
+#include "vkPlatform.hpp"
+#include "vkStrUtil.hpp"
+#include "vkRef.hpp"
+#include "vkDeviceUtil.hpp"
+#include "vkQueryUtil.hpp"
+
+#include "tcuTestLog.hpp"
+#include "tcuFormatUtil.hpp"
+
+#include "deUniquePtr.hpp"
+#include "deMemory.h"
+
+namespace vkt
+{
+namespace
+{
+
+using namespace vk;
+using std::vector;
+using std::string;
+using tcu::TestLog;
+using tcu::ScopedLogSection;
+
+tcu::TestStatus enumeratePhysicalDevices (Context& context)
+{
+ TestLog& log = context.getTestContext().getLog();
+ const vector<VkPhysicalDevice> devices = enumeratePhysicalDevices(context.getInstanceInterface(), context.getInstance());
+
+ log << TestLog::Integer("NumDevices", "Number of devices", "", QP_KEY_TAG_NONE, deInt64(devices.size()));
+
+ for (size_t ndx = 0; ndx < devices.size(); ndx++)
+ log << TestLog::Message << ndx << ": " << devices[ndx] << TestLog::EndMessage;
+
+ return tcu::TestStatus::pass("Enumerating devices succeeded");
+}
+
+tcu::TestStatus enumerateInstanceLayers (Context& context)
+{
+ TestLog& log = context.getTestContext().getLog();
+ const vector<VkLayerProperties> properties = enumerateInstanceLayerProperties(context.getPlatformInterface());
+
+ for (size_t ndx = 0; ndx < properties.size(); ndx++)
+ log << TestLog::Message << ndx << ": " << properties[ndx] << TestLog::EndMessage;
+
+ return tcu::TestStatus::pass("Enumerating layers succeeded");
+}
+
+tcu::TestStatus enumerateInstanceExtensions (Context& context)
+{
+ TestLog& log = context.getTestContext().getLog();
+
+ {
+ const ScopedLogSection section (log, "Global", "Global Extensions");
+ const vector<VkExtensionProperties> properties = enumerateInstanceExtensionProperties(context.getPlatformInterface(), DE_NULL);
+
+ for (size_t ndx = 0; ndx < properties.size(); ndx++)
+ log << TestLog::Message << ndx << ": " << properties[ndx] << TestLog::EndMessage;
+ }
+
+ {
+ const vector<VkLayerProperties> layers = enumerateInstanceLayerProperties(context.getPlatformInterface());
+
+ for (vector<VkLayerProperties>::const_iterator layer = layers.begin(); layer != layers.end(); ++layer)
+ {
+ const ScopedLogSection section (log, layer->layerName, string("Layer: ") + layer->layerName);
+ const vector<VkExtensionProperties> properties = enumerateInstanceExtensionProperties(context.getPlatformInterface(), layer->layerName);
+
+ for (size_t extNdx = 0; extNdx < properties.size(); extNdx++)
+ log << TestLog::Message << extNdx << ": " << properties[extNdx] << TestLog::EndMessage;
+ }
+ }
+
+ return tcu::TestStatus::pass("Enumerating extensions succeeded");
+}
+
+tcu::TestStatus enumerateDeviceLayers (Context& context)
+{
+ TestLog& log = context.getTestContext().getLog();
+ const vector<VkLayerProperties> properties = vk::enumerateDeviceLayerProperties(context.getInstanceInterface(), context.getPhysicalDevice());
+
+ for (size_t ndx = 0; ndx < properties.size(); ndx++)
+ log << TestLog::Message << ndx << ": " << properties[ndx] << TestLog::EndMessage;
+
+ return tcu::TestStatus::pass("Enumerating layers succeeded");
+}
+
+tcu::TestStatus enumerateDeviceExtensions (Context& context)
+{
+ TestLog& log = context.getTestContext().getLog();
+
+ {
+ const ScopedLogSection section (log, "Global", "Global Extensions");
+ const vector<VkExtensionProperties> properties = enumerateDeviceExtensionProperties(context.getInstanceInterface(), context.getPhysicalDevice(), DE_NULL);
+
+ for (size_t ndx = 0; ndx < properties.size(); ndx++)
+ log << TestLog::Message << ndx << ": " << properties[ndx] << TestLog::EndMessage;
+ }
+
+ {
+ const vector<VkLayerProperties> layers = enumerateDeviceLayerProperties(context.getInstanceInterface(), context.getPhysicalDevice());
+
+ for (vector<VkLayerProperties>::const_iterator layer = layers.begin(); layer != layers.end(); ++layer)
+ {
+ const ScopedLogSection section (log, layer->layerName, string("Layer: ") + layer->layerName);
+ const vector<VkExtensionProperties> properties = enumerateDeviceExtensionProperties(context.getInstanceInterface(), context.getPhysicalDevice(), layer->layerName);
+
+ for (size_t extNdx = 0; extNdx < properties.size(); extNdx++)
+ log << TestLog::Message << extNdx << ": " << properties[extNdx] << TestLog::EndMessage;
+ }
+ }
+
+ return tcu::TestStatus::pass("Enumerating extensions succeeded");
+}
+
+tcu::TestStatus deviceFeatures (Context& context)
+{
+ TestLog& log = context.getTestContext().getLog();
+ VkPhysicalDeviceFeatures features;
+
+ deMemset(&features, 0, sizeof(features));
+
+ context.getInstanceInterface().getPhysicalDeviceFeatures(context.getPhysicalDevice(), &features);
+
+ log << TestLog::Message << "device = " << context.getPhysicalDevice() << TestLog::EndMessage
+ << TestLog::Message << features << TestLog::EndMessage;
+
+ return tcu::TestStatus::pass("Query succeeded");
+}
+
+tcu::TestStatus deviceProperties (Context& context)
+{
+ TestLog& log = context.getTestContext().getLog();
+ VkPhysicalDeviceProperties props;
+
+ deMemset(&props, 0, sizeof(props));
+
+ context.getInstanceInterface().getPhysicalDeviceProperties(context.getPhysicalDevice(), &props);
+
+ log << TestLog::Message << "device = " << context.getPhysicalDevice() << TestLog::EndMessage
+ << TestLog::Message << props << TestLog::EndMessage;
+
+ return tcu::TestStatus::pass("Query succeeded");
+}
+
+tcu::TestStatus deviceQueueFamilyProperties (Context& context)
+{
+ TestLog& log = context.getTestContext().getLog();
+ const vector<VkQueueFamilyProperties> queueProperties = getPhysicalDeviceQueueFamilyProperties(context.getInstanceInterface(), context.getPhysicalDevice());
+
+ log << TestLog::Message << "device = " << context.getPhysicalDevice() << TestLog::EndMessage;
+
+ for (size_t queueNdx = 0; queueNdx < queueProperties.size(); queueNdx++)
+ log << TestLog::Message << queueNdx << ": " << queueProperties[queueNdx] << TestLog::EndMessage;
+
+ return tcu::TestStatus::pass("Querying queue properties succeeded");
+}
+
+tcu::TestStatus deviceMemoryProperties (Context& context)
+{
+ TestLog& log = context.getTestContext().getLog();
+
+ log << TestLog::Message << "device = " << context.getPhysicalDevice() << TestLog::EndMessage;
+
+ log << TestLog::Message
+ << getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice())
+ << TestLog::EndMessage;
+
+ return tcu::TestStatus::pass("Querying memory properties succeeded");
+}
+
+} // anonymous
+
+tcu::TestCaseGroup* createInfoTests (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> infoTests (new tcu::TestCaseGroup(testCtx, "info", "Platform Information Tests"));
+
+ {
+ de::MovePtr<tcu::TestCaseGroup> instanceInfoTests (new tcu::TestCaseGroup(testCtx, "instance", "Instance Information Tests"));
+
+ addFunctionCase(instanceInfoTests.get(), "physical_devices", "Physical devices", enumeratePhysicalDevices);
+ addFunctionCase(instanceInfoTests.get(), "layers", "Layers", enumerateInstanceLayers);
+ addFunctionCase(instanceInfoTests.get(), "extensions", "Extensions", enumerateInstanceExtensions);
+
+ infoTests->addChild(instanceInfoTests.release());
+ }
+
+ {
+ de::MovePtr<tcu::TestCaseGroup> deviceInfoTests (new tcu::TestCaseGroup(testCtx, "device", "Device Information Tests"));
+
+ addFunctionCase(deviceInfoTests.get(), "features", "Device Features", deviceFeatures);
+ addFunctionCase(deviceInfoTests.get(), "properties", "Device Properties", deviceProperties);
+ addFunctionCase(deviceInfoTests.get(), "queue_family_properties", "Queue family properties", deviceQueueFamilyProperties);
+ addFunctionCase(deviceInfoTests.get(), "memory_properties", "Memory properties", deviceMemoryProperties);
+ addFunctionCase(deviceInfoTests.get(), "layers", "Layers", enumerateDeviceLayers);
+ addFunctionCase(deviceInfoTests.get(), "extensions", "Extensions", enumerateDeviceExtensions);
+
+ infoTests->addChild(deviceInfoTests.release());
+ }
+
+ return infoTests.release();
+}
+
+} // vkt
--- /dev/null
+#ifndef _VKTINFO_HPP
+#define _VKTINFO_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Platform information tests
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+
+tcu::TestCaseGroup* createInfoTests (tcu::TestContext& testCtx);
+
+} // vkt
+
+#endif // _VKTINFO_HPP
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief RenderPass tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktRenderPassTests.hpp"
+
+#include "vktTestCaseUtil.hpp"
+
+#include "vkDefs.hpp"
+#include "vkDeviceUtil.hpp"
+#include "vkImageUtil.hpp"
+#include "vkMemUtil.hpp"
+#include "vkPlatform.hpp"
+#include "vkPrograms.hpp"
+#include "vkQueryUtil.hpp"
+#include "vkRef.hpp"
+#include "vkRefUtil.hpp"
+#include "vkStrUtil.hpp"
+#include "vkTypeUtil.hpp"
+
+#include "tcuTestLog.hpp"
+#include "tcuResultCollector.hpp"
+#include "tcuFormatUtil.hpp"
+#include "tcuTextureUtil.hpp"
+#include "tcuFloat.hpp"
+#include "tcuMaybe.hpp"
+#include "tcuVectorUtil.hpp"
+
+#include "deUniquePtr.hpp"
+#include "deSharedPtr.hpp"
+#include "deStringUtil.hpp"
+#include "deSTLUtil.hpp"
+#include "deRandom.hpp"
+
+#include <limits>
+
+using namespace vk;
+
+using tcu::Maybe;
+using tcu::nothing;
+using tcu::just;
+using tcu::TestLog;
+using tcu::Vec2;
+using tcu::IVec2;
+using tcu::UVec2;
+using tcu::IVec4;
+using tcu::UVec4;
+using tcu::Vec4;
+using tcu::BVec4;
+using tcu::ConstPixelBufferAccess;
+using tcu::PixelBufferAccess;
+
+using de::UniquePtr;
+
+using std::vector;
+using std::string;
+
+namespace vkt
+{
+namespace
+{
+enum
+{
+ STENCIL_VALUE = 84u,
+ // Limit integer values that are representable as floats
+ MAX_INTEGER_VALUE = ((1u<<22u)-1u)
+};
+
+// Utility functions using flattened structs
+Move<VkFence> createFence (const DeviceInterface& vk, VkDevice device, VkFenceCreateFlags flags)
+{
+ VkFence object = 0;
+ const VkFenceCreateInfo pCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
+ DE_NULL,
+
+ flags
+ };
+ VK_CHECK(vk.createFence(device, &pCreateInfo, DE_NULL, &object));
+ return Move<VkFence>(check<VkFence>(object), Deleter<VkFence>(vk, device));
+}
+
+Move<VkFramebuffer> createFramebuffer (const DeviceInterface& vk,
+ VkDevice device,
+ VkFramebufferCreateFlags pCreateInfo_flags,
+ VkRenderPass pCreateInfo_renderPass,
+ deUint32 pCreateInfo_attachmentCount,
+ const VkImageView* pCreateInfo_pAttachments,
+ deUint32 pCreateInfo_width,
+ deUint32 pCreateInfo_height,
+ deUint32 pCreateInfo_layers)
+{
+ VkFramebuffer object = 0;
+ const VkFramebufferCreateInfo pCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
+ DE_NULL,
+ pCreateInfo_flags,
+ pCreateInfo_renderPass,
+ pCreateInfo_attachmentCount,
+ pCreateInfo_pAttachments,
+ pCreateInfo_width,
+ pCreateInfo_height,
+ pCreateInfo_layers,
+ };
+ VK_CHECK(vk.createFramebuffer(device, &pCreateInfo, DE_NULL, &object));
+ return Move<VkFramebuffer>(check<VkFramebuffer>(object), Deleter<VkFramebuffer>(vk, device));
+}
+
+Move<VkImage> createImage (const DeviceInterface& vk,
+ VkDevice device,
+ VkImageCreateFlags pCreateInfo_flags,
+ VkImageType pCreateInfo_imageType,
+ VkFormat pCreateInfo_format,
+ VkExtent3D pCreateInfo_extent,
+ deUint32 pCreateInfo_mipLevels,
+ deUint32 pCreateInfo_arrayLayers,
+ VkSampleCountFlagBits pCreateInfo_samples,
+ VkImageTiling pCreateInfo_tiling,
+ VkImageUsageFlags pCreateInfo_usage,
+ VkSharingMode pCreateInfo_sharingMode,
+ deUint32 pCreateInfo_queueFamilyCount,
+ const deUint32* pCreateInfo_pQueueFamilyIndices,
+ VkImageLayout pCreateInfo_initialLayout)
+{
+ VkImage object = 0;
+ const VkImageCreateInfo pCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
+ DE_NULL,
+ pCreateInfo_flags,
+ pCreateInfo_imageType,
+ pCreateInfo_format,
+ pCreateInfo_extent,
+ pCreateInfo_mipLevels,
+ pCreateInfo_arrayLayers,
+ pCreateInfo_samples,
+ pCreateInfo_tiling,
+ pCreateInfo_usage,
+ pCreateInfo_sharingMode,
+ pCreateInfo_queueFamilyCount,
+ pCreateInfo_pQueueFamilyIndices,
+ pCreateInfo_initialLayout
+ };
+ VK_CHECK(vk.createImage(device, &pCreateInfo, DE_NULL, &object));
+ return Move<VkImage>(check<VkImage>(object), Deleter<VkImage>(vk, device));
+}
+
+void bindBufferMemory (const DeviceInterface& vk, VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memOffset)
+{
+ VK_CHECK(vk.bindBufferMemory(device, buffer, mem, memOffset));
+}
+
+void bindImageMemory (const DeviceInterface& vk, VkDevice device, VkImage image, VkDeviceMemory mem, VkDeviceSize memOffset)
+{
+ VK_CHECK(vk.bindImageMemory(device, image, mem, memOffset));
+}
+
+Move<VkImageView> createImageView (const DeviceInterface& vk,
+ VkDevice device,
+ VkImageViewCreateFlags pCreateInfo_flags,
+ VkImage pCreateInfo_image,
+ VkImageViewType pCreateInfo_viewType,
+ VkFormat pCreateInfo_format,
+ VkComponentMapping pCreateInfo_components,
+ VkImageSubresourceRange pCreateInfo_subresourceRange)
+{
+ VkImageView object = 0;
+ const VkImageViewCreateInfo pCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
+ DE_NULL,
+ pCreateInfo_flags,
+ pCreateInfo_image,
+ pCreateInfo_viewType,
+ pCreateInfo_format,
+ pCreateInfo_components,
+ pCreateInfo_subresourceRange,
+ };
+ VK_CHECK(vk.createImageView(device, &pCreateInfo, DE_NULL, &object));
+ return Move<VkImageView>(check<VkImageView>(object), Deleter<VkImageView>(vk, device));
+}
+
+Move<VkBuffer> createBuffer (const DeviceInterface& vk,
+ VkDevice device,
+ VkBufferCreateFlags pCreateInfo_flags,
+ VkDeviceSize pCreateInfo_size,
+ VkBufferUsageFlags pCreateInfo_usage,
+ VkSharingMode pCreateInfo_sharingMode,
+ deUint32 pCreateInfo_queueFamilyCount,
+ const deUint32* pCreateInfo_pQueueFamilyIndices)
+{
+ VkBuffer object = 0;
+ const VkBufferCreateInfo pCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
+ DE_NULL,
+ pCreateInfo_flags,
+ pCreateInfo_size,
+ pCreateInfo_usage,
+ pCreateInfo_sharingMode,
+ pCreateInfo_queueFamilyCount,
+ pCreateInfo_pQueueFamilyIndices,
+ };
+ VK_CHECK(vk.createBuffer(device, &pCreateInfo, DE_NULL, &object));
+ return Move<VkBuffer>(check<VkBuffer>(object), Deleter<VkBuffer>(vk, device));
+}
+
+Move<VkCommandPool> createCommandPool (const DeviceInterface& vk,
+ VkDevice device,
+ VkCommandPoolCreateFlags pCreateInfo_flags,
+ deUint32 pCreateInfo_queueFamilyIndex)
+{
+ VkCommandPool object = 0;
+ const VkCommandPoolCreateInfo pCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
+ DE_NULL,
+ pCreateInfo_flags,
+ pCreateInfo_queueFamilyIndex,
+ };
+ VK_CHECK(vk.createCommandPool(device, &pCreateInfo, DE_NULL, &object));
+ return Move<VkCommandPool>(check<VkCommandPool>(object), Deleter<VkCommandPool>(vk, device));
+}
+
+void cmdBeginRenderPass (const DeviceInterface& vk,
+ VkCommandBuffer cmdBuffer,
+ VkRenderPass pRenderPassBegin_renderPass,
+ VkFramebuffer pRenderPassBegin_framebuffer,
+ VkRect2D pRenderPassBegin_renderArea,
+ deUint32 pRenderPassBegin_clearValueCount,
+ const VkClearValue* pRenderPassBegin_pAttachmentClearValues,
+ VkSubpassContents contents)
+{
+ const VkRenderPassBeginInfo pRenderPassBegin =
+ {
+ VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
+ DE_NULL,
+ pRenderPassBegin_renderPass,
+ pRenderPassBegin_framebuffer,
+ pRenderPassBegin_renderArea,
+ pRenderPassBegin_clearValueCount,
+ pRenderPassBegin_pAttachmentClearValues,
+ };
+ vk.cmdBeginRenderPass(cmdBuffer, &pRenderPassBegin, contents);
+}
+
+Move<VkCommandBuffer> allocateCommandBuffer (const DeviceInterface& vk,
+ VkDevice device,
+ VkCommandPool pCreateInfo_commandPool,
+ VkCommandBufferLevel pCreateInfo_level)
+{
+ VkCommandBuffer object = 0;
+ const VkCommandBufferAllocateInfo pCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
+ DE_NULL,
+ pCreateInfo_commandPool,
+ pCreateInfo_level,
+ 1u, // bufferCount
+ };
+ VK_CHECK(vk.allocateCommandBuffers(device, &pCreateInfo, &object));
+ return Move<VkCommandBuffer>(check<VkCommandBuffer>(object), Deleter<VkCommandBuffer>(vk, device, pCreateInfo_commandPool));
+}
+
+void beginCommandBuffer (const DeviceInterface& vk,
+ VkCommandBuffer cmdBuffer,
+ VkCommandBufferUsageFlags pBeginInfo_flags,
+ VkRenderPass pBeginInfo_renderPass,
+ deUint32 pBeginInfo_subpass,
+ VkFramebuffer pBeginInfo_framebuffer,
+ VkBool32 pBeginInfo_occlusionQueryEnable,
+ VkQueryControlFlags pBeginInfo_queryFlags,
+ VkQueryPipelineStatisticFlags pBeginInfo_pipelineStatistics)
+{
+ const VkCommandBufferBeginInfo pBeginInfo =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+ DE_NULL,
+ pBeginInfo_flags,
+ pBeginInfo_renderPass,
+ pBeginInfo_subpass,
+ pBeginInfo_framebuffer,
+ pBeginInfo_occlusionQueryEnable,
+ pBeginInfo_queryFlags,
+ pBeginInfo_pipelineStatistics,
+ };
+ VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &pBeginInfo));
+}
+
+void endCommandBuffer (const DeviceInterface& vk, VkCommandBuffer cmdBuffer)
+{
+ VK_CHECK(vk.endCommandBuffer(cmdBuffer));
+}
+
+void queueSubmit (const DeviceInterface& vk, VkQueue queue, deUint32 cmdBufferCount, const VkCommandBuffer* pCmdBuffers, VkFence fence)
+{
+ const VkSubmitInfo submitInfo =
+ {
+ VK_STRUCTURE_TYPE_SUBMIT_INFO,
+ DE_NULL,
+ 0u, // waitSemaphoreCount
+ (const VkSemaphore*)DE_NULL, // pWaitSemaphores
+ cmdBufferCount, // commandBufferCount
+ pCmdBuffers,
+ 0u, // signalSemaphoreCount
+ (const VkSemaphore*)DE_NULL, // pSignalSemaphores
+ };
+ VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, fence));
+}
+
+void waitForFences (const DeviceInterface& vk, VkDevice device, deUint32 fenceCount, const VkFence* pFences, VkBool32 waitAll, deUint64 timeout)
+{
+ VK_CHECK(vk.waitForFences(device, fenceCount, pFences, waitAll, timeout));
+}
+
+VkImageAspectFlags getImageAspectFlags (VkFormat vkFormat)
+{
+ const tcu::TextureFormat format = mapVkFormat(vkFormat);
+
+ DE_STATIC_ASSERT(tcu::TextureFormat::CHANNELORDER_LAST == 21);
+
+ switch (format.order)
+ {
+ case tcu::TextureFormat::DS:
+ return VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT;
+
+ case tcu::TextureFormat::D:
+ return VK_IMAGE_ASPECT_DEPTH_BIT;
+
+ case tcu::TextureFormat::S:
+ return VK_IMAGE_ASPECT_STENCIL_BIT;
+
+ default:
+ return VK_IMAGE_ASPECT_COLOR_BIT;
+ }
+}
+
+VkAccessFlags getAllMemoryReadFlags (void)
+{
+ return VK_ACCESS_TRANSFER_READ_BIT
+ | VK_ACCESS_UNIFORM_READ_BIT
+ | VK_ACCESS_HOST_READ_BIT
+ | VK_ACCESS_INDEX_READ_BIT
+ | VK_ACCESS_SHADER_READ_BIT
+ | VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT
+ | VK_ACCESS_INDIRECT_COMMAND_READ_BIT
+ | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
+ | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT
+ | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
+}
+
+VkAccessFlags getAllMemoryWriteFlags (void)
+{
+ return VK_ACCESS_TRANSFER_WRITE_BIT
+ | VK_ACCESS_HOST_WRITE_BIT
+ | VK_ACCESS_SHADER_WRITE_BIT
+ | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT
+ | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+}
+
+VkPipelineStageFlags getAllPipelineStageFlags (void)
+{
+ return VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT
+ | VK_PIPELINE_STAGE_TRANSFER_BIT
+ | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT
+ | VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT
+ | VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT
+ | VK_PIPELINE_STAGE_VERTEX_INPUT_BIT
+ | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT
+ | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
+ | VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT
+ | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
+ | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT
+ | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
+ | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+}
+
+class AttachmentReference
+{
+public:
+ AttachmentReference (deUint32 attachment,
+ VkImageLayout layout)
+ : m_attachment (attachment)
+ , m_layout (layout)
+ {
+ }
+
+ deUint32 getAttachment (void) const { return m_attachment; }
+ VkImageLayout getImageLayout (void) const { return m_layout; }
+
+private:
+ deUint32 m_attachment;
+ VkImageLayout m_layout;
+};
+
+class Subpass
+{
+public:
+ Subpass (VkPipelineBindPoint pipelineBindPoint,
+ VkSubpassDescriptionFlags flags,
+ const vector<AttachmentReference>& inputAttachments,
+ const vector<AttachmentReference>& colorAttachments,
+ const vector<AttachmentReference>& resolveAttachments,
+ AttachmentReference depthStencilAttachment,
+ const vector<AttachmentReference>& preserveAttachments)
+ : m_pipelineBindPoint (pipelineBindPoint)
+ , m_flags (flags)
+ , m_inputAttachments (inputAttachments)
+ , m_colorAttachments (colorAttachments)
+ , m_resolveAttachments (resolveAttachments)
+ , m_depthStencilAttachment (depthStencilAttachment)
+ , m_preserveAttachments (preserveAttachments)
+ {
+ }
+
+ VkPipelineBindPoint getPipelineBindPoint (void) const { return m_pipelineBindPoint; }
+ VkSubpassDescriptionFlags getFlags (void) const { return m_flags; }
+ const vector<AttachmentReference>& getInputAttachments (void) const { return m_inputAttachments; }
+ const vector<AttachmentReference>& getColorAttachments (void) const { return m_colorAttachments; }
+ const vector<AttachmentReference>& getResolveAttachments (void) const { return m_resolveAttachments; }
+ const AttachmentReference& getDepthStencilAttachment (void) const { return m_depthStencilAttachment; }
+ const vector<AttachmentReference>& getPreserveAttachments (void) const { return m_preserveAttachments; }
+
+private:
+ VkPipelineBindPoint m_pipelineBindPoint;
+ VkSubpassDescriptionFlags m_flags;
+
+ vector<AttachmentReference> m_inputAttachments;
+ vector<AttachmentReference> m_colorAttachments;
+ vector<AttachmentReference> m_resolveAttachments;
+ AttachmentReference m_depthStencilAttachment;
+
+ vector<AttachmentReference> m_preserveAttachments;
+};
+
+class SubpassDependency
+{
+public:
+ SubpassDependency (deUint32 srcPass,
+ deUint32 dstPass,
+
+ VkPipelineStageFlags srcStageMask,
+ VkPipelineStageFlags dstStageMask,
+
+ VkAccessFlags outputMask,
+ VkAccessFlags inputMask,
+
+ VkDependencyFlags flags)
+ : m_srcPass (srcPass)
+ , m_dstPass (dstPass)
+
+ , m_srcStageMask (srcStageMask)
+ , m_dstStageMask (dstStageMask)
+
+ , m_outputMask (outputMask)
+ , m_inputMask (inputMask)
+ , m_flags (flags)
+ {
+ }
+
+ deUint32 getSrcPass (void) const { return m_srcPass; }
+ deUint32 getDstPass (void) const { return m_dstPass; }
+
+ VkPipelineStageFlags getSrcStageMask (void) const { return m_srcStageMask; }
+ VkPipelineStageFlags getDstStageMask (void) const { return m_dstStageMask; }
+
+ VkAccessFlags getOutputMask (void) const { return m_outputMask; }
+ VkAccessFlags getInputMask (void) const { return m_inputMask; }
+
+ VkDependencyFlags getFlags (void) const { return m_flags; }
+
+private:
+ deUint32 m_srcPass;
+ deUint32 m_dstPass;
+
+ VkPipelineStageFlags m_srcStageMask;
+ VkPipelineStageFlags m_dstStageMask;
+
+ VkAccessFlags m_outputMask;
+ VkAccessFlags m_inputMask;
+ VkDependencyFlags m_flags;
+};
+
+class Attachment
+{
+public:
+ Attachment (VkFormat format,
+ VkSampleCountFlagBits samples,
+
+ VkAttachmentLoadOp loadOp,
+ VkAttachmentStoreOp storeOp,
+
+ VkAttachmentLoadOp stencilLoadOp,
+ VkAttachmentStoreOp stencilStoreOp,
+
+ VkImageLayout initialLayout,
+ VkImageLayout finalLayout)
+ : m_format (format)
+ , m_samples (samples)
+
+ , m_loadOp (loadOp)
+ , m_storeOp (storeOp)
+
+ , m_stencilLoadOp (stencilLoadOp)
+ , m_stencilStoreOp (stencilStoreOp)
+
+ , m_initialLayout (initialLayout)
+ , m_finalLayout (finalLayout)
+ {
+ }
+
+ VkFormat getFormat (void) const { return m_format; }
+ VkSampleCountFlagBits getSamples (void) const { return m_samples; }
+
+ VkAttachmentLoadOp getLoadOp (void) const { return m_loadOp; }
+ VkAttachmentStoreOp getStoreOp (void) const { return m_storeOp; }
+
+
+ VkAttachmentLoadOp getStencilLoadOp (void) const { return m_stencilLoadOp; }
+ VkAttachmentStoreOp getStencilStoreOp (void) const { return m_stencilStoreOp; }
+
+ VkImageLayout getInitialLayout (void) const { return m_initialLayout; }
+ VkImageLayout getFinalLayout (void) const { return m_finalLayout; }
+
+private:
+ VkFormat m_format;
+ VkSampleCountFlagBits m_samples;
+
+ VkAttachmentLoadOp m_loadOp;
+ VkAttachmentStoreOp m_storeOp;
+
+ VkAttachmentLoadOp m_stencilLoadOp;
+ VkAttachmentStoreOp m_stencilStoreOp;
+
+ VkImageLayout m_initialLayout;
+ VkImageLayout m_finalLayout;
+};
+
+class RenderPass
+{
+public:
+ RenderPass (const vector<Attachment>& attachments,
+ const vector<Subpass>& subpasses,
+ const vector<SubpassDependency>& dependencies)
+ : m_attachments (attachments)
+ , m_subpasses (subpasses)
+ , m_dependencies (dependencies)
+ {
+ }
+
+ const vector<Attachment>& getAttachments (void) const { return m_attachments; }
+ const vector<Subpass>& getSubpasses (void) const { return m_subpasses; }
+ const vector<SubpassDependency>& getDependencies (void) const { return m_dependencies; }
+
+private:
+ const vector<Attachment> m_attachments;
+ const vector<Subpass> m_subpasses;
+ const vector<SubpassDependency> m_dependencies;
+};
+
+struct TestConfig
+{
+ enum RenderTypes
+ {
+ RENDERTYPES_NONE = 0,
+ RENDERTYPES_CLEAR = (1<<1),
+ RENDERTYPES_DRAW = (1<<2)
+ };
+
+ enum CommandBufferTypes
+ {
+ COMMANDBUFFERTYPES_INLINE = (1<<0),
+ COMMANDBUFFERTYPES_SECONDARY = (1<<1)
+ };
+
+ enum ImageMemory
+ {
+ IMAGEMEMORY_STRICT = (1<<0),
+ IMAGEMEMORY_LAZY = (1<<1)
+ };
+
+ TestConfig (const RenderPass& renderPass_,
+ RenderTypes renderTypes_,
+ CommandBufferTypes commandBufferTypes_,
+ ImageMemory imageMemory_,
+ const UVec2& targetSize_,
+ const UVec2& renderPos_,
+ const UVec2& renderSize_,
+ deUint32 seed_)
+ : renderPass (renderPass_)
+ , renderTypes (renderTypes_)
+ , commandBufferTypes (commandBufferTypes_)
+ , imageMemory (imageMemory_)
+ , targetSize (targetSize_)
+ , renderPos (renderPos_)
+ , renderSize (renderSize_)
+ , seed (seed_)
+ {
+ }
+
+ RenderPass renderPass;
+ RenderTypes renderTypes;
+ CommandBufferTypes commandBufferTypes;
+ ImageMemory imageMemory;
+ UVec2 targetSize;
+ UVec2 renderPos;
+ UVec2 renderSize;
+ deUint32 seed;
+};
+
+TestConfig::RenderTypes operator| (TestConfig::RenderTypes a, TestConfig::RenderTypes b)
+{
+ return (TestConfig::RenderTypes)(((deUint32)a) | ((deUint32)b));
+}
+
+TestConfig::CommandBufferTypes operator| (TestConfig::CommandBufferTypes a, TestConfig::CommandBufferTypes b)
+{
+ return (TestConfig::CommandBufferTypes)(((deUint32)a) | ((deUint32)b));
+}
+
+TestConfig::ImageMemory operator| (TestConfig::ImageMemory a, TestConfig::ImageMemory b)
+{
+ return (TestConfig::ImageMemory)(((deUint32)a) | ((deUint32)b));
+}
+
+void logRenderPassInfo (TestLog& log,
+ const RenderPass& renderPass)
+{
+ const tcu::ScopedLogSection section (log, "RenderPass", "RenderPass");
+
+ {
+ const tcu::ScopedLogSection attachmentsSection (log, "Attachments", "Attachments");
+ const vector<Attachment>& attachments = renderPass.getAttachments();
+
+ for (size_t attachmentNdx = 0; attachmentNdx < attachments.size(); attachmentNdx++)
+ {
+ const tcu::ScopedLogSection attachmentSection (log, "Attachment" + de::toString(attachmentNdx), "Attachment " + de::toString(attachmentNdx));
+ const Attachment& attachment = attachments[attachmentNdx];
+
+ log << TestLog::Message << "Format: " << attachment.getFormat() << TestLog::EndMessage;
+ log << TestLog::Message << "Samples: " << attachment.getSamples() << TestLog::EndMessage;
+
+ log << TestLog::Message << "LoadOp: " << attachment.getLoadOp() << TestLog::EndMessage;
+ log << TestLog::Message << "StoreOp: " << attachment.getStoreOp() << TestLog::EndMessage;
+
+ log << TestLog::Message << "StencilLoadOp: " << attachment.getStencilLoadOp() << TestLog::EndMessage;
+ log << TestLog::Message << "StencilStoreOp: " << attachment.getStencilStoreOp() << TestLog::EndMessage;
+
+ log << TestLog::Message << "InitialLayout: " << attachment.getInitialLayout() << TestLog::EndMessage;
+ log << TestLog::Message << "FinalLayout: " << attachment.getFinalLayout() << TestLog::EndMessage;
+ }
+ }
+
+ {
+ const tcu::ScopedLogSection subpassesSection (log, "Subpasses", "Subpasses");
+ const vector<Subpass>& subpasses = renderPass.getSubpasses();
+
+ for (size_t subpassNdx = 0; subpassNdx < subpasses.size(); subpassNdx++)
+ {
+ const tcu::ScopedLogSection subpassSection (log, "Subpass" + de::toString(subpassNdx), "Subpass " + de::toString(subpassNdx));
+ const Subpass& subpass = subpasses[subpassNdx];
+
+ const vector<AttachmentReference>& inputAttachments = subpass.getInputAttachments();
+ const vector<AttachmentReference>& colorAttachments = subpass.getColorAttachments();
+ const vector<AttachmentReference>& resolveAttachments = subpass.getResolveAttachments();
+ const vector<AttachmentReference>& preserveAttachments = subpass.getPreserveAttachments();
+
+ if (!inputAttachments.empty())
+ {
+ const tcu::ScopedLogSection inputAttachmentsSection (log, "Inputs", "Inputs");
+
+ for (size_t inputNdx = 0; inputNdx < inputAttachments.size(); inputNdx++)
+ {
+ const tcu::ScopedLogSection inputAttachmentSection (log, "Input" + de::toString(inputNdx), "Input " + de::toString(inputNdx));
+ const AttachmentReference& inputAttachment = inputAttachments[inputNdx];
+
+ log << TestLog::Message << "Attachment: " << inputAttachment.getAttachment() << TestLog::EndMessage;
+ log << TestLog::Message << "Layout: " << inputAttachment.getImageLayout() << TestLog::EndMessage;
+ }
+ }
+
+ if (subpass.getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED)
+ {
+ const tcu::ScopedLogSection depthStencilAttachmentSection (log, "DepthStencil", "DepthStencil");
+ const AttachmentReference& depthStencilAttachment = subpass.getDepthStencilAttachment();
+
+ log << TestLog::Message << "Attachment: " << depthStencilAttachment.getAttachment() << TestLog::EndMessage;
+ log << TestLog::Message << "Layout: " << depthStencilAttachment.getImageLayout() << TestLog::EndMessage;
+ }
+
+ if (!colorAttachments.empty())
+ {
+ const tcu::ScopedLogSection colorAttachmentsSection (log, "Colors", "Colors");
+
+ for (size_t colorNdx = 0; colorNdx < colorAttachments.size(); colorNdx++)
+ {
+ const tcu::ScopedLogSection colorAttachmentSection (log, "Color" + de::toString(colorNdx), "Color " + de::toString(colorNdx));
+ const AttachmentReference& colorAttachment = colorAttachments[colorNdx];
+
+ log << TestLog::Message << "Attachment: " << colorAttachment.getAttachment() << TestLog::EndMessage;
+ log << TestLog::Message << "Layout: " << colorAttachment.getImageLayout() << TestLog::EndMessage;
+ }
+ }
+
+ if (!resolveAttachments.empty())
+ {
+ const tcu::ScopedLogSection resolveAttachmentsSection (log, "Resolves", "Resolves");
+
+ for (size_t resolveNdx = 0; resolveNdx < resolveAttachments.size(); resolveNdx++)
+ {
+ const tcu::ScopedLogSection resolveAttachmentSection (log, "Resolve" + de::toString(resolveNdx), "Resolve " + de::toString(resolveNdx));
+ const AttachmentReference& resolveAttachment = resolveAttachments[resolveNdx];
+
+ log << TestLog::Message << "Attachment: " << resolveAttachment.getAttachment() << TestLog::EndMessage;
+ log << TestLog::Message << "Layout: " << resolveAttachment.getImageLayout() << TestLog::EndMessage;
+ }
+ }
+
+ if (!preserveAttachments.empty())
+ {
+ const tcu::ScopedLogSection preserveAttachmentsSection (log, "Preserves", "Preserves");
+
+ for (size_t preserveNdx = 0; preserveNdx < preserveAttachments.size(); preserveNdx++)
+ {
+ const tcu::ScopedLogSection preserveAttachmentSection (log, "Preserve" + de::toString(preserveNdx), "Preserve " + de::toString(preserveNdx));
+ const AttachmentReference& preserveAttachment = preserveAttachments[preserveNdx];
+
+ log << TestLog::Message << "Attachment: " << preserveAttachment.getAttachment() << TestLog::EndMessage;
+ log << TestLog::Message << "Layout: " << preserveAttachment.getImageLayout() << TestLog::EndMessage;
+ }
+ }
+ }
+
+ }
+
+ if (!renderPass.getDependencies().empty())
+ {
+ const tcu::ScopedLogSection dependenciesSection (log, "Dependencies", "Dependencies");
+
+ for (size_t depNdx = 0; depNdx < renderPass.getDependencies().size(); depNdx++)
+ {
+ const tcu::ScopedLogSection dependencySection (log, "Dependency" + de::toString(depNdx), "Dependency " + de::toString(depNdx));
+ const SubpassDependency& dep = renderPass.getDependencies()[depNdx];
+
+ log << TestLog::Message << "Source: " << dep.getSrcPass() << TestLog::EndMessage;
+ log << TestLog::Message << "Destination: " << dep.getDstPass() << TestLog::EndMessage;
+
+ log << TestLog::Message << "Source Stage Mask: " << dep.getSrcStageMask() << TestLog::EndMessage;
+ log << TestLog::Message << "Destination Stage Mask: " << dep.getDstStageMask() << TestLog::EndMessage;
+
+ log << TestLog::Message << "Input Mask: " << dep.getInputMask() << TestLog::EndMessage;
+ log << TestLog::Message << "Output Mask: " << dep.getOutputMask() << TestLog::EndMessage;
+ log << TestLog::Message << "Dependency Flags: " << getDependencyFlagsStr(dep.getFlags()) << TestLog::EndMessage;
+ }
+ }
+}
+
+std::string clearColorToString (VkFormat vkFormat, VkClearColorValue value)
+{
+ const tcu::TextureFormat format = mapVkFormat(vkFormat);
+ const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(format.type);
+ const tcu::BVec4 channelMask = tcu::getTextureFormatChannelMask(format);
+
+ std::ostringstream stream;
+
+ stream << "(";
+
+ switch (channelClass)
+ {
+ case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
+ for (int i = 0; i < 4; i++)
+ {
+ if (i > 0)
+ stream << ", ";
+
+ if (channelMask[i])
+ stream << value.int32[i];
+ else
+ stream << "Undef";
+ }
+ break;
+
+ case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
+ for (int i = 0; i < 4; i++)
+ {
+ if (i > 0)
+ stream << ", ";
+
+ if (channelMask[i])
+ stream << value.uint32[i];
+ else
+ stream << "Undef";
+ }
+ break;
+
+ case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
+ case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
+ case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
+ for (int i = 0; i < 4; i++)
+ {
+ if (i > 0)
+ stream << ", ";
+
+ if (channelMask[i])
+ stream << value.float32[i];
+ else
+ stream << "Undef";
+ }
+ break;
+
+ default:
+ DE_FATAL("Unknown channel class");
+ }
+
+ stream << ")";
+
+ return stream.str();
+}
+
+std::string clearValueToString (VkFormat vkFormat, VkClearValue value)
+{
+ const tcu::TextureFormat format = mapVkFormat(vkFormat);
+
+ if (tcu::hasStencilComponent(format.order) || tcu::hasDepthComponent(format.order))
+ {
+ std::ostringstream stream;
+
+ stream << "(";
+
+ if (tcu::hasStencilComponent(format.order))
+ stream << "stencil: " << value.depthStencil.stencil;
+
+ if (tcu::hasStencilComponent(format.order) && tcu::hasDepthComponent(format.order))
+ stream << ", ";
+
+ if (tcu::hasDepthComponent(format.order))
+ stream << "depth: " << value.depthStencil.depth;
+
+ stream << ")";
+
+ return stream.str();
+ }
+ else
+ return clearColorToString(vkFormat, value.color);
+}
+
+VkClearColorValue randomColorClearValue (const Attachment& attachment, de::Random& rng)
+{
+ const float clearNan = tcu::Float32::nan().asFloat();
+ const tcu::TextureFormat format = mapVkFormat(attachment.getFormat());
+ const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(format.type);
+ const tcu::BVec4 channelMask = tcu::getTextureFormatChannelMask(format);
+ VkClearColorValue clearColor;
+
+ switch (channelClass)
+ {
+ case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
+ {
+ const tcu::IVec4 valueMin = tcu::getFormatMinIntValue(format);
+ const tcu::IVec4 valueMax = tcu::getFormatMaxIntValue(format);
+
+ for (int ndx = 0; ndx < 4; ndx++)
+ {
+ if (!channelMask[ndx])
+ clearColor.int32[ndx] = std::numeric_limits<deInt32>::min();
+ else
+ clearColor.uint32[ndx] = rng.getInt(valueMin[ndx], valueMax[ndx]);
+ }
+ break;
+ }
+
+ case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
+ {
+ const UVec4 valueMax = tcu::getFormatMaxUintValue(format);
+
+ for (int ndx = 0; ndx < 4; ndx++)
+ {
+ if (!channelMask[ndx])
+ clearColor.uint32[ndx] = std::numeric_limits<deUint32>::max();
+ else
+ clearColor.uint32[ndx] = rng.getUint32() % valueMax[ndx];
+ }
+ break;
+ }
+
+ case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
+ case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
+ case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
+ {
+ const tcu::TextureFormatInfo formatInfo = tcu::getTextureFormatInfo(format);
+
+ for (int ndx = 0; ndx < 4; ndx++)
+ {
+ if (!channelMask[ndx])
+ clearColor.float32[ndx] = clearNan;
+ else
+ clearColor.float32[ndx] = formatInfo.valueMin[ndx] + rng.getFloat() * (formatInfo.valueMax[ndx] - formatInfo.valueMin[ndx]);
+ }
+ break;
+ }
+
+ default:
+ DE_FATAL("Unknown channel class");
+ }
+
+ return clearColor;
+}
+
+VkAttachmentDescription createAttachmentDescription (const Attachment& attachment)
+{
+ const VkAttachmentDescription attachmentDescription =
+ {
+ 0, // flags
+
+ attachment.getFormat(), // format
+ attachment.getSamples(), // samples
+
+ attachment.getLoadOp(), // loadOp
+ attachment.getStoreOp(), // storeOp
+
+ attachment.getStencilLoadOp(), // stencilLoadOp
+ attachment.getStencilStoreOp(), // stencilStoreOp
+
+ attachment.getInitialLayout(), // initialLayout
+ attachment.getFinalLayout(), // finalLayout
+ };
+
+ return attachmentDescription;
+}
+
+VkAttachmentReference createAttachmentReference (const AttachmentReference& referenceInfo)
+{
+ const VkAttachmentReference reference =
+ {
+ referenceInfo.getAttachment(), // attachment;
+ referenceInfo.getImageLayout() // layout;
+ };
+
+ return reference;
+}
+
+VkSubpassDescription createSubpassDescription (const Subpass& subpass,
+ vector<VkAttachmentReference>* attachmentReferenceLists)
+{
+ vector<VkAttachmentReference>& inputAttachmentReferences = attachmentReferenceLists[0];
+ vector<VkAttachmentReference>& colorAttachmentReferences = attachmentReferenceLists[1];
+ vector<VkAttachmentReference>& resolveAttachmentReferences = attachmentReferenceLists[2];
+ vector<VkAttachmentReference>& depthStencilAttachmentReferences = attachmentReferenceLists[3];
+ vector<VkAttachmentReference>& preserveAttachmentReferences = attachmentReferenceLists[4];
+
+ for (size_t attachmentNdx = 0; attachmentNdx < subpass.getColorAttachments().size(); attachmentNdx++)
+ colorAttachmentReferences.push_back(createAttachmentReference(subpass.getColorAttachments()[attachmentNdx]));
+
+ for (size_t attachmentNdx = 0; attachmentNdx < subpass.getInputAttachments().size(); attachmentNdx++)
+ inputAttachmentReferences.push_back(createAttachmentReference(subpass.getInputAttachments()[attachmentNdx]));
+
+ for (size_t attachmentNdx = 0; attachmentNdx < subpass.getResolveAttachments().size(); attachmentNdx++)
+ resolveAttachmentReferences.push_back(createAttachmentReference(subpass.getResolveAttachments()[attachmentNdx]));
+
+ depthStencilAttachmentReferences.push_back(createAttachmentReference(subpass.getDepthStencilAttachment()));
+
+ for (size_t attachmentNdx = 0; attachmentNdx < subpass.getPreserveAttachments().size(); attachmentNdx++)
+ preserveAttachmentReferences.push_back(createAttachmentReference(subpass.getPreserveAttachments()[attachmentNdx]));
+
+ DE_ASSERT(resolveAttachmentReferences.empty() || colorAttachmentReferences.size() == resolveAttachmentReferences.size());
+
+ {
+ const VkSubpassDescription subpassDescription =
+ {
+ subpass.getFlags(), // flags;
+ subpass.getPipelineBindPoint(), // pipelineBindPoint;
+
+ (deUint32)inputAttachmentReferences.size(), // inputCount;
+ inputAttachmentReferences.empty() ? DE_NULL : &inputAttachmentReferences[0], // inputAttachments;
+
+ (deUint32)colorAttachmentReferences.size(), // colorCount;
+ colorAttachmentReferences.empty() ? DE_NULL : &colorAttachmentReferences[0], // colorAttachments;
+ resolveAttachmentReferences.empty() ? DE_NULL : &resolveAttachmentReferences[0], // resolveAttachments;
+
+ &depthStencilAttachmentReferences[0], // pDepthStencilAttachment;
+ (deUint32)preserveAttachmentReferences.size(), // preserveCount;
+ preserveAttachmentReferences.empty() ? DE_NULL : &preserveAttachmentReferences[0] // preserveAttachments;
+ };
+
+ return subpassDescription;
+ }
+}
+
+VkSubpassDependency createSubpassDependency (const SubpassDependency& dependencyInfo)
+{
+ const VkSubpassDependency dependency =
+ {
+ dependencyInfo.getSrcPass(), // srcSubpass;
+ dependencyInfo.getDstPass(), // destSubpass;
+
+ dependencyInfo.getSrcStageMask(), // srcStageMask;
+ dependencyInfo.getDstStageMask(), // destStageMask;
+
+ dependencyInfo.getOutputMask(), // outputMask;
+ dependencyInfo.getInputMask(), // inputMask;
+
+ dependencyInfo.getFlags() // dependencyFlags;
+ };
+
+ return dependency;
+}
+
+Move<VkRenderPass> createRenderPass (const DeviceInterface& vk,
+ VkDevice device,
+ const RenderPass& renderPassInfo)
+{
+ const size_t perSubpassAttachmentReferenceLists = 5;
+ vector<VkAttachmentDescription> attachments;
+ vector<VkSubpassDescription> subpasses;
+ vector<VkSubpassDependency> dependencies;
+ vector<vector<VkAttachmentReference> > attachmentReferenceLists(renderPassInfo.getSubpasses().size() * perSubpassAttachmentReferenceLists);
+
+ for (size_t attachmentNdx = 0; attachmentNdx < renderPassInfo.getAttachments().size(); attachmentNdx++)
+ attachments.push_back(createAttachmentDescription(renderPassInfo.getAttachments()[attachmentNdx]));
+
+ for (size_t subpassNdx = 0; subpassNdx < renderPassInfo.getSubpasses().size(); subpassNdx++)
+ subpasses.push_back(createSubpassDescription(renderPassInfo.getSubpasses()[subpassNdx], &(attachmentReferenceLists[subpassNdx * perSubpassAttachmentReferenceLists])));
+
+ for (size_t depNdx = 0; depNdx < renderPassInfo.getDependencies().size(); depNdx++)
+ dependencies.push_back(createSubpassDependency(renderPassInfo.getDependencies()[depNdx]));
+
+ {
+ const VkRenderPassCreateInfo createInfo =
+ {
+ VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
+ DE_NULL,
+ (VkRenderPassCreateFlags)0u,
+ (deUint32)attachments.size(),
+ (attachments.empty() ? DE_NULL : &attachments[0]),
+ (deUint32)subpasses.size(),
+ (subpasses.empty() ? DE_NULL : &subpasses[0]),
+ (deUint32)dependencies.size(),
+ (dependencies.empty() ? DE_NULL : &dependencies[0])
+ };
+
+ return createRenderPass(vk, device, &createInfo);
+ }
+}
+
+Move<VkFramebuffer> createFramebuffer (const DeviceInterface& vk,
+ VkDevice device,
+ VkRenderPass renderPass,
+ const UVec2& size,
+ const vector<VkImageView>& attachments)
+{
+ return createFramebuffer(vk, device, 0u, renderPass, (deUint32)attachments.size(), attachments.empty() ? DE_NULL : &attachments[0], size.x(), size.y(), 1u);
+}
+
+Move<VkImage> createAttachmentImage (const DeviceInterface& vk,
+ VkDevice device,
+ deUint32 queueIndex,
+ const UVec2& size,
+ VkFormat format,
+ VkSampleCountFlagBits samples,
+ VkImageUsageFlags usageFlags,
+ VkImageLayout layout)
+{
+ const VkExtent3D size_ = { (deInt32)size.x(), (deInt32)size.y(), 1 };
+ VkImageUsageFlags targetUsageFlags = 0;
+ const tcu::TextureFormat textureFormat = mapVkFormat(format);
+
+ if (tcu::hasDepthComponent(textureFormat.order) || tcu::hasStencilComponent(textureFormat.order))
+ {
+ targetUsageFlags |= vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
+ }
+ else
+ {
+ targetUsageFlags |= vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+ }
+
+ return createImage(vk, device,
+ (VkImageCreateFlags)0,
+ VK_IMAGE_TYPE_2D,
+ format,
+ size_,
+ 1u /* mipLevels */,
+ 1u /* arraySize */,
+ samples,
+ VK_IMAGE_TILING_OPTIMAL,
+ usageFlags | targetUsageFlags,
+ VK_SHARING_MODE_EXCLUSIVE,
+ 1,
+ &queueIndex,
+ layout);
+}
+
+de::MovePtr<Allocation> createImageMemory (const DeviceInterface& vk,
+ VkDevice device,
+ Allocator& allocator,
+ VkImage image,
+ bool lazy)
+{
+ de::MovePtr<Allocation> allocation (allocator.allocate(getImageMemoryRequirements(vk, device, image), lazy ? MemoryRequirement::LazilyAllocated : MemoryRequirement::Any));
+ bindImageMemory(vk, device, image, allocation->getMemory(), allocation->getOffset());
+ return allocation;
+}
+
+Move<VkImageView> createImageAttachmentView (const DeviceInterface& vk,
+ VkDevice device,
+ VkImage image,
+ VkFormat format,
+ VkImageAspectFlags aspect)
+{
+ const VkImageSubresourceRange range =
+ {
+ aspect,
+ 0,
+ 1,
+ 0,
+ 1
+ };
+
+ return createImageView(vk, device, 0u, image, VK_IMAGE_VIEW_TYPE_2D, format, makeComponentMappingRGBA(), range);
+}
+
+VkClearValue randomClearValue (const Attachment& attachment, de::Random& rng)
+{
+ const float clearNan = tcu::Float32::nan().asFloat();
+ const tcu::TextureFormat format = mapVkFormat(attachment.getFormat());
+
+ if (tcu::hasStencilComponent(format.order) || tcu::hasDepthComponent(format.order))
+ {
+ VkClearValue clearValue;
+
+ clearValue.depthStencil.depth = clearNan;
+ clearValue.depthStencil.stencil = 255;
+
+ if (tcu::hasStencilComponent(format.order))
+ clearValue.depthStencil.stencil = rng.getInt(0, 255);
+
+ if (tcu::hasDepthComponent(format.order))
+ clearValue.depthStencil.depth = rng.getFloat();
+
+ return clearValue;
+ }
+ else
+ {
+ VkClearValue clearValue;
+
+ clearValue.color = randomColorClearValue(attachment, rng);
+
+ return clearValue;
+ }
+}
+
+class AttachmentResources
+{
+public:
+ AttachmentResources (const DeviceInterface& vk,
+ VkDevice device,
+ Allocator& allocator,
+ deUint32 queueIndex,
+ const UVec2& size,
+ const Attachment& attachmentInfo,
+ bool lazy)
+ : m_image (createAttachmentImage(vk, device, queueIndex, size, attachmentInfo.getFormat(), attachmentInfo.getSamples(), lazy ? VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT : 0, VK_IMAGE_LAYOUT_UNDEFINED))
+ , m_imageMemory (createImageMemory(vk, device, allocator, *m_image, lazy))
+ , m_attachmentView (createImageAttachmentView(vk, device, *m_image, attachmentInfo.getFormat(), getImageAspectFlags(attachmentInfo.getFormat())))
+ {
+ if (!lazy)
+ {
+ const tcu::TextureFormat format = mapVkFormat(attachmentInfo.getFormat());
+
+ if (tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order))
+ {
+ const tcu::TextureFormat depthFormat = tcu::getEffectiveDepthStencilTextureFormat(format, tcu::Sampler::MODE_DEPTH);
+ const tcu::TextureFormat stencilFormat = tcu::getEffectiveDepthStencilTextureFormat(format, tcu::Sampler::MODE_STENCIL);
+
+ m_bufferSize = size.x() * size.y() * depthFormat.getPixelSize();
+ m_secondaryBufferSize = size.x() * size.y() * stencilFormat.getPixelSize();
+
+ m_buffer = createBuffer(vk, device, 0, m_bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_SHARING_MODE_EXCLUSIVE, 1, &queueIndex);
+ m_bufferMemory = allocator.allocate(getBufferMemoryRequirements(vk, device, *m_buffer), MemoryRequirement::HostVisible);
+
+ bindBufferMemory(vk, device, *m_buffer, m_bufferMemory->getMemory(), m_bufferMemory->getOffset());
+
+ m_secondaryBuffer = createBuffer(vk, device, 0, m_secondaryBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_SHARING_MODE_EXCLUSIVE, 1, &queueIndex);
+ m_secondaryBufferMemory = allocator.allocate(getBufferMemoryRequirements(vk, device, *m_secondaryBuffer), MemoryRequirement::HostVisible);
+
+ bindBufferMemory(vk, device, *m_secondaryBuffer, m_secondaryBufferMemory->getMemory(), m_secondaryBufferMemory->getOffset());
+ }
+ else
+ {
+ m_bufferSize = size.x() * size.y() * format.getPixelSize();
+
+ m_buffer = createBuffer(vk, device, 0, m_bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_SHARING_MODE_EXCLUSIVE, 1, &queueIndex);
+ m_bufferMemory = allocator.allocate(getBufferMemoryRequirements(vk, device, *m_buffer), MemoryRequirement::HostVisible);
+
+ bindBufferMemory(vk, device, *m_buffer, m_bufferMemory->getMemory(), m_bufferMemory->getOffset());
+ }
+ }
+ }
+
+ ~AttachmentResources (void)
+ {
+ }
+
+ VkImageView getAttachmentView (void) const
+ {
+ return *m_attachmentView;
+ }
+
+ VkImage getImage (void) const
+ {
+ return *m_image;
+ }
+
+ VkBuffer getBuffer (void) const
+ {
+ DE_ASSERT(*m_buffer != DE_NULL);
+ return *m_buffer;
+ }
+
+ VkDeviceSize getBufferSize (void) const
+ {
+ DE_ASSERT(*m_buffer != DE_NULL);
+ return m_bufferSize;
+ }
+
+ const Allocation& getResultMemory (void) const
+ {
+ DE_ASSERT(m_bufferMemory);
+ return *m_bufferMemory;
+ }
+
+ VkBuffer getSecondaryBuffer (void) const
+ {
+ DE_ASSERT(*m_secondaryBuffer != DE_NULL);
+ return *m_secondaryBuffer;
+ }
+
+ VkDeviceSize getSecondaryBufferSize (void) const
+ {
+ DE_ASSERT(*m_secondaryBuffer != DE_NULL);
+ return m_secondaryBufferSize;
+ }
+
+ const Allocation& getSecondaryResultMemory (void) const
+ {
+ DE_ASSERT(m_secondaryBufferMemory);
+ return *m_secondaryBufferMemory;
+ }
+
+private:
+ const Unique<VkImage> m_image;
+ const UniquePtr<Allocation> m_imageMemory;
+ const Unique<VkImageView> m_attachmentView;
+
+ Move<VkBuffer> m_buffer;
+ VkDeviceSize m_bufferSize;
+ de::MovePtr<Allocation> m_bufferMemory;
+
+ Move<VkBuffer> m_secondaryBuffer;
+ VkDeviceSize m_secondaryBufferSize;
+ de::MovePtr<Allocation> m_secondaryBufferMemory;
+};
+
+void uploadBufferData (const DeviceInterface& vk,
+ VkDevice device,
+ const Allocation& memory,
+ size_t size,
+ const void* data)
+{
+ const VkMappedMemoryRange range =
+ {
+ VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // sType;
+ DE_NULL, // pNext;
+ memory.getMemory(), // mem;
+ memory.getOffset(), // offset;
+ (VkDeviceSize)size // size;
+ };
+ void* const ptr = memory.getHostPtr();
+
+ deMemcpy(ptr, data, size);
+ VK_CHECK(vk.flushMappedMemoryRanges(device, 1, &range));
+}
+
+VkImageAspectFlagBits getPrimaryImageAspect (tcu::TextureFormat::ChannelOrder order)
+{
+ DE_STATIC_ASSERT(tcu::TextureFormat::CHANNELORDER_LAST == 21);
+
+ switch (order)
+ {
+ case tcu::TextureFormat::D:
+ case tcu::TextureFormat::DS:
+ return VK_IMAGE_ASPECT_DEPTH_BIT;
+
+ case tcu::TextureFormat::S:
+ return VK_IMAGE_ASPECT_STENCIL_BIT;
+
+ default:
+ return VK_IMAGE_ASPECT_COLOR_BIT;
+ }
+}
+
+class RenderQuad
+{
+public:
+ RenderQuad (const Vec4& posA, const Vec4& posB)
+ : m_vertices(6)
+ {
+ m_vertices[0] = posA;
+ m_vertices[1] = Vec4(posA[0], posB[1], posA[2], posA[3]);
+ m_vertices[2] = posB;
+
+ m_vertices[3] = posB;
+ m_vertices[4] = Vec4(posB[0], posA[1], posB[2], posA[3]);
+ m_vertices[5] = posA;
+ }
+
+ const Vec4& getCornerA (void) const
+ {
+ return m_vertices[0];
+ }
+
+ const Vec4& getCornerB (void) const
+ {
+ return m_vertices[2];
+ }
+
+ const void* getVertexPointer (void) const
+ {
+ return &m_vertices[0];
+ }
+
+ size_t getVertexDataSize (void) const
+ {
+ return sizeof(Vec4) * m_vertices.size();
+ }
+
+private:
+ vector<Vec4> m_vertices;
+};
+
+class ColorClear
+{
+public:
+ ColorClear (const UVec2& offset,
+ const UVec2& size,
+ const VkClearColorValue& color)
+ : m_offset (offset)
+ , m_size (size)
+ , m_color (color)
+ {
+ }
+
+ const UVec2& getOffset (void) const { return m_offset; }
+ const UVec2& getSize (void) const { return m_size; }
+ const VkClearColorValue& getColor (void) const { return m_color; }
+
+private:
+ UVec2 m_offset;
+ UVec2 m_size;
+ VkClearColorValue m_color;
+};
+
+class DepthStencilClear
+{
+public:
+ DepthStencilClear (const UVec2& offset,
+ const UVec2& size,
+ float depth,
+ deUint32 stencil)
+ : m_offset (offset)
+ , m_size (size)
+ , m_depth (depth)
+ , m_stencil (stencil)
+ {
+ }
+
+ const UVec2& getOffset (void) const { return m_offset; }
+ const UVec2& getSize (void) const { return m_size; }
+ float getDepth (void) const { return m_depth; }
+ deUint32 getStencil (void) const { return m_stencil; }
+
+private:
+ UVec2 m_offset;
+ UVec2 m_size;
+
+ float m_depth;
+ deUint32 m_stencil;
+};
+
+class SubpassRenderInfo
+{
+public:
+ SubpassRenderInfo (const RenderPass& renderPass,
+ deUint32 subpassIndex,
+
+ bool isSecondary_,
+
+ const UVec2& viewportOffset,
+ const UVec2& viewportSize,
+
+ const Maybe<RenderQuad>& renderQuad,
+ const vector<ColorClear>& colorClears,
+ const Maybe<DepthStencilClear>& depthStencilClear)
+ : m_viewportOffset (viewportOffset)
+ , m_viewportSize (viewportSize)
+ , m_subpassIndex (subpassIndex)
+ , m_isSecondary (isSecondary_)
+ , m_flags (renderPass.getSubpasses()[subpassIndex].getFlags())
+ , m_renderQuad (renderQuad)
+ , m_colorClears (colorClears)
+ , m_depthStencilClear (depthStencilClear)
+ , m_colorAttachments (renderPass.getSubpasses()[subpassIndex].getColorAttachments())
+ {
+ for (deUint32 attachmentNdx = 0; attachmentNdx < (deUint32)m_colorAttachments.size(); attachmentNdx++)
+ m_colorAttachmentInfo.push_back(renderPass.getAttachments()[m_colorAttachments[attachmentNdx].getAttachment()]);
+
+ if (renderPass.getSubpasses()[subpassIndex].getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED)
+ {
+ m_depthStencilAttachment = tcu::just(renderPass.getSubpasses()[subpassIndex].getDepthStencilAttachment());
+ m_depthStencilAttachmentInfo = tcu::just(renderPass.getAttachments()[renderPass.getSubpasses()[subpassIndex].getDepthStencilAttachment().getAttachment()]);
+ }
+ }
+
+ const UVec2& getViewportOffset (void) const { return m_viewportOffset; }
+ const UVec2& getViewportSize (void) const { return m_viewportSize; }
+
+ deUint32 getSubpassIndex (void) const { return m_subpassIndex; }
+ bool isSecondary (void) const { return m_isSecondary; }
+
+ const Maybe<RenderQuad>& getRenderQuad (void) const { return m_renderQuad; }
+ const vector<ColorClear>& getColorClears (void) const { return m_colorClears; }
+ const Maybe<DepthStencilClear>& getDepthStencilClear (void) const { return m_depthStencilClear; }
+
+ deUint32 getColorAttachmentCount (void) const { return (deUint32)m_colorAttachments.size(); }
+ VkImageLayout getColorAttachmentLayout (deUint32 attachmentNdx) const { return m_colorAttachments[attachmentNdx].getImageLayout(); }
+ deUint32 getColorAttachmentIndex (deUint32 attachmentNdx) const { return m_colorAttachments[attachmentNdx].getAttachment(); }
+ const Attachment& getColorAttachment (deUint32 attachmentNdx) const { return m_colorAttachmentInfo[attachmentNdx]; }
+ Maybe<VkImageLayout> getDepthStencilAttachmentLayout (void) const { return m_depthStencilAttachment ? tcu::just(m_depthStencilAttachment->getImageLayout()) : tcu::nothing<VkImageLayout>(); }
+ Maybe<deUint32> getDepthStencilAttachmentIndex (void) const { return m_depthStencilAttachment ? tcu::just(m_depthStencilAttachment->getAttachment()) : tcu::nothing<deUint32>(); };
+ const Maybe<Attachment>& getDepthStencilAttachment (void) const { return m_depthStencilAttachmentInfo; }
+ VkSubpassDescriptionFlags getSubpassFlags (void) const { return m_flags; }
+private:
+ UVec2 m_viewportOffset;
+ UVec2 m_viewportSize;
+
+ deUint32 m_subpassIndex;
+ bool m_isSecondary;
+ VkSubpassDescriptionFlags m_flags;
+
+ Maybe<RenderQuad> m_renderQuad;
+ vector<ColorClear> m_colorClears;
+ Maybe<DepthStencilClear> m_depthStencilClear;
+
+ vector<AttachmentReference> m_colorAttachments;
+ vector<Attachment> m_colorAttachmentInfo;
+
+ Maybe<AttachmentReference> m_depthStencilAttachment;
+ Maybe<Attachment> m_depthStencilAttachmentInfo;
+};
+
+Move<VkPipeline> createSubpassPipeline (const DeviceInterface& vk,
+ VkDevice device,
+ VkRenderPass renderPass,
+ VkShaderModule vertexShaderModule,
+ VkShaderModule fragmentShaderModule,
+ VkPipelineLayout pipelineLayout,
+ const SubpassRenderInfo& renderInfo)
+{
+ const VkSpecializationInfo emptyShaderSpecializations =
+ {
+ 0u, // mapEntryCount
+ DE_NULL, // pMap
+ 0u, // dataSize
+ DE_NULL, // pData
+ };
+
+ Maybe<VkSampleCountFlagBits> rasterSamples;
+ vector<VkPipelineColorBlendAttachmentState> attachmentBlendStates;
+
+ for (deUint32 attachmentNdx = 0; attachmentNdx < renderInfo.getColorAttachmentCount(); attachmentNdx++)
+ {
+ const Attachment& attachment = renderInfo.getColorAttachment(attachmentNdx);
+
+ DE_ASSERT(!rasterSamples || *rasterSamples == attachment.getSamples());
+
+ rasterSamples = attachment.getSamples();
+
+ {
+ const VkPipelineColorBlendAttachmentState attachmentBlendState =
+ {
+ VK_FALSE, // blendEnable
+ VK_BLEND_FACTOR_SRC_ALPHA, // srcBlendColor
+ VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, // destBlendColor
+ VK_BLEND_OP_ADD, // blendOpColor
+ VK_BLEND_FACTOR_ONE, // srcBlendAlpha
+ VK_BLEND_FACTOR_ONE, // destBlendAlpha
+ VK_BLEND_OP_ADD, // blendOpAlpha
+ VK_COLOR_COMPONENT_R_BIT|VK_COLOR_COMPONENT_G_BIT|VK_COLOR_COMPONENT_B_BIT|VK_COLOR_COMPONENT_A_BIT, // channelWriteMask
+ };
+
+ attachmentBlendStates.push_back(attachmentBlendState);
+ }
+ }
+
+ if (renderInfo.getDepthStencilAttachment())
+ {
+ const Attachment& attachment = *renderInfo.getDepthStencilAttachment();
+
+ DE_ASSERT(!rasterSamples || *rasterSamples == attachment.getSamples());
+ rasterSamples = attachment.getSamples();
+ }
+
+ // If there are no attachment use single sample
+ if (!rasterSamples)
+ rasterSamples = VK_SAMPLE_COUNT_1_BIT;
+
+ const VkPipelineShaderStageCreateInfo shaderStages[2] =
+ {
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ (VkPipelineShaderStageCreateFlags)0u,
+ VK_SHADER_STAGE_VERTEX_BIT, // stage
+ vertexShaderModule, // shader
+ "main",
+ &emptyShaderSpecializations
+ },
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ (VkPipelineShaderStageCreateFlags)0u,
+ VK_SHADER_STAGE_FRAGMENT_BIT, // stage
+ fragmentShaderModule, // shader
+ "main",
+ &emptyShaderSpecializations
+ }
+ };
+ const VkVertexInputBindingDescription vertexBinding =
+ {
+ 0u, // binding
+ (deUint32)sizeof(tcu::Vec4), // strideInBytes
+ VK_VERTEX_INPUT_RATE_VERTEX, // stepRate
+ };
+ const VkVertexInputAttributeDescription vertexAttrib =
+ {
+ 0u, // location
+ 0u, // binding
+ VK_FORMAT_R32G32B32A32_SFLOAT, // format
+ 0u, // offsetInBytes
+ };
+ const VkPipelineVertexInputStateCreateInfo vertexInputState =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ (VkPipelineVertexInputStateCreateFlags)0u,
+ 1u, // bindingCount
+ &vertexBinding, // pVertexBindingDescriptions
+ 1u, // attributeCount
+ &vertexAttrib, // pVertexAttributeDescriptions
+ };
+ const VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ (VkPipelineInputAssemblyStateCreateFlags)0u,
+ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // topology
+ VK_FALSE, // primitiveRestartEnable
+ };
+ const VkViewport viewport =
+ {
+ (float)renderInfo.getViewportOffset().x(), (float)renderInfo.getViewportOffset().y(),
+ (float)renderInfo.getViewportSize().x(), (float)renderInfo.getViewportSize().y(),
+ 0.0f, 1.0f
+ };
+ const VkRect2D scissor =
+ {
+ { (deInt32)renderInfo.getViewportOffset().x(), (deInt32)renderInfo.getViewportOffset().y() },
+ { (deInt32)renderInfo.getViewportSize().x(), (deInt32)renderInfo.getViewportSize().y() }
+ };
+ const VkPipelineViewportStateCreateInfo viewportState =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
+ DE_NULL,
+ (VkPipelineViewportStateCreateFlags)0u,
+ 1u,
+ &viewport,
+ 1u,
+ &scissor
+ };
+ const VkPipelineRasterizationStateCreateInfo rasterState =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ (VkPipelineRasterizationStateCreateFlags)0u,
+ VK_TRUE, // depthClipEnable
+ VK_FALSE, // rasterizerDiscardEnable
+ VK_POLYGON_MODE_FILL, // fillMode
+ VK_CULL_MODE_NONE, // cullMode
+ VK_FRONT_FACE_COUNTER_CLOCKWISE, // frontFace
+ VK_FALSE, // depthBiasEnable
+ 0.0f, // depthBias
+ 0.0f, // depthBiasClamp
+ 0.0f, // slopeScaledDepthBias
+ 1.0f // lineWidth
+ };
+ const VkPipelineMultisampleStateCreateInfo multisampleState =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ (VkPipelineMultisampleStateCreateFlags)0u,
+ *rasterSamples, // rasterSamples
+ VK_FALSE, // sampleShadingEnable
+ 0.0f, // minSampleShading
+ DE_NULL, // pSampleMask
+ VK_FALSE, // alphaToCoverageEnable
+ VK_FALSE, // alphaToOneEnable
+ };
+ const VkPipelineDepthStencilStateCreateInfo depthStencilState =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ (VkPipelineDepthStencilStateCreateFlags)0u,
+ VK_TRUE, // depthTestEnable
+ VK_TRUE, // depthWriteEnable
+ VK_COMPARE_OP_ALWAYS, // depthCompareOp
+ VK_FALSE, // depthBoundsEnable
+ VK_TRUE, // stencilTestEnable
+ {
+ VK_STENCIL_OP_REPLACE, // stencilFailOp
+ VK_STENCIL_OP_REPLACE, // stencilPassOp
+ VK_STENCIL_OP_REPLACE, // stencilDepthFailOp
+ VK_COMPARE_OP_ALWAYS, // stencilCompareOp
+ ~0u, // stencilCompareMask
+ ~0u, // stencilWriteMask
+ ~0u // stencilReference
+ }, // front
+ {
+ VK_STENCIL_OP_REPLACE, // stencilFailOp
+ VK_STENCIL_OP_REPLACE, // stencilPassOp
+ VK_STENCIL_OP_REPLACE, // stencilDepthFailOp
+ VK_COMPARE_OP_ALWAYS, // stencilCompareOp
+ ~0u, // stencilCompareMask
+ ~0u, // stencilWriteMask
+ ~0u // stencilReference
+ }, // back
+
+ -1.0f, // minDepthBounds;
+ 1.0f // maxDepthBounds;
+ };
+ const VkPipelineColorBlendStateCreateInfo blendState =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ (VkPipelineColorBlendStateCreateFlags)0u,
+ VK_FALSE, // logicOpEnable
+ VK_LOGIC_OP_COPY, // logicOp
+ (deUint32)attachmentBlendStates.size(), // attachmentCount
+ attachmentBlendStates.empty() ? DE_NULL : &attachmentBlendStates[0],// pAttachments
+ { 0.0f, 0.0f, 0.0f, 0.0f } // blendConst
+ };
+ const VkPipelineDynamicStateCreateInfo dynamicState =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
+ DE_NULL,
+ (VkPipelineDynamicStateCreateFlags)0u,
+ 0,
+ DE_NULL
+ };
+ const VkGraphicsPipelineCreateInfo createInfo =
+ {
+ VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ (VkPipelineCreateFlags)0u,
+
+ 2, // stageCount
+ shaderStages, // pStages
+
+ &vertexInputState, // pVertexInputState
+ &inputAssemblyState, // pInputAssemblyState
+ DE_NULL, // pTessellationState
+ &viewportState, // pViewportState
+ &rasterState, // pRasterState
+ &multisampleState, // pMultisampleState
+ &depthStencilState, // pDepthStencilState
+ &blendState, // pColorBlendState
+ &dynamicState, // pDynamicState
+ pipelineLayout, // layout
+
+ renderPass, // renderPass
+ renderInfo.getSubpassIndex(), // subpass
+ DE_NULL, // basePipelineHandle
+ 0u // basePipelineIndex
+ };
+
+ return createGraphicsPipeline(vk, device, DE_NULL, &createInfo);
+}
+
+class SubpassRenderer
+{
+public:
+ SubpassRenderer (Context& context,
+ const DeviceInterface& vk,
+ VkDevice device,
+ Allocator& allocator,
+ VkRenderPass renderPass,
+ VkFramebuffer framebuffer,
+ VkCommandPool commandBufferPool,
+ deUint32 queueFamilyIndex,
+ const SubpassRenderInfo& renderInfo)
+ : m_renderInfo (renderInfo)
+ {
+ const deUint32 subpassIndex = renderInfo.getSubpassIndex();
+
+ if (renderInfo.getRenderQuad())
+ {
+ const RenderQuad& renderQuad = *renderInfo.getRenderQuad();
+ const VkPipelineLayoutCreateInfo pipelineLayoutParams =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType;
+ DE_NULL, // pNext;
+ (vk::VkPipelineLayoutCreateFlags)0,
+ 0u, // descriptorSetCount;
+ DE_NULL, // pSetLayouts;
+ 0u, // pushConstantRangeCount;
+ DE_NULL, // pPushConstantRanges;
+ };
+
+ m_vertexShaderModule = createShaderModule(vk, device, context.getBinaryCollection().get(de::toString(subpassIndex) + "-vert"), 0u);
+ m_fragmentShaderModule = createShaderModule(vk, device, context.getBinaryCollection().get(de::toString(subpassIndex) + "-frag"), 0u);
+ m_pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutParams);
+ m_pipeline = createSubpassPipeline(vk, device, renderPass, *m_vertexShaderModule, *m_fragmentShaderModule, *m_pipelineLayout, m_renderInfo);
+
+ m_vertexBuffer = createBuffer(vk, device, 0u, (VkDeviceSize)renderQuad.getVertexDataSize(), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_SHARING_MODE_EXCLUSIVE, 1u, &queueFamilyIndex);
+ m_vertexBufferMemory = allocator.allocate(getBufferMemoryRequirements(vk, device, *m_vertexBuffer), MemoryRequirement::HostVisible);
+
+ bindBufferMemory(vk, device, *m_vertexBuffer, m_vertexBufferMemory->getMemory(), m_vertexBufferMemory->getOffset());
+ uploadBufferData(vk, device, *m_vertexBufferMemory, renderQuad.getVertexDataSize(), renderQuad.getVertexPointer());
+ }
+
+ if (renderInfo.isSecondary())
+ {
+ m_commandBuffer = allocateCommandBuffer(vk, device, commandBufferPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
+
+ beginCommandBuffer(vk, *m_commandBuffer, vk::VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, renderPass, subpassIndex, framebuffer, VK_FALSE, (VkQueryControlFlags)0, (VkQueryPipelineStatisticFlags)0);
+ pushRenderCommands(vk, *m_commandBuffer);
+ endCommandBuffer(vk, *m_commandBuffer);
+ }
+ }
+
+ bool isSecondary (void) const
+ {
+ return m_commandBuffer;
+ }
+
+ VkCommandBuffer getCommandBuffer (void) const
+ {
+ DE_ASSERT(isSecondary());
+ return *m_commandBuffer;
+ }
+
+ void pushRenderCommands (const DeviceInterface& vk,
+ VkCommandBuffer commandBuffer)
+ {
+ if (!m_renderInfo.getColorClears().empty())
+ {
+ const vector<ColorClear>& colorClears (m_renderInfo.getColorClears());
+
+ for (deUint32 attachmentNdx = 0; attachmentNdx < m_renderInfo.getColorAttachmentCount(); attachmentNdx++)
+ {
+ const ColorClear& colorClear = colorClears[attachmentNdx];
+ const VkClearAttachment attachment =
+ {
+ VK_IMAGE_ASPECT_COLOR_BIT,
+ attachmentNdx,
+ makeClearValue(colorClear.getColor()),
+ };
+ const VkClearRect rect =
+ {
+ {
+ { (deInt32)colorClear.getOffset().x(), (deInt32)colorClear.getOffset().y() },
+ { (deInt32)colorClear.getSize().x(), (deInt32)colorClear.getSize().y() }
+ }, // rect
+ 0u, // baseArrayLayer
+ 1u, // layerCount
+ };
+
+ vk.cmdClearAttachments(commandBuffer, 1u, &attachment, 1u, &rect);
+ }
+ }
+
+ if (m_renderInfo.getDepthStencilClear())
+ {
+ const DepthStencilClear& depthStencilClear = *m_renderInfo.getDepthStencilClear();
+ const deUint32 attachmentNdx = m_renderInfo.getColorAttachmentCount();
+ const VkClearAttachment attachment =
+ {
+ VK_IMAGE_ASPECT_DEPTH_BIT|VK_IMAGE_ASPECT_STENCIL_BIT,
+ attachmentNdx,
+ makeClearValueDepthStencil(depthStencilClear.getDepth(), depthStencilClear.getStencil())
+ };
+ const VkClearRect rect =
+ {
+ {
+ { (deInt32)depthStencilClear.getOffset().x(), (deInt32)depthStencilClear.getOffset().y() },
+ { (deInt32)depthStencilClear.getSize().x(), (deInt32)depthStencilClear.getSize().y() }
+ }, // rect
+ 0u, // baseArrayLayer
+ 1u, // layerCount
+ };
+
+ vk.cmdClearAttachments(commandBuffer, 1u, &attachment, 1u, &rect);
+ }
+
+ if (m_renderInfo.getRenderQuad())
+ {
+ const VkDeviceSize offset = 0;
+ const VkBuffer vertexBuffer = *m_vertexBuffer;
+
+ vk.cmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
+ vk.cmdBindVertexBuffers(commandBuffer, 0u, 1u, &vertexBuffer, &offset);
+ vk.cmdDraw(commandBuffer, 6u, 1u, 0u, 0u);
+ }
+ }
+
+private:
+ const SubpassRenderInfo m_renderInfo;
+ Move<VkCommandBuffer> m_commandBuffer;
+ Move<VkPipeline> m_pipeline;
+ Move<VkPipelineLayout> m_pipelineLayout;
+
+ Move<VkShaderModule> m_vertexShaderModule;
+
+ Move<VkShaderModule> m_fragmentShaderModule;
+
+ Move<VkBuffer> m_vertexBuffer;
+ de::MovePtr<Allocation> m_vertexBufferMemory;
+};
+
+void pushImageInitializationCommands (const DeviceInterface& vk,
+ VkCommandBuffer commandBuffer,
+ const vector<Attachment>& attachmentInfo,
+ const vector<de::SharedPtr<AttachmentResources> >& attachmentResources,
+ deUint32 queueIndex,
+ const vector<Maybe<VkClearValue> >& clearValues)
+{
+ {
+ vector<VkImageMemoryBarrier> initializeLayouts;
+
+ for (size_t attachmentNdx = 0; attachmentNdx < attachmentInfo.size(); attachmentNdx++)
+ {
+ if (!clearValues[attachmentNdx])
+ continue;
+
+ const VkImageMemoryBarrier barrier =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType;
+ DE_NULL, // pNext;
+
+ getAllMemoryWriteFlags(), // srcAccessMask
+ getAllMemoryReadFlags(), // dstAccessMask
+
+ VK_IMAGE_LAYOUT_UNDEFINED, // oldLayout
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // newLayout;
+
+ queueIndex, // srcQueueFamilyIndex;
+ queueIndex, // destQueueFamilyIndex;
+
+ attachmentResources[attachmentNdx]->getImage(), // image;
+ { // subresourceRange;
+ getImageAspectFlags(attachmentInfo[attachmentNdx].getFormat()), // aspect;
+ 0, // baseMipLevel;
+ 1, // mipLevels;
+ 0, // baseArraySlice;
+ 1 // arraySize;
+ }
+ };
+
+ initializeLayouts.push_back(barrier);
+ }
+
+ if (!initializeLayouts.empty())
+ {
+ vector<VkImageMemoryBarrier*> initializeLayoutPtrs;
+
+ for (size_t ndx = 0; ndx < initializeLayouts.size(); ndx++)
+ initializeLayoutPtrs.push_back(&initializeLayouts[ndx]);
+
+ vk.cmdPipelineBarrier(commandBuffer, 0, 0, VK_FALSE, (deUint32)initializeLayouts.size(), (const void* const*)&initializeLayoutPtrs[0]);
+ }
+ }
+
+ for (size_t attachmentNdx = 0; attachmentNdx < attachmentInfo.size(); attachmentNdx++)
+ {
+ if (!clearValues[attachmentNdx])
+ continue;
+
+ const tcu::TextureFormat format = mapVkFormat(attachmentInfo[attachmentNdx].getFormat());
+
+ if (hasStencilComponent(format.order) || hasDepthComponent(format.order))
+ {
+ const float clearNan = tcu::Float32::nan().asFloat();
+ const float clearDepth = hasDepthComponent(format.order) ? clearValues[attachmentNdx]->depthStencil.depth : clearNan;
+ const deUint32 clearStencil = hasStencilComponent(format.order) ? clearValues[attachmentNdx]->depthStencil.stencil : ~0u;
+ const VkClearDepthStencilValue depthStencil =
+ {
+ clearDepth,
+ clearStencil
+ };
+ const VkImageSubresourceRange range =
+ {
+ (VkImageAspectFlags)(hasDepthComponent(format.order) ? VK_IMAGE_ASPECT_DEPTH_BIT : 0
+ | hasStencilComponent(format.order) ? VK_IMAGE_ASPECT_STENCIL_BIT : 0),
+ 0,
+ 1,
+ 0,
+ 1
+ };
+
+ vk.cmdClearDepthStencilImage(commandBuffer, attachmentResources[attachmentNdx]->getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &depthStencil, 1, &range);
+ }
+ else
+ {
+ const VkImageSubresourceRange range =
+ {
+ VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask;
+ 0, // baseMipLevel;
+ 1, // mipLevels;
+ 0, // baseArrayLayer;
+ 1 // layerCount;
+ };
+ const VkClearColorValue clearColor = clearValues[attachmentNdx]->color;
+
+ vk.cmdClearColorImage(commandBuffer, attachmentResources[attachmentNdx]->getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor, 1, &range);
+ }
+ }
+
+ {
+ vector<VkImageMemoryBarrier> renderPassLayouts;
+
+ for (size_t attachmentNdx = 0; attachmentNdx < attachmentInfo.size(); attachmentNdx++)
+ {
+ const VkImageMemoryBarrier barrier =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType;
+ DE_NULL, // pNext;
+
+ getAllMemoryWriteFlags(), // srcAccessMask
+ getAllMemoryReadFlags(), // dstAccessMask
+
+ clearValues[attachmentNdx] ?
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
+ : VK_IMAGE_LAYOUT_UNDEFINED, // oldLayout
+
+ attachmentInfo[attachmentNdx].getInitialLayout(), // newLayout;
+
+ queueIndex, // srcQueueFamilyIndex;
+ queueIndex, // destQueueFamilyIndex;
+
+ attachmentResources[attachmentNdx]->getImage(), // image;
+ { // subresourceRange;
+ getImageAspectFlags(attachmentInfo[attachmentNdx].getFormat()), // aspect;
+ 0, // baseMipLevel;
+ 1, // mipLevels;
+ 0, // baseArraySlice;
+ 1 // arraySize;
+ }
+ };
+
+ renderPassLayouts.push_back(barrier);
+ }
+
+ if (!renderPassLayouts.empty())
+ {
+ vector<VkImageMemoryBarrier*> renderPassLayoutPtrs;
+
+ for (size_t ndx = 0; ndx < renderPassLayouts.size(); ndx++)
+ renderPassLayoutPtrs.push_back(&renderPassLayouts[ndx]);
+
+ vk.cmdPipelineBarrier(commandBuffer, 0, 0, VK_FALSE, (deUint32)renderPassLayouts.size(), (const void* const*)&renderPassLayoutPtrs[0]);
+ }
+ }
+}
+
+void pushRenderPassCommands (const DeviceInterface& vk,
+ VkCommandBuffer commandBuffer,
+ VkRenderPass renderPass,
+ VkFramebuffer framebuffer,
+ const vector<de::SharedPtr<SubpassRenderer> >& subpassRenderers,
+ const UVec2& renderPos,
+ const UVec2& renderSize,
+ const vector<Maybe<VkClearValue> >& renderPassClearValues,
+ TestConfig::RenderTypes render)
+{
+ const float clearNan = tcu::Float32::nan().asFloat();
+ vector<VkClearValue> attachmentClearValues;
+
+ for (size_t attachmentNdx = 0; attachmentNdx < renderPassClearValues.size(); attachmentNdx++)
+ {
+ if (renderPassClearValues[attachmentNdx])
+ attachmentClearValues.push_back(*renderPassClearValues[attachmentNdx]);
+ else
+ attachmentClearValues.push_back(makeClearValueColorF32(clearNan, clearNan, clearNan, clearNan));
+ }
+
+ {
+ const VkRect2D renderArea =
+ {
+ { (deInt32)renderPos.x(), (deInt32)renderPos.y() },
+ { (deInt32)renderSize.x(), (deInt32)renderSize.y() }
+ };
+
+ for (size_t subpassNdx = 0; subpassNdx < subpassRenderers.size(); subpassNdx++)
+ {
+ const VkSubpassContents contents = subpassRenderers[subpassNdx]->isSecondary() ? VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS : VK_SUBPASS_CONTENTS_INLINE;
+
+ if (subpassNdx == 0)
+ cmdBeginRenderPass(vk, commandBuffer, renderPass, framebuffer, renderArea, (deUint32)attachmentClearValues.size(), attachmentClearValues.empty() ? DE_NULL : &attachmentClearValues[0], contents);
+ else
+ vk.cmdNextSubpass(commandBuffer, contents);
+
+ if (render)
+ {
+ if (contents == VK_SUBPASS_CONTENTS_INLINE)
+ {
+ subpassRenderers[subpassNdx]->pushRenderCommands(vk, commandBuffer);
+ }
+ else if (contents == VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS)
+ {
+ const VkCommandBuffer cmd = subpassRenderers[subpassNdx]->getCommandBuffer();
+ vk.cmdExecuteCommands(commandBuffer, 1, &cmd);
+ }
+ else
+ DE_FATAL("Invalid contents");
+ }
+ }
+
+ vk.cmdEndRenderPass(commandBuffer);
+ }
+}
+
+void pushReadImagesToBuffers (const DeviceInterface& vk,
+ VkCommandBuffer commandBuffer,
+ deUint32 queueIndex,
+
+ const vector<de::SharedPtr<AttachmentResources> >& attachmentResources,
+ const vector<Attachment>& attachmentInfo,
+ const vector<bool>& isLazy,
+
+ const UVec2& targetSize)
+{
+ {
+ vector<VkImageMemoryBarrier> imageBarriers;
+
+ for (size_t attachmentNdx = 0; attachmentNdx < attachmentInfo.size(); attachmentNdx++)
+ {
+ if (isLazy[attachmentNdx])
+ continue;
+
+ const VkImageMemoryBarrier barrier =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
+ DE_NULL, // pNext
+
+ getAllMemoryWriteFlags(), // srcAccessMask
+ getAllMemoryReadFlags(), // dstAccessMask
+
+ attachmentInfo[attachmentNdx].getFinalLayout(), // oldLayout
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // newLayout
+
+ queueIndex, // srcQueueFamilyIndex
+ queueIndex, // destQueueFamilyIndex
+
+ attachmentResources[attachmentNdx]->getImage(), // image
+ { // subresourceRange
+ getImageAspectFlags(attachmentInfo[attachmentNdx].getFormat()), // aspect;
+ 0, // baseMipLevel
+ 1, // mipLevels
+ 0, // baseArraySlice
+ 1 // arraySize
+ }
+ };
+
+ imageBarriers.push_back(barrier);
+ }
+
+ if (!imageBarriers.empty())
+ {
+ vector<VkImageMemoryBarrier*> clearLayoutPtrs;
+
+ for (size_t ndx = 0; ndx < imageBarriers.size(); ndx++)
+ clearLayoutPtrs.push_back(&imageBarriers[ndx]);
+
+ vk.cmdPipelineBarrier(commandBuffer, getAllPipelineStageFlags(),
+ getAllPipelineStageFlags(),
+ VK_FALSE, (deUint32)imageBarriers.size(), (const void* const*)&clearLayoutPtrs[0]);
+ }
+ }
+
+ for (size_t attachmentNdx = 0; attachmentNdx < attachmentInfo.size(); attachmentNdx++)
+ {
+ if (isLazy[attachmentNdx])
+ continue;
+
+ const tcu::TextureFormat::ChannelOrder order = mapVkFormat(attachmentInfo[attachmentNdx].getFormat()).order;
+ const VkBufferImageCopy rect =
+ {
+ 0, // bufferOffset
+ 0, // bufferRowLength
+ 0, // bufferImageHeight
+ { // imageSubresource
+ getPrimaryImageAspect(mapVkFormat(attachmentInfo[attachmentNdx].getFormat()).order), // aspect
+ 0, // mipLevel
+ 0, // arraySlice
+ 1 // arraySize
+ },
+ { 0, 0, 0 }, // imageOffset
+ { (deInt32)targetSize.x(), (deInt32)targetSize.y(), 1 } // imageExtent
+ };
+
+ vk.cmdCopyImageToBuffer(commandBuffer, attachmentResources[attachmentNdx]->getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, attachmentResources[attachmentNdx]->getBuffer(), 1, &rect);
+
+ if (tcu::TextureFormat::DS == order)
+ {
+ const VkBufferImageCopy stencilRect =
+ {
+ 0, // bufferOffset
+ 0, // bufferRowLength
+ 0, // bufferImageHeight
+ { // imageSubresource
+ VK_IMAGE_ASPECT_STENCIL_BIT, // aspect
+ 0, // mipLevel
+ 0, // arraySlice
+ 1 // arraySize
+ },
+ { 0, 0, 0 }, // imageOffset
+ { (deInt32)targetSize.x(), (deInt32)targetSize.y(), 1 } // imageExtent
+ };
+
+ vk.cmdCopyImageToBuffer(commandBuffer, attachmentResources[attachmentNdx]->getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, attachmentResources[attachmentNdx]->getSecondaryBuffer(), 1, &stencilRect);
+ }
+ }
+
+ {
+ vector<VkBufferMemoryBarrier> bufferBarriers;
+
+ for (size_t attachmentNdx = 0; attachmentNdx < attachmentInfo.size(); attachmentNdx++)
+ {
+ if (isLazy[attachmentNdx])
+ continue;
+
+ const tcu::TextureFormat::ChannelOrder order = mapVkFormat(attachmentInfo[attachmentNdx].getFormat()).order;
+ const VkBufferMemoryBarrier bufferBarrier =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
+ DE_NULL,
+
+ getAllMemoryWriteFlags(),
+ getAllMemoryReadFlags(),
+
+ queueIndex,
+ queueIndex,
+
+ attachmentResources[attachmentNdx]->getBuffer(),
+ 0,
+ attachmentResources[attachmentNdx]->getBufferSize()
+ };
+
+ bufferBarriers.push_back(bufferBarrier);
+
+ if (tcu::TextureFormat::DS == order)
+ {
+ const VkBufferMemoryBarrier secondaryBufferBarrier =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
+ DE_NULL,
+
+ getAllMemoryWriteFlags(),
+ getAllMemoryReadFlags(),
+
+ queueIndex,
+ queueIndex,
+
+ attachmentResources[attachmentNdx]->getSecondaryBuffer(),
+ 0,
+ attachmentResources[attachmentNdx]->getSecondaryBufferSize()
+ };
+
+ bufferBarriers.push_back(secondaryBufferBarrier);
+ }
+
+ bufferBarriers.push_back(bufferBarrier);
+ }
+
+ if (!bufferBarriers.empty())
+ {
+ vector<VkBufferMemoryBarrier*> clearLayoutPtrs;
+
+ for (size_t ndx = 0; ndx < bufferBarriers.size(); ndx++)
+ clearLayoutPtrs.push_back(&bufferBarriers[ndx]);
+
+ vk.cmdPipelineBarrier(commandBuffer, getAllPipelineStageFlags(),
+ getAllPipelineStageFlags(),
+ VK_FALSE, (deUint32)bufferBarriers.size(), (const void* const*)&clearLayoutPtrs[0]);
+ }
+ }
+}
+
+void clear (const PixelBufferAccess& access, const VkClearValue& value)
+{
+ const tcu::TextureFormat& format = access.getFormat();
+
+ if (tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order))
+ {
+ if (tcu::hasDepthComponent(format.order))
+ tcu::clearDepth(access, value.depthStencil.depth);
+
+ if (tcu::hasStencilComponent(format.order))
+ tcu::clearStencil(access, value.depthStencil.stencil);
+ }
+ else
+ {
+ if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_FLOATING_POINT
+ || tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT
+ || tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT)
+ {
+ const tcu::Vec4 color (value.color.float32[0],
+ value.color.float32[1],
+ value.color.float32[2],
+ value.color.float32[3]);
+
+ if (tcu::isSRGB(format))
+ tcu::clear(access, tcu::linearToSRGB(color));
+ else
+ tcu::clear(access, color);
+ }
+ else if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
+ {
+ const tcu::UVec4 color (value.color.uint32[0],
+ value.color.uint32[1],
+ value.color.uint32[2],
+ value.color.uint32[3]);
+
+ tcu::clear(access, color);
+ }
+ else if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
+ {
+ const tcu::IVec4 color (value.color.int32[0],
+ value.color.int32[1],
+ value.color.int32[2],
+ value.color.int32[3]);
+
+ tcu::clear(access, color);
+ }
+ else
+ DE_FATAL("Unknown channel class");
+ }
+}
+
+Vec4 computeUvs (const IVec2& posA, const IVec2& posB, const IVec2& pos)
+{
+ const float u = de::clamp((float)(pos.x() - posA.x()) / (float)(posB.x() - posA.x()), 0.0f, 1.0f);
+ const float v = de::clamp((float)(pos.y() - posA.y()) / (float)(posB.y() - posA.y()), 0.0f, 1.0f);
+
+ return Vec4(u, v, u * v, (u + v) / 2.0f);
+}
+
+void renderReferenceImages (vector<tcu::TextureLevel>& referenceAttachments,
+ const RenderPass& renderPassInfo,
+ const UVec2& targetSize,
+ const vector<Maybe<VkClearValue> >& imageClearValues,
+ const vector<Maybe<VkClearValue> >& renderPassClearValues,
+ const vector<SubpassRenderInfo>& subpassRenderInfo,
+ const UVec2& renderPos,
+ const UVec2& renderSize)
+{
+ const vector<Subpass>& subpasses = renderPassInfo.getSubpasses();
+ vector<bool> attachmentUsed (renderPassInfo.getAttachments().size(), false);
+
+ referenceAttachments.resize(renderPassInfo.getAttachments().size());
+
+ for (size_t attachmentNdx = 0; attachmentNdx < renderPassInfo.getAttachments().size(); attachmentNdx++)
+ {
+ const Attachment attachment = renderPassInfo.getAttachments()[attachmentNdx];
+ const tcu::TextureFormat format = mapVkFormat(attachment.getFormat());
+ const tcu::TextureFormatInfo textureInfo = tcu::getTextureFormatInfo(format);
+ tcu::TextureLevel& reference = referenceAttachments[attachmentNdx];
+ const bool isDepthOrStencilAttachment = hasDepthComponent(format.order) || hasStencilComponent(format.order);
+
+ reference = tcu::TextureLevel(format, targetSize.x(), targetSize.y());
+
+ if (imageClearValues[attachmentNdx])
+ clear(reference.getAccess(), *imageClearValues[attachmentNdx]);
+ else
+ {
+ // Fill with grid if image contentst are undefined before renderpass
+ if (isDepthOrStencilAttachment)
+ {
+ if (tcu::hasDepthComponent(format.order))
+ tcu::fillWithGrid(tcu::getEffectiveDepthStencilAccess(reference.getAccess(), tcu::Sampler::MODE_DEPTH), 2, textureInfo.valueMin, textureInfo.valueMax);
+
+ if (tcu::hasStencilComponent(format.order))
+ tcu::fillWithGrid(tcu::getEffectiveDepthStencilAccess(reference.getAccess(), tcu::Sampler::MODE_STENCIL), 2, textureInfo.valueMin, textureInfo.valueMax);
+ }
+ else
+ tcu::fillWithGrid(reference.getAccess(), 2, textureInfo.valueMin, textureInfo.valueMax);
+ }
+ }
+
+ for (size_t subpassNdx = 0; subpassNdx < subpasses.size(); subpassNdx++)
+ {
+ const Subpass& subpass = subpasses[subpassNdx];
+ const SubpassRenderInfo& renderInfo = subpassRenderInfo[subpassNdx];
+ const vector<AttachmentReference>& colorAttachments = subpass.getColorAttachments();
+
+ // Apply load op if attachment was used for the first time
+ for (size_t attachmentNdx = 0; attachmentNdx < colorAttachments.size(); attachmentNdx++)
+ {
+ const deUint32 attachmentIndex = colorAttachments[attachmentNdx].getAttachment();
+
+ if (!attachmentUsed[attachmentIndex])
+ {
+ const Attachment& attachment = renderPassInfo.getAttachments()[attachmentIndex];
+ tcu::TextureLevel& reference = referenceAttachments[attachmentIndex];
+
+ DE_ASSERT(!tcu::hasDepthComponent(reference.getFormat().order));
+ DE_ASSERT(!tcu::hasStencilComponent(reference.getFormat().order));
+
+ if (attachment.getLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR)
+ clear(tcu::getSubregion(reference.getAccess(), renderPos.x(), renderPos.y(), renderSize.x(), renderSize.y()), *renderPassClearValues[attachmentIndex]);
+ else if (attachment.getLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE)
+ {
+ const tcu::TextureFormatInfo textureInfo = tcu::getTextureFormatInfo(reference.getFormat());
+
+ tcu::fillWithGrid(tcu::getSubregion(reference.getAccess(), renderPos.x(), renderPos.y(), renderSize.x(), renderSize.y()), 2, textureInfo.valueMin, textureInfo.valueMax);
+ }
+
+ attachmentUsed[attachmentIndex] = true;
+ }
+ }
+
+ // Apply load op to depth/stencil attachment if it was used for the first time
+ if (subpass.getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED && !attachmentUsed[subpass.getDepthStencilAttachment().getAttachment()])
+ {
+ const deUint32 attachmentIndex = subpass.getDepthStencilAttachment().getAttachment();
+
+ // Apply load op if attachment was used for the first time
+ if (!attachmentUsed[attachmentIndex])
+ {
+ const Attachment& attachment = renderPassInfo.getAttachments()[attachmentIndex];
+ tcu::TextureLevel& reference = referenceAttachments[attachmentIndex];
+
+ if (tcu::hasDepthComponent(reference.getFormat().order))
+ {
+ if (attachment.getLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR)
+ clear(tcu::getSubregion(tcu::getEffectiveDepthStencilAccess(reference.getAccess(), tcu::Sampler::MODE_DEPTH), renderPos.x(), renderPos.y(), renderSize.x(), renderSize.y()), *renderPassClearValues[attachmentIndex]);
+ else if (attachment.getLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE)
+ {
+ const tcu::TextureFormatInfo textureInfo = tcu::getTextureFormatInfo(reference.getFormat());
+
+ tcu::fillWithGrid(tcu::getSubregion(tcu::getEffectiveDepthStencilAccess(reference.getAccess(), tcu::Sampler::MODE_DEPTH), renderPos.x(), renderPos.y(), renderSize.x(), renderSize.y()), 2, textureInfo.valueMin, textureInfo.valueMax);
+ }
+ }
+
+ if (tcu::hasStencilComponent(reference.getFormat().order))
+ {
+ if (attachment.getStencilLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR)
+ clear(tcu::getSubregion(tcu::getEffectiveDepthStencilAccess(reference.getAccess(), tcu::Sampler::MODE_STENCIL), renderPos.x(), renderPos.y(), renderSize.x(), renderSize.y()), *renderPassClearValues[attachmentIndex]);
+ else if (attachment.getStencilLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE)
+ {
+ const tcu::TextureFormatInfo textureInfo = tcu::getTextureFormatInfo(reference.getFormat());
+
+ tcu::fillWithGrid(tcu::getSubregion(tcu::getEffectiveDepthStencilAccess(reference.getAccess(), tcu::Sampler::MODE_STENCIL), renderPos.x(), renderPos.y(), renderSize.x(), renderSize.y()), 2, textureInfo.valueMin, textureInfo.valueMax);
+ }
+ }
+ }
+
+ attachmentUsed[attachmentIndex] = true;
+ }
+
+ for (size_t colorClearNdx = 0; colorClearNdx < renderInfo.getColorClears().size(); colorClearNdx++)
+ {
+ const ColorClear& colorClear = renderInfo.getColorClears()[colorClearNdx];
+ const UVec2 offset = colorClear.getOffset();
+ const UVec2 size = colorClear.getSize();
+ tcu::TextureLevel& reference = referenceAttachments[subpass.getColorAttachments()[colorClearNdx].getAttachment()];
+ VkClearValue value;
+
+ value.color = colorClear.getColor();
+
+ clear(tcu::getSubregion(reference.getAccess(), offset.x(), offset.y(), 0, size.x(), size.y(), 1), value);
+ }
+
+ if (renderInfo.getDepthStencilClear())
+ {
+ const DepthStencilClear& dsClear = *renderInfo.getDepthStencilClear();
+ const UVec2 offset = dsClear.getOffset();
+ const UVec2 size = dsClear.getSize();
+ tcu::TextureLevel& reference = referenceAttachments[subpass.getDepthStencilAttachment().getAttachment()];
+
+ if (tcu::hasDepthComponent(reference.getFormat().order))
+ clearDepth(tcu::getSubregion(reference.getAccess(), offset.x(), offset.y(), 0, size.x(), size.y(), 1), dsClear.getDepth());
+
+ if (tcu::hasStencilComponent(reference.getFormat().order))
+ clearStencil(tcu::getSubregion(reference.getAccess(), offset.x(), offset.y(), 0, size.x(), size.y(), 1), dsClear.getStencil());
+ }
+
+ if (renderInfo.getRenderQuad())
+ {
+ const RenderQuad& renderQuad = *renderInfo.getRenderQuad();
+ const Vec4 posA = renderQuad.getCornerA();
+ const Vec4 posB = renderQuad.getCornerB();
+ const Vec2 origin = Vec2((float)renderInfo.getViewportOffset().x(), (float)renderInfo.getViewportOffset().y()) + Vec2((float)renderInfo.getViewportSize().x(), (float)renderInfo.getViewportSize().y()) / Vec2(2.0f);
+ const Vec2 p = Vec2((float)renderInfo.getViewportSize().x(), (float)renderInfo.getViewportSize().y()) / Vec2(2.0f);
+ const IVec2 posAI ((deInt32)(origin.x() + (p.x() * posA.x())),
+ (deInt32)(origin.y() + (p.y() * posA.y())));
+ const IVec2 posBI ((deInt32)(origin.x() + (p.x() * posB.x())),
+ (deInt32)(origin.y() + (p.y() * posB.y())));
+
+ for (size_t attachmentRefNdx = 0; attachmentRefNdx < subpass.getColorAttachments().size(); attachmentRefNdx++)
+ {
+ const Attachment attachment = renderPassInfo.getAttachments()[subpass.getColorAttachments()[attachmentRefNdx].getAttachment()];
+ const tcu::TextureFormatInfo textureInfo = tcu::getTextureFormatInfo(mapVkFormat(attachment.getFormat()));
+ tcu::TextureLevel& referenceTexture = referenceAttachments[subpass.getColorAttachments()[attachmentRefNdx].getAttachment()];
+ const bool srgb = tcu::isSRGB(referenceTexture.getFormat());
+ const PixelBufferAccess reference = referenceTexture.getAccess();
+ const float clampMin = (float)(-MAX_INTEGER_VALUE);
+ const float clampMax = (float)(MAX_INTEGER_VALUE);
+ const Vec4 valueMax (de::clamp(textureInfo.valueMax[0], clampMin, clampMax),
+ de::clamp(textureInfo.valueMax[1], clampMin, clampMax),
+ de::clamp(textureInfo.valueMax[2], clampMin, clampMax),
+ de::clamp(textureInfo.valueMax[3], clampMin, clampMax));
+
+ const Vec4 valueMin (de::clamp(textureInfo.valueMin[0], clampMin, clampMax),
+ de::clamp(textureInfo.valueMin[1], clampMin, clampMax),
+ de::clamp(textureInfo.valueMin[2], clampMin, clampMax),
+ de::clamp(textureInfo.valueMin[3], clampMin, clampMax));
+
+ DE_ASSERT(posAI.x() < posBI.x());
+ DE_ASSERT(posAI.y() < posBI.y());
+
+ for (int y = posAI.y(); y <= (int)posBI.y(); y++)
+ for (int x = posAI.x(); x <= (int)posBI.x(); x++)
+ {
+ const Vec4 uvs = computeUvs(posAI, posBI, IVec2(x, y));
+ const Vec4 color = valueMax * uvs + valueMin * (Vec4(1.0f) - uvs);
+
+ if (srgb)
+ reference.setPixel(tcu::linearToSRGB(color), x, y);
+ else
+ reference.setPixel(color, x, y);
+ }
+ }
+
+ if (subpass.getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED)
+ {
+ tcu::TextureLevel& referenceTexture = referenceAttachments[subpass.getDepthStencilAttachment().getAttachment()];
+ const PixelBufferAccess reference = referenceTexture.getAccess();
+
+ DE_ASSERT(posAI.x() < posBI.x());
+ DE_ASSERT(posAI.y() < posBI.y());
+
+ for (int y = posAI.y(); y <= (int)posBI.y(); y++)
+ for (int x = posAI.x(); x <= (int)posBI.x(); x++)
+ {
+ const Vec4 uvs = computeUvs(posAI, posBI, IVec2(x, y));
+
+ if (tcu::hasDepthComponent(reference.getFormat().order))
+ reference.setPixDepth(uvs.x(), x, y);
+
+ if (tcu::hasStencilComponent(reference.getFormat().order))
+ reference.setPixStencil(STENCIL_VALUE, x, y);
+ }
+ }
+ }
+ }
+
+ // Mark all attachments that were used but not stored as undefined
+ for (size_t attachmentNdx = 0; attachmentNdx < renderPassInfo.getAttachments().size(); attachmentNdx++)
+ {
+ const Attachment attachment = renderPassInfo.getAttachments()[attachmentNdx];
+ const tcu::TextureFormat format = mapVkFormat(attachment.getFormat());
+ const tcu::TextureFormatInfo textureInfo = tcu::getTextureFormatInfo(format);
+ tcu::TextureLevel& reference = referenceAttachments[attachmentNdx];
+
+ if (attachmentUsed[attachmentNdx] && renderPassInfo.getAttachments()[attachmentNdx].getStoreOp() == VK_ATTACHMENT_STORE_OP_DONT_CARE)
+ tcu::fillWithGrid(tcu::getSubregion(reference.getAccess(), renderPos.x(), renderPos.y(), renderSize.x(), renderSize.y()), 2, textureInfo.valueMin, textureInfo.valueMax);
+ }
+}
+
+Maybe<deUint32> findColorAttachment (const Subpass& subpass,
+ deUint32 attachmentIndex)
+{
+ for (size_t colorAttachmentNdx = 0; colorAttachmentNdx < subpass.getColorAttachments().size(); colorAttachmentNdx++)
+ {
+ if (subpass.getColorAttachments()[colorAttachmentNdx].getAttachment() == attachmentIndex)
+ return tcu::just((deUint32)colorAttachmentNdx);
+ }
+
+ return tcu::nothing<deUint32>();
+}
+
+int calcFloatDiff (float a, float b)
+{
+ const deUint32 au = tcu::Float32(a).bits();
+ const deUint32 bu = tcu::Float32(b).bits();
+
+ const bool asign = (au & (0x1u << 31u)) != 0u;
+ const bool bsign = (bu & (0x1u << 31u)) != 0u;
+
+ const deUint32 avalue = (au & ((0x1u << 31u) - 1u));
+ const deUint32 bvalue = (bu & ((0x1u << 31u) - 1u));
+
+ if (asign != bsign)
+ return avalue + bvalue + 1u;
+ else if (avalue < bvalue)
+ return bvalue - avalue;
+ else
+ return avalue - bvalue;
+}
+
+bool comparePixelToDepthClearValue (const ConstPixelBufferAccess& access,
+ int x,
+ int y,
+ float ref)
+{
+ const tcu::TextureFormat format = tcu::getEffectiveDepthStencilTextureFormat(access.getFormat(), tcu::Sampler::MODE_DEPTH);
+ const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(format.type);
+
+ switch (channelClass)
+ {
+ case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
+ case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
+ {
+ const int bitDepth = tcu::getTextureFormatBitDepth(format).x();
+ const float depth = access.getPixDepth(x, y);
+ const float threshold = 2.0f / (float)((1 << bitDepth) - 1);
+
+ return deFloatAbs(depth - ref) <= threshold;
+ }
+
+ case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
+ {
+ const float depth = access.getPixDepth(x, y);
+ const int mantissaBits = tcu::getTextureFormatMantissaBitDepth(format).x();
+ const int threshold = 10 * 1 << (23 - mantissaBits);
+
+ DE_ASSERT(mantissaBits <= 23);
+
+ return calcFloatDiff(depth, ref) <= threshold;
+ }
+
+ default:
+ DE_FATAL("Invalid channel class");
+ return false;
+ }
+}
+
+bool comparePixelToStencilClearValue (const ConstPixelBufferAccess& access,
+ int x,
+ int y,
+ deUint32 ref)
+{
+ const deUint32 stencil = access.getPixStencil(x, y);
+
+ return stencil == ref;
+}
+
+bool comparePixelToColorClearValue (const ConstPixelBufferAccess& access,
+ int x,
+ int y,
+ const VkClearColorValue& ref)
+{
+ const tcu::TextureFormat format = access.getFormat();
+ const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(format.type);
+ const BVec4 channelMask = tcu::getTextureFormatChannelMask(format);
+
+ switch (channelClass)
+ {
+ case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
+ case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
+ {
+ const IVec4 bitDepth (tcu::getTextureFormatBitDepth(format));
+ const Vec4 resColor (access.getPixel(x, y));
+ const Vec4 refColor (ref.float32[0],
+ ref.float32[1],
+ ref.float32[2],
+ ref.float32[3]);
+ const Vec4 threshold (bitDepth[0] > 0 ? 20.0f / (float)((1 << bitDepth[0]) - 1) : 1.0f,
+ bitDepth[1] > 0 ? 20.0f / (float)((1 << bitDepth[1]) - 1) : 1.0f,
+ bitDepth[2] > 0 ? 20.0f / (float)((1 << bitDepth[2]) - 1) : 1.0f,
+ bitDepth[3] > 0 ? 20.0f / (float)((1 << bitDepth[3]) - 1) : 1.0f);
+
+ if (tcu::isSRGB(access.getFormat()))
+ return !(tcu::anyNotEqual(tcu::logicalAnd(lessThanEqual(tcu::absDiff(resColor, tcu::linearToSRGB(refColor)), threshold), channelMask), channelMask));
+ else
+ return !(tcu::anyNotEqual(tcu::logicalAnd(lessThanEqual(tcu::absDiff(resColor, refColor), threshold), channelMask), channelMask));
+ }
+
+ case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
+ {
+ const UVec4 resColor (access.getPixelUint(x, y));
+ const UVec4 refColor (ref.uint32[0],
+ ref.uint32[1],
+ ref.uint32[2],
+ ref.uint32[3]);
+ const UVec4 threshold (1);
+
+ return !(tcu::anyNotEqual(tcu::logicalAnd(lessThanEqual(tcu::absDiff(resColor, refColor), threshold), channelMask), channelMask));
+ }
+
+ case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
+ {
+ const IVec4 resColor (access.getPixelInt(x, y));
+ const IVec4 refColor (ref.int32[0],
+ ref.int32[1],
+ ref.int32[2],
+ ref.int32[3]);
+ const IVec4 threshold (1);
+
+ return !(tcu::anyNotEqual(tcu::logicalAnd(lessThanEqual(tcu::absDiff(resColor, refColor), threshold), channelMask), channelMask));
+ }
+
+ case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
+ {
+ const Vec4 resColor (access.getPixel(x, y));
+ const Vec4 refColor (ref.float32[0],
+ ref.float32[1],
+ ref.float32[2],
+ ref.float32[3]);
+ const IVec4 mantissaBits (tcu::getTextureFormatMantissaBitDepth(format));
+ const IVec4 threshold (10 * IVec4(1) << (23 - mantissaBits));
+
+ DE_ASSERT(tcu::allEqual(greaterThanEqual(threshold, IVec4(0)), BVec4(true)));
+
+ for (int ndx = 0; ndx < 4; ndx++)
+ {
+ if (calcFloatDiff(resColor[ndx], refColor[ndx]) > threshold[ndx] && channelMask[ndx])
+ return false;
+ }
+
+ return true;
+ }
+
+ default:
+ DE_FATAL("Invalid channel class");
+ return false;
+ }
+}
+
+class PixelStatus
+{
+public:
+ enum Status
+ {
+ STATUS_UNDEFINED = 0,
+ STATUS_OK = 1,
+ STATUS_FAIL = 2,
+
+ STATUS_LAST
+ };
+
+ PixelStatus (Status color, Status depth, Status stencil)
+ : m_status ((deUint8)(color << COLOR_OFFSET)
+ | (deUint8)((deUint8)depth << DEPTH_OFFSET)
+ | (deUint8)((deUint8)stencil << STENCIL_OFFSET))
+ {
+ }
+
+ Status getColorStatus (void) const { return (Status)((m_status & COLOR_MASK) >> COLOR_OFFSET); }
+ Status getDepthStatus (void) const { return (Status)((m_status & DEPTH_MASK) >> DEPTH_OFFSET); }
+ Status getStencilStatus (void) const { return (Status)((m_status & STENCIL_MASK) >> STENCIL_OFFSET); }
+
+ void setColorStatus (Status status)
+ {
+ DE_ASSERT(getColorStatus() == STATUS_UNDEFINED);
+ m_status |= (deUint8)(status << COLOR_OFFSET);
+ }
+
+ void setDepthStatus (Status status)
+ {
+ DE_ASSERT(getDepthStatus() == STATUS_UNDEFINED);
+ m_status |= (deUint8)(status << DEPTH_OFFSET);
+ }
+
+ void setStencilStatus (Status status)
+ {
+ DE_ASSERT(getStencilStatus() == STATUS_UNDEFINED);
+ m_status |= (deUint8)(status << STENCIL_OFFSET);
+ }
+
+private:
+ enum
+ {
+ COLOR_OFFSET = 0,
+ DEPTH_OFFSET = 2,
+ STENCIL_OFFSET = 4,
+
+ COLOR_MASK = (3<<COLOR_OFFSET),
+ DEPTH_MASK = (3<<DEPTH_OFFSET),
+ STENCIL_MASK = (3<<STENCIL_OFFSET),
+ };
+ deUint8 m_status;
+};
+
+void checkDepthRenderQuad (const ConstPixelBufferAccess& result,
+ const IVec2& posA,
+ const IVec2& posB,
+ vector<PixelStatus>& status)
+{
+ for (int y = posA.y(); y <= posB.y(); y++)
+ for (int x = posA.x(); x <= posB.x(); x++)
+ {
+ PixelStatus& pixelStatus = status[x + y * result.getWidth()];
+
+ if (pixelStatus.getDepthStatus() == PixelStatus::STATUS_UNDEFINED)
+ {
+ const Vec4 minUvs = computeUvs(posA, posB, IVec2(x-1, y-1));
+ const Vec4 maxUvs = computeUvs(posA, posB, IVec2(x+1, y+1));
+ const bool softCheck = std::abs(x - posA.x()) <= 1 || std::abs(x - posB.x()) <= 1
+ || std::abs(y - posA.y()) <= 1 || std::abs(y - posB.y()) <= 1;
+ const float resDepth = result.getPixDepth(x, y);
+
+ if (resDepth >= minUvs.x() && resDepth <= maxUvs.x())
+ pixelStatus.setDepthStatus(PixelStatus::STATUS_OK);
+ else if (!softCheck)
+ pixelStatus.setDepthStatus(PixelStatus::STATUS_FAIL);
+ }
+ }
+}
+
+void checkStencilRenderQuad (const ConstPixelBufferAccess& result,
+ const IVec2& posA,
+ const IVec2& posB,
+ vector<PixelStatus>& status)
+{
+ for (int y = posA.y(); y <= posB.y(); y++)
+ for (int x = posA.x(); x <= posB.x(); x++)
+ {
+ PixelStatus& pixelStatus = status[x + y * result.getWidth()];
+
+ if (pixelStatus.getStencilStatus() == PixelStatus::STATUS_UNDEFINED)
+ {
+ const bool softCheck = std::abs(x - posA.x()) <= 1 || std::abs(x - posB.x()) <= 1
+ || std::abs(y - posA.y()) <= 1 || std::abs(y - posB.y()) <= 1;
+
+ if (result.getPixStencil(x, y) == STENCIL_VALUE)
+ pixelStatus.setStencilStatus(PixelStatus::STATUS_OK);
+ else if (!softCheck)
+ pixelStatus.setStencilStatus(PixelStatus::STATUS_FAIL);
+ }
+ }
+}
+
+void checkColorRenderQuad (const ConstPixelBufferAccess& result,
+ const IVec2& posA,
+ const IVec2& posB,
+ vector<PixelStatus>& status)
+{
+ const tcu::TextureFormat& format = result.getFormat();
+ const bool srgb = tcu::isSRGB(format);
+ const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(format.type);
+ const tcu::TextureFormatInfo textureInfo = tcu::getTextureFormatInfo(format);
+ const float clampMin = (float)(-MAX_INTEGER_VALUE);
+ const float clampMax = (float)(MAX_INTEGER_VALUE);
+ const Vec4 valueMax (de::clamp(textureInfo.valueMax[0], clampMin, clampMax),
+ de::clamp(textureInfo.valueMax[1], clampMin, clampMax),
+ de::clamp(textureInfo.valueMax[2], clampMin, clampMax),
+ de::clamp(textureInfo.valueMax[3], clampMin, clampMax));
+
+ const Vec4 valueMin (de::clamp(textureInfo.valueMin[0], clampMin, clampMax),
+ de::clamp(textureInfo.valueMin[1], clampMin, clampMax),
+ de::clamp(textureInfo.valueMin[2], clampMin, clampMax),
+ de::clamp(textureInfo.valueMin[3], clampMin, clampMax));
+ const BVec4 channelMask = tcu::getTextureFormatChannelMask(format);
+
+ switch (channelClass)
+ {
+ case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
+ case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
+ case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
+ {
+ for (int y = posA.y(); y <= posB.y(); y++)
+ for (int x = posA.x(); x <= posB.x(); x++)
+ {
+ PixelStatus& pixelStatus = status[x + y * result.getWidth()];
+
+ if (pixelStatus.getColorStatus() == PixelStatus::STATUS_UNDEFINED)
+ {
+ const Vec4 minUvs = computeUvs(posA, posB, IVec2(x-1, y-1));
+ const Vec4 maxUvs = computeUvs(posA, posB, IVec2(x+1, y+1));
+ const bool softCheck = std::abs(x - posA.x()) <= 1 || std::abs(x - posB.x()) <= 1
+ || std::abs(y - posA.y()) <= 1 || std::abs(y - posB.y()) <= 1;
+
+ const Vec4 resColor (result.getPixel(x, y));
+
+ const Vec4 minRefColor = srgb ? tcu::linearToSRGB(valueMax * minUvs + valueMin * (Vec4(1.0f) - minUvs))
+ : valueMax * minUvs + valueMin * (Vec4(1.0f) - minUvs);
+ const Vec4 maxRefColor = srgb ? tcu::linearToSRGB(valueMax * maxUvs + valueMin * (Vec4(1.0f) - maxUvs))
+ : valueMax * maxUvs + valueMin * (Vec4(1.0f) - maxUvs);
+
+ DE_ASSERT(minRefColor[0] <= maxRefColor[0]);
+ DE_ASSERT(minRefColor[1] <= maxRefColor[1]);
+ DE_ASSERT(minRefColor[2] <= maxRefColor[2]);
+ DE_ASSERT(minRefColor[3] <= maxRefColor[3]);
+
+ if (tcu::anyNotEqual(tcu::logicalAnd(
+ tcu::logicalAnd(greaterThanEqual(resColor, minRefColor),
+ lessThanEqual(resColor, maxRefColor)),
+ channelMask), channelMask))
+ {
+ if (!softCheck)
+ pixelStatus.setColorStatus(PixelStatus::STATUS_FAIL);
+ }
+ else
+ pixelStatus.setColorStatus(PixelStatus::STATUS_OK);
+ }
+ }
+
+ break;
+ }
+
+ case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
+ {
+ for (int y = posA.y(); y <= posB.y(); y++)
+ for (int x = posA.x(); x <= posB.x(); x++)
+ {
+ PixelStatus& pixelStatus = status[x + y * result.getWidth()];
+
+ if (pixelStatus.getColorStatus() == PixelStatus::STATUS_UNDEFINED)
+ {
+ const Vec4 minUvs = computeUvs(posA, posB, IVec2(x-1, y-1));
+ const Vec4 maxUvs = computeUvs(posA, posB, IVec2(x+1, y+1));
+ const bool softCheck = std::abs(x - posA.x()) <= 1 || std::abs(x - posB.x()) <= 1
+ || std::abs(y - posA.y()) <= 1 || std::abs(y - posB.y()) <= 1;
+
+ const UVec4 resColor (result.getPixelUint(x, y));
+
+ const Vec4 minRefColorF = valueMax * minUvs + valueMin * (Vec4(1.0f) - minUvs);
+ const Vec4 maxRefColorF = valueMax * maxUvs + valueMin * (Vec4(1.0f) - maxUvs);
+
+ const UVec4 minRefColor (minRefColorF.asUint());
+ const UVec4 maxRefColor (maxRefColorF.asUint());
+
+ DE_ASSERT(minRefColor[0] <= maxRefColor[0]);
+ DE_ASSERT(minRefColor[1] <= maxRefColor[1]);
+ DE_ASSERT(minRefColor[2] <= maxRefColor[2]);
+ DE_ASSERT(minRefColor[3] <= maxRefColor[3]);
+
+ if (tcu::anyNotEqual(tcu::logicalAnd(
+ tcu::logicalAnd(greaterThanEqual(resColor, minRefColor),
+ lessThanEqual(resColor, maxRefColor)),
+ channelMask), channelMask))
+ {
+ if (!softCheck)
+ pixelStatus.setColorStatus(PixelStatus::STATUS_FAIL);
+ }
+ else
+ pixelStatus.setColorStatus(PixelStatus::STATUS_OK);
+ }
+ }
+
+ break;
+ }
+
+ case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
+ {
+ for (int y = posA.y(); y <= posB.y(); y++)
+ for (int x = posA.x(); x <= posB.x(); x++)
+ {
+ PixelStatus& pixelStatus = status[x + y * result.getWidth()];
+
+ if (pixelStatus.getColorStatus() == PixelStatus::STATUS_UNDEFINED)
+ {
+ const Vec4 minUvs = computeUvs(posA, posB, IVec2(x-1, y-1));
+ const Vec4 maxUvs = computeUvs(posA, posB, IVec2(x+1, y+1));
+ const bool softCheck = std::abs(x - posA.x()) <= 1 || std::abs(x - posB.x()) <= 1
+ || std::abs(y - posA.y()) <= 1 || std::abs(y - posB.y()) <= 1;
+
+ const IVec4 resColor (result.getPixelInt(x, y));
+
+ const Vec4 minRefColorF = valueMax * minUvs + valueMin * (Vec4(1.0f) - minUvs);
+ const Vec4 maxRefColorF = valueMax * maxUvs + valueMin * (Vec4(1.0f) - maxUvs);
+
+ const IVec4 minRefColor (minRefColorF.asInt());
+ const IVec4 maxRefColor (maxRefColorF.asInt());
+
+ DE_ASSERT(minRefColor[0] <= maxRefColor[0]);
+ DE_ASSERT(minRefColor[1] <= maxRefColor[1]);
+ DE_ASSERT(minRefColor[2] <= maxRefColor[2]);
+ DE_ASSERT(minRefColor[3] <= maxRefColor[3]);
+
+ if (tcu::anyNotEqual(tcu::logicalAnd(
+ tcu::logicalAnd(greaterThanEqual(resColor, minRefColor),
+ lessThanEqual(resColor, maxRefColor)),
+ channelMask), channelMask))
+ {
+ if (!softCheck)
+ pixelStatus.setColorStatus(PixelStatus::STATUS_FAIL);
+ }
+ else
+ pixelStatus.setColorStatus(PixelStatus::STATUS_OK);
+ }
+ }
+
+ break;
+ }
+
+ default:
+ DE_FATAL("Invalid channel class");
+ }
+}
+
+void checkColorClear (const ConstPixelBufferAccess& result,
+ const UVec2& offset,
+ const UVec2& size,
+ vector<PixelStatus>& status,
+ const VkClearColorValue& color)
+{
+ DE_ASSERT(offset.x() + size.x() <= (deUint32)result.getWidth());
+ DE_ASSERT(offset.y() + size.y() <= (deUint32)result.getHeight());
+
+ DE_ASSERT(result.getWidth() * result.getHeight() == (int)status.size());
+
+ for (int y = offset.y(); y < (int)(offset.y() + size.y()); y++)
+ for (int x = offset.x(); x < (int)(offset.x() + size.x()); x++)
+ {
+ PixelStatus& pixelStatus = status[x + y * result.getWidth()];
+
+ DE_ASSERT(x + y * result.getWidth() < (int)status.size());
+
+ if (pixelStatus.getColorStatus() == PixelStatus::STATUS_UNDEFINED)
+ {
+ if (comparePixelToColorClearValue(result, x, y, color))
+ pixelStatus.setColorStatus(PixelStatus::STATUS_OK);
+ else
+ pixelStatus.setColorStatus(PixelStatus::STATUS_FAIL);
+ }
+ }
+}
+
+void checkDepthClear (const ConstPixelBufferAccess& result,
+ const UVec2& offset,
+ const UVec2& size,
+ vector<PixelStatus>& status,
+ float depth)
+{
+ for (int y = offset.y(); y < (int)(offset.y() + size.y()); y++)
+ for (int x = offset.x(); x < (int)(offset.x() + size.x()); x++)
+ {
+ PixelStatus& pixelStatus = status[x + y * result.getWidth()];
+
+ if (pixelStatus.getDepthStatus() == PixelStatus::STATUS_UNDEFINED)
+ {
+ if (comparePixelToDepthClearValue(result, x, y, depth))
+ pixelStatus.setDepthStatus(PixelStatus::STATUS_OK);
+ else
+ pixelStatus.setDepthStatus(PixelStatus::STATUS_FAIL);
+ }
+ }
+}
+
+void checkStencilClear (const ConstPixelBufferAccess& result,
+ const UVec2& offset,
+ const UVec2& size,
+ vector<PixelStatus>& status,
+ deUint32 stencil)
+{
+ for (int y = offset.y(); y < (int)(offset.y() + size.y()); y++)
+ for (int x = offset.x(); x < (int)(offset.x() + size.x()); x++)
+ {
+ PixelStatus& pixelStatus = status[x + y * result.getWidth()];
+
+ if (pixelStatus.getStencilStatus() == PixelStatus::STATUS_UNDEFINED)
+ {
+ if (comparePixelToStencilClearValue(result, x, y, stencil))
+ pixelStatus.setStencilStatus(PixelStatus::STATUS_OK);
+ else
+ pixelStatus.setStencilStatus(PixelStatus::STATUS_FAIL);
+ }
+ }
+}
+
+bool verifyAttachment (const ConstPixelBufferAccess& result,
+ const Maybe<ConstPixelBufferAccess>& secondaryResult,
+ const RenderPass& renderPassInfo,
+ const Maybe<VkClearValue>& renderPassClearValue,
+ const Maybe<VkClearValue>& imageClearValue,
+ const vector<Subpass>& subpasses,
+ const vector<SubpassRenderInfo>& subpassRenderInfo,
+ const PixelBufferAccess& errorImage,
+ deUint32 attachmentIndex,
+ const UVec2& renderPos,
+ const UVec2& renderSize)
+{
+ const tcu::TextureFormat& format = result.getFormat();
+ const bool hasDepth = tcu::hasDepthComponent(format.order);
+ const bool hasStencil = tcu::hasStencilComponent(format.order);
+ const bool isColorFormat = !hasDepth && !hasStencil;
+ const PixelStatus initialStatus (isColorFormat ? PixelStatus::STATUS_UNDEFINED : PixelStatus::STATUS_OK,
+ hasDepth ? PixelStatus::STATUS_UNDEFINED : PixelStatus::STATUS_OK,
+ hasStencil ? PixelStatus::STATUS_UNDEFINED : PixelStatus::STATUS_OK);
+
+ bool attachmentIsUsed = false;
+ vector<PixelStatus> status (result.getWidth() * result.getHeight(), initialStatus);
+ tcu::clear(errorImage, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
+
+ // Check if attachment is used
+ for (int subpassNdx = 0; subpassNdx < (int)subpasses.size(); subpassNdx++)
+ {
+ const Subpass& subpass = subpasses[subpassNdx];
+ const Maybe<deUint32> attachmentNdx = findColorAttachment(subpass, attachmentIndex);
+
+ if (attachmentNdx || subpass.getDepthStencilAttachment().getAttachment() == attachmentIndex)
+ attachmentIsUsed = true;
+ }
+
+ // Set all pixels that have undefined values to OK
+ if (attachmentIsUsed && (((isColorFormat || hasDepth) && renderPassInfo.getAttachments()[attachmentIndex].getStoreOp() == VK_ATTACHMENT_STORE_OP_DONT_CARE)
+ || (hasStencil && renderPassInfo.getAttachments()[attachmentIndex].getStencilStoreOp() == VK_ATTACHMENT_STORE_OP_DONT_CARE)))
+ {
+ for(int y = renderPos.y(); y < (int)(renderPos.y() + renderSize.y()); y++)
+ for(int x = renderPos.x(); x < (int)(renderPos.x() + renderSize.x()); x++)
+ {
+ PixelStatus& pixelStatus = status[x + y * result.getWidth()];
+
+ if (isColorFormat && renderPassInfo.getAttachments()[attachmentIndex].getStoreOp() == VK_ATTACHMENT_STORE_OP_DONT_CARE)
+ pixelStatus.setColorStatus(PixelStatus::STATUS_OK);
+ else
+ {
+ if (hasDepth && renderPassInfo.getAttachments()[attachmentIndex].getStoreOp() == VK_ATTACHMENT_STORE_OP_DONT_CARE)
+ pixelStatus.setDepthStatus(PixelStatus::STATUS_OK);
+
+ if (hasStencil && renderPassInfo.getAttachments()[attachmentIndex].getStencilStoreOp() == VK_ATTACHMENT_STORE_OP_DONT_CARE)
+ pixelStatus.setStencilStatus(PixelStatus::STATUS_OK);
+ }
+ }
+ }
+
+ // Check renderpass rendering results
+ if (renderPassInfo.getAttachments()[attachmentIndex].getStoreOp() == VK_ATTACHMENT_STORE_OP_STORE
+ || (hasStencil && renderPassInfo.getAttachments()[attachmentIndex].getStencilStoreOp() == VK_ATTACHMENT_STORE_OP_STORE))
+ {
+ // Check subpass rendering results
+ for (int subpassNdx = (int)subpasses.size() - 1; subpassNdx >= 0; subpassNdx--)
+ {
+ const Subpass& subpass = subpasses[subpassNdx];
+ const SubpassRenderInfo& renderInfo = subpassRenderInfo[subpassNdx];
+ const Maybe<deUint32> attachmentNdx = findColorAttachment(subpass, attachmentIndex);
+
+ // Check rendered quad
+ if (renderInfo.getRenderQuad() && (attachmentNdx || subpass.getDepthStencilAttachment().getAttachment() == attachmentIndex))
+ {
+ const RenderQuad& renderQuad = *renderInfo.getRenderQuad();
+ const Vec4 posA = renderQuad.getCornerA();
+ const Vec4 posB = renderQuad.getCornerB();
+ const Vec2 origin = Vec2((float)renderInfo.getViewportOffset().x(), (float)renderInfo.getViewportOffset().y()) + Vec2((float)renderInfo.getViewportSize().x(), (float)renderInfo.getViewportSize().y()) / Vec2(2.0f);
+ const Vec2 p = Vec2((float)renderInfo.getViewportSize().x(), (float)renderInfo.getViewportSize().y()) / Vec2(2.0f);
+ const IVec2 posAI ((deInt32)(origin.x() + (p.x() * posA.x())),
+ (deInt32)(origin.y() + (p.y() * posA.y())));
+ const IVec2 posBI ((deInt32)(origin.x() + (p.x() * posB.x())),
+ (deInt32)(origin.y() + (p.y() * posB.y())));
+
+ if (isColorFormat)
+ checkColorRenderQuad(result, posAI, posBI, status);
+ else
+ {
+ if (hasDepth)
+ checkDepthRenderQuad(result, posAI, posBI, status);
+
+ if (hasDepth && hasStencil)
+ checkStencilRenderQuad(*secondaryResult, posAI, posBI, status);
+ else if (hasStencil)
+ checkStencilRenderQuad(result, posAI, posBI, status);
+ }
+ }
+
+ // Check color attachment clears
+ if (attachmentNdx && !renderInfo.getColorClears().empty())
+ {
+ const ColorClear& clear = renderInfo.getColorClears()[*attachmentNdx];
+
+ checkColorClear(result, clear.getOffset(), clear.getSize(), status, clear.getColor());
+ }
+
+ // Check depth/stencil attachment clears
+ if (subpass.getDepthStencilAttachment().getAttachment() == attachmentIndex && renderInfo.getDepthStencilClear())
+ {
+ const DepthStencilClear clear = *renderInfo.getDepthStencilClear();
+
+ if (hasDepth)
+ checkDepthClear(result, clear.getOffset(), clear.getSize(), status, clear.getDepth());
+
+ if (hasDepth && hasStencil)
+ checkStencilClear(*secondaryResult, clear.getOffset(), clear.getSize(), status, clear.getStencil());
+ else if (hasStencil)
+ checkStencilClear(result, clear.getOffset(), clear.getSize(), status, clear.getStencil());
+ }
+ }
+
+ // Check renderpas clear results
+ if (attachmentIsUsed && renderPassClearValue)
+ {
+ if (isColorFormat)
+ {
+ if (renderPassInfo.getAttachments()[attachmentIndex].getLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR)
+ checkColorClear(result, renderPos, renderSize, status, renderPassClearValue->color);
+ }
+ else
+ {
+ if (hasDepth && renderPassInfo.getAttachments()[attachmentIndex].getLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR)
+ checkDepthClear(result, renderPos, renderSize, status, renderPassClearValue->depthStencil.depth);
+
+ if (hasDepth && hasStencil && renderPassInfo.getAttachments()[attachmentIndex].getStencilLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR)
+ checkStencilClear(*secondaryResult, renderPos, renderSize, status, renderPassClearValue->depthStencil.stencil);
+ else if (hasStencil && renderPassInfo.getAttachments()[attachmentIndex].getStencilLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR)
+ checkStencilClear(result, renderPos, renderSize, status, renderPassClearValue->depthStencil.stencil);
+ }
+ }
+ }
+
+ // Set all pixels that have undefined values fater renderpass to OK
+ if (attachmentIsUsed && (((isColorFormat || hasDepth) && renderPassInfo.getAttachments()[attachmentIndex].getLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE)
+ || (hasStencil && renderPassInfo.getAttachments()[attachmentIndex].getStencilLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE)))
+ {
+ for(int y = renderPos.y(); y < (int)(renderPos.y() + renderSize.y()); y++)
+ for(int x = renderPos.x(); x < (int)(renderPos.x() + renderSize.x()); x++)
+ {
+ PixelStatus& pixelStatus = status[x + y * result.getWidth()];
+
+ if (pixelStatus.getColorStatus() == PixelStatus::STATUS_UNDEFINED
+ && isColorFormat && renderPassInfo.getAttachments()[attachmentIndex].getLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE)
+ pixelStatus.setColorStatus(PixelStatus::STATUS_OK);
+ else
+ {
+ if (pixelStatus.getDepthStatus() == PixelStatus::STATUS_UNDEFINED
+ && hasDepth && renderPassInfo.getAttachments()[attachmentIndex].getLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE)
+ pixelStatus.setDepthStatus(PixelStatus::STATUS_OK);
+
+ if (pixelStatus.getStencilStatus() == PixelStatus::STATUS_UNDEFINED
+ && hasStencil && renderPassInfo.getAttachments()[attachmentIndex].getStencilLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE)
+ pixelStatus.setStencilStatus(PixelStatus::STATUS_OK);
+ }
+ }
+ }
+
+ if (imageClearValue)
+ {
+ if (isColorFormat)
+ checkColorClear(result, UVec2(0, 0), UVec2(result.getWidth(), result.getHeight()), status, imageClearValue->color);
+ else
+ {
+ if (hasDepth)
+ checkDepthClear(result, UVec2(0, 0), UVec2(result.getWidth(), result.getHeight()), status, imageClearValue->depthStencil.depth);
+
+ if (hasDepth && hasStencil)
+ checkStencilClear(*secondaryResult, UVec2(0, 0), UVec2(secondaryResult->getWidth(), result.getHeight()), status, imageClearValue->depthStencil.stencil);
+ else if (hasStencil)
+ checkStencilClear(result, UVec2(0, 0), UVec2(result.getWidth(), result.getHeight()), status, imageClearValue->depthStencil.stencil);
+ }
+ }
+
+ {
+ bool isOk = true;
+
+ for(int y = 0; y < result.getHeight(); y++)
+ for(int x = 0; x < result.getWidth(); x++)
+ {
+ const PixelStatus& pixelStatus = status[x + y * result.getWidth()];
+
+ if (isColorFormat)
+ {
+ if (pixelStatus.getColorStatus() != PixelStatus::STATUS_OK)
+ {
+ if (pixelStatus.getColorStatus() == PixelStatus::STATUS_UNDEFINED)
+ errorImage.setPixel(Vec4(1.0f, 1.0f, 0.0f, 1.0f), x, y);
+ else if (pixelStatus.getColorStatus() == PixelStatus::STATUS_FAIL)
+ errorImage.setPixel(Vec4(1.0f, 0.0f, 0.0f, 1.0f), x, y);
+
+ isOk = false;
+ }
+ }
+ else
+ {
+ if (hasDepth && pixelStatus.getDepthStatus() != PixelStatus::STATUS_OK)
+ {
+ errorImage.setPixel(Vec4(1.0f, 0.0f, 0.0f, 1.0f), x, y);
+ isOk = false;
+ }
+
+ if (hasStencil && pixelStatus.getStencilStatus() != PixelStatus::STATUS_OK)
+ {
+ errorImage.setPixel(Vec4(1.0f, 0.0f, 0.0f, 1.0f), x, y);
+ isOk = false;
+ }
+ }
+ }
+
+ return isOk;
+ }
+}
+
+bool logAndVerifyImages (TestLog& log,
+ const DeviceInterface& vk,
+ VkDevice device,
+ const vector<de::SharedPtr<AttachmentResources> >& attachmentResources,
+ const vector<bool>& attachmentIsLazy,
+ const RenderPass& renderPassInfo,
+ const vector<Maybe<VkClearValue> >& renderPassClearValues,
+ const vector<Maybe<VkClearValue> >& imageClearValues,
+ const vector<SubpassRenderInfo>& subpassRenderInfo,
+ const UVec2& targetSize,
+ const TestConfig& config)
+{
+ vector<tcu::TextureLevel> referenceAttachments;
+ bool isOk = true;
+
+ log << TestLog::Message << "Reference images fill undefined pixels with grid pattern." << TestLog::EndMessage;
+
+ renderReferenceImages(referenceAttachments, renderPassInfo, targetSize, imageClearValues, renderPassClearValues, subpassRenderInfo, config.renderPos, config.renderSize);
+
+ for (size_t attachmentNdx = 0; attachmentNdx < renderPassInfo.getAttachments().size(); attachmentNdx++)
+ {
+ if (!attachmentIsLazy[attachmentNdx])
+ {
+ const Attachment attachment = renderPassInfo.getAttachments()[attachmentNdx];
+ const tcu::TextureFormat format = mapVkFormat(attachment.getFormat());
+
+ if (tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order))
+ {
+ const tcu::TextureFormat depthFormat = tcu::getEffectiveDepthStencilTextureFormat(format, tcu::Sampler::MODE_DEPTH);
+ const VkDeviceSize depthBufferSize = targetSize.x() * targetSize.y() * depthFormat.getPixelSize();
+ void* const depthPtr = attachmentResources[attachmentNdx]->getResultMemory().getHostPtr();
+
+ const tcu::TextureFormat stencilFormat = tcu::getEffectiveDepthStencilTextureFormat(format, tcu::Sampler::MODE_STENCIL);
+ const VkDeviceSize stencilBufferSize = targetSize.x() * targetSize.y() * stencilFormat.getPixelSize();
+ void* const stencilPtr = attachmentResources[attachmentNdx]->getResultMemory().getHostPtr();
+
+ const VkMappedMemoryRange ranges[] =
+ {
+ {
+ VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // sType;
+ DE_NULL, // pNext;
+ attachmentResources[attachmentNdx]->getResultMemory().getMemory(), // mem;
+ attachmentResources[attachmentNdx]->getResultMemory().getOffset(), // offset;
+ depthBufferSize // size;
+ },
+ {
+ VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // sType;
+ DE_NULL, // pNext;
+ attachmentResources[attachmentNdx]->getSecondaryResultMemory().getMemory(), // mem;
+ attachmentResources[attachmentNdx]->getSecondaryResultMemory().getOffset(), // offset;
+ stencilBufferSize // size;
+ }
+ };
+ VK_CHECK(vk.invalidateMappedMemoryRanges(device, 2u, ranges));
+
+ {
+ const ConstPixelBufferAccess depthAccess (depthFormat, targetSize.x(), targetSize.y(), 1, depthPtr);
+ const ConstPixelBufferAccess stencilAccess (stencilFormat, targetSize.x(), targetSize.y(), 1, stencilPtr);
+ tcu::TextureLevel errorImage (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), targetSize.x(), targetSize.y());
+
+ log << TestLog::Image("Attachment" + de::toString(attachmentNdx) + "Depth", "Attachment " + de::toString(attachmentNdx) + " Depth", depthAccess);
+ log << TestLog::Image("Attachment" + de::toString(attachmentNdx) + "Stencil", "Attachment " + de::toString(attachmentNdx) + " Stencil", stencilAccess);
+
+ log << TestLog::Image("AttachmentReference" + de::toString(attachmentNdx), "Attachment reference " + de::toString(attachmentNdx), referenceAttachments[attachmentNdx].getAccess());
+
+ if ((renderPassInfo.getAttachments()[attachmentNdx].getStoreOp() == VK_ATTACHMENT_STORE_OP_STORE || renderPassInfo.getAttachments()[attachmentNdx].getStencilStoreOp() == VK_ATTACHMENT_STORE_OP_STORE)
+ && !verifyAttachment(depthAccess, tcu::just(stencilAccess), renderPassInfo, renderPassClearValues[attachmentNdx], imageClearValues[attachmentNdx], renderPassInfo.getSubpasses(), subpassRenderInfo, errorImage.getAccess(), (deUint32)attachmentNdx, config.renderPos, config.renderSize))
+ {
+ log << TestLog::Image("AttachmentError" + de::toString(attachmentNdx), "Attachment Error " + de::toString(attachmentNdx), errorImage.getAccess());
+ isOk = false;
+ }
+ }
+ }
+ else
+ {
+ const VkDeviceSize bufferSize = targetSize.x() * targetSize.y() * format.getPixelSize();
+ void* const ptr = attachmentResources[attachmentNdx]->getResultMemory().getHostPtr();
+
+ const VkMappedMemoryRange range =
+ {
+ VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // sType;
+ DE_NULL, // pNext;
+ attachmentResources[attachmentNdx]->getResultMemory().getMemory(), // mem;
+ attachmentResources[attachmentNdx]->getResultMemory().getOffset(), // offset;
+ bufferSize // size;
+ };
+ VK_CHECK(vk.invalidateMappedMemoryRanges(device, 1u, &range));
+
+ {
+ const ConstPixelBufferAccess access (format, targetSize.x(), targetSize.y(), 1, ptr);
+ tcu::TextureLevel errorImage (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), targetSize.x(), targetSize.y());
+
+ log << TestLog::Image("Attachment" + de::toString(attachmentNdx), "Attachment " + de::toString(attachmentNdx), access);
+ log << TestLog::Image("AttachmentReference" + de::toString(attachmentNdx), "Attachment reference " + de::toString(attachmentNdx), referenceAttachments[attachmentNdx].getAccess());
+
+ if ((renderPassInfo.getAttachments()[attachmentNdx].getStoreOp() == VK_ATTACHMENT_STORE_OP_STORE || renderPassInfo.getAttachments()[attachmentNdx].getStencilStoreOp() == VK_ATTACHMENT_STORE_OP_STORE)
+ && !verifyAttachment(access, tcu::nothing<ConstPixelBufferAccess>(), renderPassInfo, renderPassClearValues[attachmentNdx], imageClearValues[attachmentNdx], renderPassInfo.getSubpasses(), subpassRenderInfo, errorImage.getAccess(), (deUint32)attachmentNdx, config.renderPos, config.renderSize))
+ {
+ log << TestLog::Image("AttachmentError" + de::toString(attachmentNdx), "Attachment Error " + de::toString(attachmentNdx), errorImage.getAccess());
+ isOk = false;
+ }
+ }
+ }
+ }
+ }
+
+ return isOk;
+}
+
+std::string getAttachmentType (VkFormat vkFormat)
+{
+ const tcu::TextureFormat format = mapVkFormat(vkFormat);
+ const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(format.type);
+
+ switch (channelClass)
+ {
+ case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
+ return "ivec4";
+
+ case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
+ return "uvec4";
+
+ case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
+ case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
+ case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
+ return "vec4";
+
+ default:
+ DE_FATAL("Unknown channel class");
+ return "";
+ }
+}
+
+void createTestShaders (SourceCollections& dst, TestConfig config)
+{
+ if (config.renderTypes & TestConfig::RENDERTYPES_DRAW)
+ {
+ const vector<Subpass>& subpasses = config.renderPass.getSubpasses();
+
+ for (size_t subpassNdx = 0; subpassNdx < subpasses.size(); subpassNdx++)
+ {
+ const Subpass& subpass = subpasses[subpassNdx];
+ std::ostringstream vertexShader;
+ std::ostringstream fragmentShader;
+
+ vertexShader << "#version 310 es\n"
+ << "layout(location = 0) in highp vec4 a_position;\n"
+ << "layout(location = 0) out highp vec2 v_color;\n"
+ << "void main (void) {\n"
+ << "\thighp float a = 0.5 + a_position.x;\n"
+ << "\thighp float b = 0.5 + a_position.y;\n"
+ << "\tv_color = vec2(a, b);\n"
+ << "\tgl_Position = a_position;\n"
+ << "}\n";
+
+ fragmentShader << "#version 310 es\n"
+ << "layout(location = 0) in highp vec2 v_color;\n";
+
+ for (size_t attachmentNdx = 0; attachmentNdx < subpass.getColorAttachments().size(); attachmentNdx++)
+ {
+ const std::string attachmentType = getAttachmentType(config.renderPass.getAttachments()[subpass.getColorAttachments()[attachmentNdx].getAttachment()].getFormat());
+ fragmentShader << "layout(location = " << attachmentNdx << ") out highp " << attachmentType << " o_color" << attachmentNdx << ";\n";
+ }
+
+ fragmentShader << "void main (void) {\n"
+ << "\thighp vec4 scale = vec4(v_color.x, v_color.y, v_color.x * v_color.y, (v_color.x + v_color.y) / 2.0);\n";
+
+ for (size_t attachmentNdx = 0; attachmentNdx < subpass.getColorAttachments().size(); attachmentNdx++)
+ {
+ const tcu::TextureFormat format = mapVkFormat(config.renderPass.getAttachments()[subpass.getColorAttachments()[attachmentNdx].getAttachment()].getFormat());
+ const tcu::TextureFormatInfo formatInfo = tcu::getTextureFormatInfo(format);
+ const float clampMin = (float)(-MAX_INTEGER_VALUE);
+ const float clampMax = (float)(MAX_INTEGER_VALUE);
+ const Vec4 valueMax (de::clamp(formatInfo.valueMax[0], clampMin, clampMax),
+ de::clamp(formatInfo.valueMax[1], clampMin, clampMax),
+ de::clamp(formatInfo.valueMax[2], clampMin, clampMax),
+ de::clamp(formatInfo.valueMax[3], clampMin, clampMax));
+
+ const Vec4 valueMin (de::clamp(formatInfo.valueMin[0], clampMin, clampMax),
+ de::clamp(formatInfo.valueMin[1], clampMin, clampMax),
+ de::clamp(formatInfo.valueMin[2], clampMin, clampMax),
+ de::clamp(formatInfo.valueMin[3], clampMin, clampMax));
+ const std::string attachmentType = getAttachmentType(config.renderPass.getAttachments()[subpass.getColorAttachments()[attachmentNdx].getAttachment()].getFormat());
+
+ fragmentShader << "\to_color" << attachmentNdx << " = " << attachmentType << "(vec4" << valueMin << " + vec4" << (valueMax - valueMin) << " * scale);\n";
+ }
+
+ fragmentShader << "}\n";
+
+ dst.glslSources.add(de::toString(subpassNdx) + "-vert") << glu::VertexSource(vertexShader.str());
+ dst.glslSources.add(de::toString(subpassNdx) + "-frag") << glu::FragmentSource(fragmentShader.str());
+ }
+ }
+}
+
+void initializeAttachmentIsLazy (vector<bool>& attachmentIsLazy, const vector<Attachment>& attachments, TestConfig::ImageMemory imageMemory)
+{
+ bool lastAttachmentWasLazy = false;
+
+ for (size_t attachmentNdx = 0; attachmentNdx < attachments.size(); attachmentNdx++)
+ {
+ if (attachments[attachmentNdx].getLoadOp() != VK_ATTACHMENT_LOAD_OP_LOAD
+ && attachments[attachmentNdx].getStoreOp() != VK_ATTACHMENT_STORE_OP_STORE
+ && attachments[attachmentNdx].getStencilLoadOp() != VK_ATTACHMENT_LOAD_OP_LOAD
+ && attachments[attachmentNdx].getStencilStoreOp() != VK_ATTACHMENT_STORE_OP_STORE)
+ {
+ if (imageMemory == TestConfig::IMAGEMEMORY_LAZY || (imageMemory & TestConfig::IMAGEMEMORY_LAZY && !lastAttachmentWasLazy))
+ {
+ attachmentIsLazy.push_back(true);
+ lastAttachmentWasLazy = true;
+ }
+ else if (imageMemory & TestConfig::IMAGEMEMORY_STRICT)
+ {
+ attachmentIsLazy.push_back(false);
+ lastAttachmentWasLazy = false;
+ }
+ else
+ DE_FATAL("Unknown imageMemory");
+ }
+ else
+ attachmentIsLazy.push_back(false);
+ }
+}
+
+void initializeSubpassIsSecondary (vector<bool>& subpassIsSecondary, const vector<Subpass>& subpasses, TestConfig::CommandBufferTypes commandBuffer)
+{
+ bool lastSubpassWasSecondary = false;
+
+ for (size_t subpassNdx = 0; subpassNdx < subpasses.size(); subpassNdx++)
+ {
+ if (commandBuffer == TestConfig::COMMANDBUFFERTYPES_SECONDARY || (commandBuffer & TestConfig::COMMANDBUFFERTYPES_SECONDARY && !lastSubpassWasSecondary))
+ {
+ subpassIsSecondary.push_back(true);
+ lastSubpassWasSecondary = true;
+ }
+ else if (commandBuffer & TestConfig::COMMANDBUFFERTYPES_INLINE)
+ {
+ subpassIsSecondary.push_back(false);
+ lastSubpassWasSecondary = false;
+ }
+ else
+ DE_FATAL("Unknown commandBuffer");
+ }
+}
+
+void initializeImageClearValues (de::Random& rng, vector<Maybe<VkClearValue> >& clearValues, const vector<Attachment>& attachments, const vector<bool>& isLazy)
+{
+ for (size_t attachmentNdx = 0; attachmentNdx < attachments.size(); attachmentNdx++)
+ {
+ if (!isLazy[attachmentNdx])
+ clearValues.push_back(just(randomClearValue(attachments[attachmentNdx], rng)));
+ else
+ clearValues.push_back(nothing<VkClearValue>());
+ }
+}
+
+void initializeRenderPassClearValues (de::Random& rng, vector<Maybe<VkClearValue> >& clearValues, const vector<Attachment>& attachments)
+{
+ for (size_t attachmentNdx = 0; attachmentNdx < attachments.size(); attachmentNdx++)
+ {
+ if (attachments[attachmentNdx].getLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR
+ || attachments[attachmentNdx].getStencilLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR)
+ {
+ clearValues.push_back(just(randomClearValue(attachments[attachmentNdx], rng)));
+ }
+ else
+ clearValues.push_back(nothing<VkClearValue>());
+ }
+}
+
+void initializeSubpassClearValues (de::Random& rng, vector<vector<VkClearColorValue> >& clearValues, const RenderPass& renderPass)
+{
+ clearValues.resize(renderPass.getSubpasses().size());
+
+ for (size_t subpassNdx = 0; subpassNdx < renderPass.getSubpasses().size(); subpassNdx++)
+ {
+ const Subpass& subpass = renderPass.getSubpasses()[subpassNdx];
+ const vector<AttachmentReference>& colorAttachments = subpass.getColorAttachments();
+
+ clearValues[subpassNdx].resize(colorAttachments.size());
+
+ for (size_t attachmentRefNdx = 0; attachmentRefNdx < colorAttachments.size(); attachmentRefNdx++)
+ {
+ const AttachmentReference& attachmentRef = colorAttachments[attachmentRefNdx];
+ const Attachment& attachment = renderPass.getAttachments()[attachmentRef.getAttachment()];
+
+ clearValues[subpassNdx][attachmentRefNdx] = randomColorClearValue(attachment, rng);
+ }
+ }
+}
+
+void logSubpassRenderInfo (TestLog& log,
+ const SubpassRenderInfo& info)
+{
+ log << TestLog::Message << "Viewport, offset: " << info.getViewportOffset() << ", size: " << info.getViewportSize() << TestLog::EndMessage;
+
+ if (info.isSecondary())
+ log << TestLog::Message << "Subpass uses secondary command buffers" << TestLog::EndMessage;
+ else
+ log << TestLog::Message << "Subpass uses inlined commands" << TestLog::EndMessage;
+
+ for (deUint32 attachmentNdx = 0; attachmentNdx < info.getColorClears().size(); attachmentNdx++)
+ {
+ const ColorClear& colorClear = info.getColorClears()[attachmentNdx];
+
+ log << TestLog::Message << "Clearing color attachment " << attachmentNdx
+ << ". Offset: " << colorClear.getOffset()
+ << ", Size: " << colorClear.getSize()
+ << ", Color: " << clearColorToString(info.getColorAttachment(attachmentNdx).getFormat(), colorClear.getColor()) << TestLog::EndMessage;
+ }
+
+ if (info.getDepthStencilClear())
+ {
+ const DepthStencilClear& depthStencilClear = *info.getDepthStencilClear();
+
+ log << TestLog::Message << "Clearing depth stencil attachment"
+ << ". Offset: " << depthStencilClear.getOffset()
+ << ", Size: " << depthStencilClear.getSize()
+ << ", Depth: " << depthStencilClear.getDepth()
+ << ", Stencil: " << depthStencilClear.getStencil() << TestLog::EndMessage;
+ }
+
+ if (info.getRenderQuad())
+ {
+ const RenderQuad& renderQuad = *info.getRenderQuad();
+
+ log << TestLog::Message << "Rendering gradient quad to " << renderQuad.getCornerA() << " -> " << renderQuad.getCornerB() << TestLog::EndMessage;
+ }
+}
+
+void logTestCaseInfo (TestLog& log,
+ const TestConfig& config,
+ const vector<bool>& attachmentIsLazy,
+ const vector<Maybe<VkClearValue> >& imageClearValues,
+ const vector<Maybe<VkClearValue> >& renderPassClearValues,
+ const vector<SubpassRenderInfo>& subpassRenderInfo)
+{
+ const RenderPass& renderPass = config.renderPass;
+
+ logRenderPassInfo(log, renderPass);
+
+ DE_ASSERT(attachmentIsLazy.size() == renderPass.getAttachments().size());
+ DE_ASSERT(imageClearValues.size() == renderPass.getAttachments().size());
+ DE_ASSERT(renderPassClearValues.size() == renderPass.getAttachments().size());
+
+ log << TestLog::Message << "TargetSize: " << config.targetSize << TestLog::EndMessage;
+ log << TestLog::Message << "Render area, Offset: " << config.renderPos << ", Size: " << config.renderSize << TestLog::EndMessage;
+
+ for (size_t attachmentNdx = 0; attachmentNdx < attachmentIsLazy.size(); attachmentNdx++)
+ {
+ const tcu::ScopedLogSection section (log, "Attachment" + de::toString(attachmentNdx), "Attachment " + de::toString(attachmentNdx));
+
+ if (attachmentIsLazy[attachmentNdx])
+ log << TestLog::Message << "Is lazy." << TestLog::EndMessage;
+
+ if (imageClearValues[attachmentNdx])
+ log << TestLog::Message << "Image is cleared to " << clearValueToString(renderPass.getAttachments()[attachmentNdx].getFormat(), *imageClearValues[attachmentNdx]) << " before rendering." << TestLog::EndMessage;
+
+ if (renderPass.getAttachments()[attachmentNdx].getLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR && renderPassClearValues[attachmentNdx])
+ log << TestLog::Message << "Attachment is cleared to " << clearValueToString(renderPass.getAttachments()[attachmentNdx].getFormat(), *renderPassClearValues[attachmentNdx]) << " in the beginning of the render pass." << TestLog::EndMessage;
+ }
+
+ for (size_t subpassNdx = 0; subpassNdx < renderPass.getSubpasses().size(); subpassNdx++)
+ {
+ const tcu::ScopedLogSection section (log, "Subpass" + de::toString(subpassNdx), "Subpass " + de::toString(subpassNdx));
+
+ logSubpassRenderInfo(log, subpassRenderInfo[subpassNdx]);
+ }
+}
+
+void initializeSubpassRenderInfo (vector<SubpassRenderInfo>& renderInfos, de::Random& rng, const RenderPass& renderPass, const TestConfig& config)
+{
+ const TestConfig::CommandBufferTypes commandBuffer = config.commandBufferTypes;
+ const vector<Subpass>& subpasses = renderPass.getSubpasses();
+ bool lastSubpassWasSecondary = false;
+
+ for (deUint32 subpassNdx = 0; subpassNdx < (deUint32)subpasses.size(); subpassNdx++)
+ {
+ const Subpass& subpass = subpasses[subpassNdx];
+ const bool subpassIsSecondary = commandBuffer == TestConfig::COMMANDBUFFERTYPES_SECONDARY
+ || (commandBuffer & TestConfig::COMMANDBUFFERTYPES_SECONDARY && !lastSubpassWasSecondary) ? true : false;
+ const UVec2 viewportSize ((config.renderSize * UVec2(2)) / UVec2(3));
+ const UVec2 viewportOffset (config.renderPos.x() + (subpassNdx % 2) * (config.renderSize.x() / 3),
+ config.renderPos.y() + ((subpassNdx / 2) % 2) * (config.renderSize.y() / 3));
+
+ vector<ColorClear> colorClears;
+ Maybe<DepthStencilClear> depthStencilClear;
+ Maybe<RenderQuad> renderQuad;
+
+ lastSubpassWasSecondary = subpassIsSecondary;
+
+ if (config.renderTypes & TestConfig::RENDERTYPES_CLEAR)
+ {
+ const vector<AttachmentReference>& colorAttachments = subpass.getColorAttachments();
+
+ for (size_t attachmentRefNdx = 0; attachmentRefNdx < colorAttachments.size(); attachmentRefNdx++)
+ {
+ const AttachmentReference& attachmentRef = colorAttachments[attachmentRefNdx];
+ const Attachment& attachment = renderPass.getAttachments()[attachmentRef.getAttachment()];
+ const UVec2 size ((viewportSize * UVec2(2)) / UVec2(3));
+ const UVec2 offset (viewportOffset.x() + ((deUint32)attachmentRefNdx % 2u) * (viewportSize.x() / 3u),
+ viewportOffset.y() + (((deUint32)attachmentRefNdx / 2u) % 2u) * (viewportSize.y() / 3u));
+ const VkClearColorValue color = randomColorClearValue(attachment, rng);
+
+ colorClears.push_back(ColorClear(offset, size, color));
+ }
+
+ if (subpass.getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED)
+ {
+ const Attachment& attachment = renderPass.getAttachments()[subpass.getDepthStencilAttachment().getAttachment()];
+ const UVec2 size ((viewportSize * UVec2(2)) / UVec2(3));
+ const UVec2 offset (viewportOffset.x() + ((deUint32)colorAttachments.size() % 2u) * (viewportSize.x() / 3u),
+ viewportOffset.y() + (((deUint32)colorAttachments.size() / 2u) % 2u) * (viewportSize.y() / 3u));
+ const VkClearValue value = randomClearValue(attachment, rng);
+
+ depthStencilClear = tcu::just(DepthStencilClear(offset, size, value.depthStencil.depth, value.depthStencil.stencil));
+ }
+ }
+
+ if (config.renderTypes & TestConfig::RENDERTYPES_DRAW)
+ renderQuad = tcu::just(RenderQuad(tcu::Vec4(-0.5f, -0.5f, 0.0f, 1.0f), tcu::Vec4(0.5f, 0.5f, 1.0f, 1.0f)));
+
+ renderInfos.push_back(SubpassRenderInfo(renderPass, subpassNdx, subpassIsSecondary, viewportOffset, viewportSize, renderQuad, colorClears, depthStencilClear));
+ }
+}
+
+void checkTextureFormatSupport (TestLog& log,
+ const InstanceInterface& vk,
+ VkPhysicalDevice device,
+ const vector<Attachment>& attachments)
+{
+ bool supported = true;
+
+ for (size_t attachmentNdx = 0; attachmentNdx < attachments.size(); attachmentNdx++)
+ {
+ const Attachment& attachment = attachments[attachmentNdx];
+ const tcu::TextureFormat format = mapVkFormat(attachment.getFormat());
+ const bool isDepthOrStencilAttachment = hasDepthComponent(format.order) || hasStencilComponent(format.order);
+ const VkFormatFeatureFlags flags = isDepthOrStencilAttachment? VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT : VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
+ VkFormatProperties properties;
+
+ vk.getPhysicalDeviceFormatProperties(device, attachment.getFormat(), &properties);
+
+ if ((properties.optimalTilingFeatures & flags) != flags)
+ {
+ supported = false;
+ log << TestLog::Message << "Format: " << attachment.getFormat() << " not supported as " << (isDepthOrStencilAttachment ? "depth stencil attachment" : "color attachment") << TestLog::EndMessage;
+ }
+ }
+
+ if (!supported)
+ TCU_THROW(NotSupportedError, "Format not supported");
+}
+
+tcu::TestStatus renderPassTest (Context& context, TestConfig config)
+{
+ const UVec2 targetSize = config.targetSize;
+ const UVec2 renderPos = config.renderPos;
+ const UVec2 renderSize = config.renderSize;
+ const RenderPass& renderPassInfo = config.renderPass;
+
+ TestLog& log = context.getTestContext().getLog();
+ de::Random rng (config.seed);
+
+ vector<bool> attachmentIsLazy;
+ vector<Maybe<VkClearValue> > imageClearValues;
+ vector<Maybe<VkClearValue> > renderPassClearValues;
+
+ vector<bool> subpassIsSecondary;
+ vector<SubpassRenderInfo> subpassRenderInfo;
+ vector<vector<VkClearColorValue> > subpassColorClearValues;
+
+ initializeAttachmentIsLazy(attachmentIsLazy, renderPassInfo.getAttachments(), config.imageMemory);
+ initializeImageClearValues(rng, imageClearValues, renderPassInfo.getAttachments(), attachmentIsLazy);
+ initializeRenderPassClearValues(rng, renderPassClearValues, renderPassInfo.getAttachments());
+
+ initializeSubpassIsSecondary(subpassIsSecondary, renderPassInfo.getSubpasses(), config.commandBufferTypes);
+ initializeSubpassClearValues(rng, subpassColorClearValues, renderPassInfo);
+ initializeSubpassRenderInfo(subpassRenderInfo, rng, renderPassInfo, config);
+
+ logTestCaseInfo(log, config, attachmentIsLazy, imageClearValues, renderPassClearValues, subpassRenderInfo);
+
+ checkTextureFormatSupport(log, context.getInstanceInterface(), context.getPhysicalDevice(), config.renderPass.getAttachments());
+
+ {
+ const VkDevice device = context.getDevice();
+ const DeviceInterface& vk = context.getDeviceInterface();
+ const VkQueue queue = context.getUniversalQueue();
+ const deUint32 queueIndex = context.getUniversalQueueFamilyIndex();
+ Allocator& allocator = context.getDefaultAllocator();
+
+ const Unique<VkRenderPass> renderPass (createRenderPass(vk, device, renderPassInfo));
+ const Unique<VkCommandPool> commandBufferPool (createCommandPool(vk, device, queueIndex, 0));
+ const Unique<VkCommandBuffer> initializeImagesCommandBuffer (allocateCommandBuffer(vk, device, *commandBufferPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
+ const Unique<VkCommandBuffer> renderCommandBuffer (allocateCommandBuffer(vk, device, *commandBufferPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
+ const Unique<VkCommandBuffer> readImagesToBuffersCommandBuffer (allocateCommandBuffer(vk, device, *commandBufferPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
+
+ vector<de::SharedPtr<AttachmentResources> > attachmentResources;
+ vector<de::SharedPtr<SubpassRenderer> > subpassRenderers;
+ vector<VkImageView> attachmentViews;
+
+ for (size_t attachmentNdx = 0; attachmentNdx < renderPassInfo.getAttachments().size(); attachmentNdx++)
+ {
+ const Attachment& attachmentInfo = renderPassInfo.getAttachments()[attachmentNdx];
+
+ attachmentResources.push_back(de::SharedPtr<AttachmentResources>(new AttachmentResources(vk, device, allocator, queueIndex, targetSize, attachmentInfo, attachmentIsLazy[attachmentNdx])));
+ attachmentViews.push_back(attachmentResources[attachmentNdx]->getAttachmentView());
+ }
+
+ beginCommandBuffer(vk, *initializeImagesCommandBuffer, (VkCommandBufferUsageFlags)0, DE_NULL, 0, DE_NULL, VK_FALSE, (VkQueryControlFlags)0, (VkQueryPipelineStatisticFlags)0);
+ pushImageInitializationCommands(vk, *initializeImagesCommandBuffer, renderPassInfo.getAttachments(), attachmentResources, queueIndex, imageClearValues);
+ endCommandBuffer(vk, *initializeImagesCommandBuffer);
+
+ {
+ const Unique<VkFramebuffer> framebuffer (createFramebuffer(vk, device, *renderPass, targetSize, attachmentViews));
+
+ for (size_t subpassNdx = 0; subpassNdx < renderPassInfo.getSubpasses().size(); subpassNdx++)
+ subpassRenderers.push_back(de::SharedPtr<SubpassRenderer>(new SubpassRenderer(context, vk, device, allocator, *renderPass, *framebuffer, *commandBufferPool, queueIndex, subpassRenderInfo[subpassNdx])));
+
+ beginCommandBuffer(vk, *renderCommandBuffer, (VkCommandBufferUsageFlags)0, DE_NULL, 0, DE_NULL, VK_FALSE, (VkQueryControlFlags)0, (VkQueryPipelineStatisticFlags)0);
+ pushRenderPassCommands(vk, *renderCommandBuffer, *renderPass, *framebuffer, subpassRenderers, renderPos, renderSize, renderPassClearValues, config.renderTypes);
+ endCommandBuffer(vk, *renderCommandBuffer);
+
+ beginCommandBuffer(vk, *readImagesToBuffersCommandBuffer, (VkCommandBufferUsageFlags)0, DE_NULL, 0, DE_NULL, VK_FALSE, (VkQueryControlFlags)0, (VkQueryPipelineStatisticFlags)0);
+ pushReadImagesToBuffers(vk, *readImagesToBuffersCommandBuffer, queueIndex, attachmentResources, renderPassInfo.getAttachments(), attachmentIsLazy, targetSize);
+ endCommandBuffer(vk, *readImagesToBuffersCommandBuffer);
+ {
+ const VkCommandBuffer commandBuffers[] =
+ {
+ *initializeImagesCommandBuffer,
+ *renderCommandBuffer,
+ *readImagesToBuffersCommandBuffer
+ };
+ const Unique<VkFence> fence (createFence(vk, device, 0u));
+
+ queueSubmit(vk, queue, DE_LENGTH_OF_ARRAY(commandBuffers), commandBuffers, *fence);
+ waitForFences(vk, device, 1, &fence.get(), VK_TRUE, ~0ull);
+ }
+ }
+
+ if (logAndVerifyImages(log, vk, device, attachmentResources, attachmentIsLazy, renderPassInfo, renderPassClearValues, imageClearValues, subpassRenderInfo, targetSize, config))
+ return tcu::TestStatus::pass("Pass");
+ else
+ return tcu::TestStatus::fail("Result verification failed");
+ }
+}
+
+// \todo Fill with actually required formats in the future
+static const VkFormat s_colorFormats[] =
+{
+ VK_FORMAT_R5G6B5_UNORM_PACK16,
+ VK_FORMAT_R5G5B5A1_UNORM_PACK16,
+ VK_FORMAT_R8_UNORM,
+ VK_FORMAT_R8_SNORM,
+ VK_FORMAT_R8_UINT,
+ VK_FORMAT_R8_SINT,
+ VK_FORMAT_R8G8_UNORM,
+ VK_FORMAT_R8G8_SNORM,
+ VK_FORMAT_R8G8_UINT,
+ VK_FORMAT_R8G8_SINT,
+ VK_FORMAT_R8G8B8_UNORM,
+ VK_FORMAT_R8G8B8_SNORM,
+ VK_FORMAT_R8G8B8_UINT,
+ VK_FORMAT_R8G8B8_SINT,
+ VK_FORMAT_R8G8B8_SRGB,
+ VK_FORMAT_R8G8B8A8_UNORM,
+ VK_FORMAT_R8G8B8A8_SNORM,
+ VK_FORMAT_R8G8B8A8_UINT,
+ VK_FORMAT_R8G8B8A8_SINT,
+ VK_FORMAT_R8G8B8A8_SRGB,
+ VK_FORMAT_R16_UNORM,
+ VK_FORMAT_R16_SNORM,
+ VK_FORMAT_R16_UINT,
+ VK_FORMAT_R16_SINT,
+ VK_FORMAT_R16_SFLOAT,
+ VK_FORMAT_R16G16_UNORM,
+ VK_FORMAT_R16G16_SNORM,
+ VK_FORMAT_R16G16_UINT,
+ VK_FORMAT_R16G16_SINT,
+ VK_FORMAT_R16G16_SFLOAT,
+ VK_FORMAT_R16G16B16_UNORM,
+ VK_FORMAT_R16G16B16_SNORM,
+ VK_FORMAT_R16G16B16_UINT,
+ VK_FORMAT_R16G16B16_SINT,
+ VK_FORMAT_R16G16B16_SFLOAT,
+ VK_FORMAT_R16G16B16A16_UNORM,
+ VK_FORMAT_R16G16B16A16_SNORM,
+ VK_FORMAT_R16G16B16A16_UINT,
+ VK_FORMAT_R16G16B16A16_SINT,
+ VK_FORMAT_R16G16B16A16_SFLOAT,
+ VK_FORMAT_R32_UINT,
+ VK_FORMAT_R32_SINT,
+ VK_FORMAT_R32_SFLOAT,
+ VK_FORMAT_R32G32_UINT,
+ VK_FORMAT_R32G32_SINT,
+ VK_FORMAT_R32G32_SFLOAT,
+ VK_FORMAT_R32G32B32_UINT,
+ VK_FORMAT_R32G32B32_SINT,
+ VK_FORMAT_R32G32B32_SFLOAT,
+ VK_FORMAT_R32G32B32A32_UINT,
+ VK_FORMAT_R32G32B32A32_SINT,
+ VK_FORMAT_R32G32B32A32_SFLOAT
+};
+
+static const VkFormat s_depthStencilFormats[] =
+{
+ VK_FORMAT_D16_UNORM,
+ VK_FORMAT_X8_D24_UNORM_PACK32,
+ VK_FORMAT_D32_SFLOAT,
+ VK_FORMAT_S8_UINT,
+ VK_FORMAT_D24_UNORM_S8_UINT
+};
+
+de::MovePtr<tcu::TestCaseGroup> createAttachmentTestCaseGroup (tcu::TestContext& testCtx)
+{
+ const deUint32 attachmentCounts[] = { 1, 3, 8 };
+ const VkAttachmentLoadOp loadOps[] =
+ {
+ VK_ATTACHMENT_LOAD_OP_LOAD,
+ VK_ATTACHMENT_LOAD_OP_CLEAR,
+ VK_ATTACHMENT_LOAD_OP_DONT_CARE
+ };
+
+ const VkAttachmentStoreOp storeOps[] =
+ {
+ VK_ATTACHMENT_STORE_OP_STORE,
+ VK_ATTACHMENT_STORE_OP_DONT_CARE
+ };
+
+ const VkImageLayout initialAndFinalColorLayouts[] =
+ {
+ VK_IMAGE_LAYOUT_GENERAL,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
+ };
+
+ const VkImageLayout initialAndFinalDepthStencilLayouts[] =
+ {
+ VK_IMAGE_LAYOUT_GENERAL,
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL,
+ VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
+ };
+
+ const VkImageLayout subpassLayouts[] =
+ {
+ VK_IMAGE_LAYOUT_GENERAL,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
+ };
+
+ const VkImageLayout depthStencilLayouts[] =
+ {
+ VK_IMAGE_LAYOUT_GENERAL,
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
+ };
+
+ const TestConfig::RenderTypes renderCommands[] =
+ {
+ TestConfig::RENDERTYPES_NONE,
+ TestConfig::RENDERTYPES_CLEAR,
+ TestConfig::RENDERTYPES_DRAW,
+ TestConfig::RENDERTYPES_CLEAR|TestConfig::RENDERTYPES_DRAW,
+ };
+
+ const TestConfig::CommandBufferTypes commandBuffers[] =
+ {
+ TestConfig::COMMANDBUFFERTYPES_INLINE,
+ TestConfig::COMMANDBUFFERTYPES_SECONDARY,
+ TestConfig::COMMANDBUFFERTYPES_INLINE|TestConfig::COMMANDBUFFERTYPES_SECONDARY
+ };
+
+ const TestConfig::ImageMemory imageMemories[] =
+ {
+ TestConfig::IMAGEMEMORY_STRICT,
+ TestConfig::IMAGEMEMORY_LAZY,
+ TestConfig::IMAGEMEMORY_STRICT|TestConfig::IMAGEMEMORY_LAZY
+ };
+
+ const UVec2 targetSizes[] =
+ {
+ UVec2(64, 64),
+ UVec2(63, 65)
+ };
+
+ const UVec2 renderPositions[] =
+ {
+ UVec2(0, 0),
+ UVec2(3, 17)
+ };
+
+ const UVec2 renderSizes[] =
+ {
+ UVec2(32, 32),
+ UVec2(60, 47)
+ };
+
+ de::Random rng (1433774382u);
+ de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "attachment", "Attachment format and count tests with load and store ops and image layouts"));
+
+ for (size_t attachmentCountNdx = 0; attachmentCountNdx < DE_LENGTH_OF_ARRAY(attachmentCounts); attachmentCountNdx++)
+ {
+ const deUint32 attachmentCount = attachmentCounts[attachmentCountNdx];
+ const deUint32 testCaseCount = (attachmentCount == 1 ? 100 : 200);
+ de::MovePtr<tcu::TestCaseGroup> attachmentCountGroup (new tcu::TestCaseGroup(testCtx, de::toString(attachmentCount).c_str(), de::toString(attachmentCount).c_str()));
+
+ for (size_t testCaseNdx = 0; testCaseNdx < testCaseCount; testCaseNdx++)
+ {
+ const bool useDepthStencil = rng.getBool();
+ VkImageLayout depthStencilLayout = VK_IMAGE_LAYOUT_GENERAL;
+ vector<Attachment> attachments;
+ vector<AttachmentReference> colorAttachmentReferences;
+
+ for (size_t attachmentNdx = 0; attachmentNdx < attachmentCount; attachmentNdx++)
+ {
+ const VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT;
+ const VkFormat format = rng.choose<VkFormat>(DE_ARRAY_BEGIN(s_colorFormats), DE_ARRAY_END(s_colorFormats));
+ const VkAttachmentLoadOp loadOp = rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps));
+ const VkAttachmentStoreOp storeOp = rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps));
+
+ const VkImageLayout initialLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalColorLayouts), DE_ARRAY_END(initialAndFinalColorLayouts));
+ const VkImageLayout finalizeLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalColorLayouts), DE_ARRAY_END(initialAndFinalColorLayouts));
+ const VkImageLayout subpassLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(subpassLayouts), DE_ARRAY_END(subpassLayouts));
+
+ const VkAttachmentLoadOp stencilLoadOp = rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps));
+ const VkAttachmentStoreOp stencilStoreOp = rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps));
+
+ attachments.push_back(Attachment(format, sampleCount, loadOp, storeOp, stencilLoadOp, stencilStoreOp, initialLayout, finalizeLayout));
+ colorAttachmentReferences.push_back(AttachmentReference((deUint32)attachmentNdx, subpassLayout));
+ }
+
+ if (useDepthStencil)
+ {
+ const VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT;
+ const VkFormat format = rng.choose<VkFormat>(DE_ARRAY_BEGIN(s_depthStencilFormats), DE_ARRAY_END(s_depthStencilFormats));
+ const VkAttachmentLoadOp loadOp = rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps));
+ const VkAttachmentStoreOp storeOp = rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps));
+
+ const VkImageLayout initialLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalDepthStencilLayouts), DE_ARRAY_END(initialAndFinalDepthStencilLayouts));
+ const VkImageLayout finalizeLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalDepthStencilLayouts), DE_ARRAY_END(initialAndFinalDepthStencilLayouts));
+
+ const VkAttachmentLoadOp stencilLoadOp = rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps));
+ const VkAttachmentStoreOp stencilStoreOp = rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps));
+
+ depthStencilLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(depthStencilLayouts), DE_ARRAY_END(depthStencilLayouts));
+ attachments.push_back(Attachment(format, sampleCount, loadOp, storeOp, stencilLoadOp, stencilStoreOp, initialLayout, finalizeLayout));
+ }
+
+ {
+ const TestConfig::RenderTypes render = rng.choose<TestConfig::RenderTypes>(DE_ARRAY_BEGIN(renderCommands), DE_ARRAY_END(renderCommands));
+ const TestConfig::CommandBufferTypes commandBuffer = rng.choose<TestConfig::CommandBufferTypes>(DE_ARRAY_BEGIN(commandBuffers), DE_ARRAY_END(commandBuffers));
+ const TestConfig::ImageMemory imageMemory = rng.choose<TestConfig::ImageMemory>(DE_ARRAY_BEGIN(imageMemories), DE_ARRAY_END(imageMemories));
+ const vector<Subpass> subpasses (1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(), colorAttachmentReferences, vector<AttachmentReference>(), AttachmentReference((useDepthStencil ? (deUint32)(attachments.size() - 1) : VK_ATTACHMENT_UNUSED), depthStencilLayout), vector<AttachmentReference>()));
+ const vector<SubpassDependency> deps;
+
+ const string testCaseName = de::toString(attachmentCountNdx * testCaseCount + testCaseNdx);
+ const RenderPass renderPass (attachments, subpasses, deps);
+ const UVec2 targetSize = rng.choose<UVec2>(DE_ARRAY_BEGIN(targetSizes), DE_ARRAY_END(targetSizes));
+ const UVec2 renderPos = rng.choose<UVec2>(DE_ARRAY_BEGIN(renderPositions), DE_ARRAY_END(renderPositions));
+ const UVec2 renderSize = rng.choose<UVec2>(DE_ARRAY_BEGIN(renderSizes), DE_ARRAY_END(renderSizes));
+
+ addFunctionCaseWithPrograms<TestConfig>(attachmentCountGroup.get(), testCaseName.c_str(), testCaseName.c_str(), createTestShaders, renderPassTest, TestConfig(renderPass, render, commandBuffer, imageMemory, targetSize, renderPos, renderSize, 1293809));
+ }
+ }
+
+ group->addChild(attachmentCountGroup.release());
+ }
+
+ return group;
+}
+
+de::MovePtr<tcu::TestCaseGroup> createAttachmentAllocationTestGroup (tcu::TestContext& testCtx)
+{
+ const deUint32 attachmentCounts[] = { 4, 8 };
+ const VkAttachmentLoadOp loadOps[] =
+ {
+ VK_ATTACHMENT_LOAD_OP_LOAD,
+ VK_ATTACHMENT_LOAD_OP_CLEAR,
+ VK_ATTACHMENT_LOAD_OP_DONT_CARE
+ };
+
+ const VkAttachmentStoreOp storeOps[] =
+ {
+ VK_ATTACHMENT_STORE_OP_STORE,
+ VK_ATTACHMENT_STORE_OP_DONT_CARE
+ };
+
+ const VkImageLayout initialAndFinalLayouts[] =
+ {
+ VK_IMAGE_LAYOUT_GENERAL,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL,
+ VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
+ };
+
+ const VkImageLayout subpassLayouts[] =
+ {
+ VK_IMAGE_LAYOUT_GENERAL,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ };
+
+ enum AllocationType
+ {
+ // Each pass uses one more attachmen than previous one
+ ALLOCATIONTYPE_GROW,
+ // Each pass uses one less attachment than previous one
+ ALLOCATIONTYPE_SHRINK,
+ // Each pass drops one attachment and picks up new one
+ ALLOCATIONTYPE_ROLL,
+ // Start by growing and end by shrinking
+ ALLOCATIONTYPE_GROW_SHRINK
+ };
+
+ const AllocationType allocationTypes[] =
+ {
+ ALLOCATIONTYPE_GROW,
+ ALLOCATIONTYPE_SHRINK,
+ ALLOCATIONTYPE_ROLL,
+ ALLOCATIONTYPE_GROW_SHRINK
+ };
+
+ const char* const allocationTypeStr[] =
+ {
+ "grow",
+ "shrink",
+ "roll",
+ "grow_shrink"
+ };
+
+ const TestConfig::RenderTypes renderCommands[] =
+ {
+ TestConfig::RENDERTYPES_NONE,
+ TestConfig::RENDERTYPES_CLEAR,
+ TestConfig::RENDERTYPES_DRAW,
+ TestConfig::RENDERTYPES_CLEAR|TestConfig::RENDERTYPES_DRAW,
+ };
+
+ const TestConfig::CommandBufferTypes commandBuffers[] =
+ {
+ TestConfig::COMMANDBUFFERTYPES_INLINE,
+ TestConfig::COMMANDBUFFERTYPES_SECONDARY,
+ TestConfig::COMMANDBUFFERTYPES_INLINE|TestConfig::COMMANDBUFFERTYPES_SECONDARY
+ };
+
+ const TestConfig::ImageMemory imageMemories[] =
+ {
+ TestConfig::IMAGEMEMORY_STRICT,
+ TestConfig::IMAGEMEMORY_LAZY,
+ TestConfig::IMAGEMEMORY_STRICT|TestConfig::IMAGEMEMORY_LAZY
+ };
+
+ const UVec2 targetSizes[] =
+ {
+ UVec2(64, 64),
+ UVec2(63, 65)
+ };
+
+ const UVec2 renderPositions[] =
+ {
+ UVec2(0, 0),
+ UVec2(3, 17)
+ };
+
+ const UVec2 renderSizes[] =
+ {
+ UVec2(32, 32),
+ UVec2(60, 47)
+ };
+
+ de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "attachment_allocation", "Attachment allocation tests"));
+ de::Random rng (3700649827u);
+
+ for (size_t allocationTypeNdx = 0; allocationTypeNdx < DE_LENGTH_OF_ARRAY(allocationTypes); allocationTypeNdx++)
+ {
+ const AllocationType allocationType = allocationTypes[allocationTypeNdx];
+ const size_t testCaseCount = 100;
+ de::MovePtr<tcu::TestCaseGroup> allocationTypeGroup (new tcu::TestCaseGroup(testCtx, allocationTypeStr[allocationTypeNdx], allocationTypeStr[allocationTypeNdx]));
+
+ for (size_t testCaseNdx = 0; testCaseNdx < testCaseCount; testCaseNdx++)
+ {
+ const deUint32 attachmentCount = rng.choose<deUint32>(DE_ARRAY_BEGIN(attachmentCounts), DE_ARRAY_END(attachmentCounts));
+ vector<Attachment> attachments;
+ vector<Subpass> subpasses;
+
+ for (size_t attachmentNdx = 0; attachmentNdx < attachmentCount; attachmentNdx++)
+ {
+ const VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT;
+ const VkFormat format = rng.choose<VkFormat>(DE_ARRAY_BEGIN(s_colorFormats), DE_ARRAY_END(s_colorFormats));
+ const VkAttachmentLoadOp loadOp = rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps));
+ const VkAttachmentStoreOp storeOp = rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps));
+
+ const VkImageLayout initialLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalLayouts), DE_ARRAY_END(initialAndFinalLayouts));
+ const VkImageLayout finalizeLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalLayouts), DE_ARRAY_END(initialAndFinalLayouts));
+
+ const VkAttachmentLoadOp stencilLoadOp = rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps));
+ const VkAttachmentStoreOp stencilStoreOp = rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps));
+
+ attachments.push_back(Attachment(format, sampleCount, loadOp, storeOp, stencilLoadOp, stencilStoreOp, initialLayout, finalizeLayout));
+ }
+
+ if (allocationType == ALLOCATIONTYPE_GROW)
+ {
+ for (size_t subpassNdx = 0; subpassNdx < attachmentCount; subpassNdx++)
+ {
+ vector<AttachmentReference> colorAttachmentReferences;
+
+ for (size_t attachmentNdx = 0; attachmentNdx < subpassNdx + 1; attachmentNdx++)
+ {
+ const VkImageLayout subpassLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(subpassLayouts), DE_ARRAY_END(subpassLayouts));
+
+ colorAttachmentReferences.push_back(AttachmentReference((deUint32)attachmentNdx, subpassLayout));
+ }
+
+ subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(), colorAttachmentReferences, vector<AttachmentReference>(), AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), vector<AttachmentReference>()));
+ }
+ }
+ else if (allocationType == ALLOCATIONTYPE_SHRINK)
+ {
+ for (size_t subpassNdx = 0; subpassNdx < attachmentCount; subpassNdx++)
+ {
+ vector<AttachmentReference> colorAttachmentReferences;
+
+ for (size_t attachmentNdx = 0; attachmentNdx < (attachmentCount - subpassNdx); attachmentNdx++)
+ {
+ const VkImageLayout subpassLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(subpassLayouts), DE_ARRAY_END(subpassLayouts));
+
+ colorAttachmentReferences.push_back(AttachmentReference((deUint32)attachmentNdx, subpassLayout));
+ }
+
+ subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(), colorAttachmentReferences, vector<AttachmentReference>(), AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), vector<AttachmentReference>()));
+ }
+ }
+ else if (allocationType == ALLOCATIONTYPE_ROLL)
+ {
+ for (size_t subpassNdx = 0; subpassNdx < attachmentCount / 2; subpassNdx++)
+ {
+ vector<AttachmentReference> colorAttachmentReferences;
+
+ for (size_t attachmentNdx = 0; attachmentNdx < attachmentCount / 2; attachmentNdx++)
+ {
+ const VkImageLayout subpassLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(subpassLayouts), DE_ARRAY_END(subpassLayouts));
+
+ colorAttachmentReferences.push_back(AttachmentReference((deUint32)(subpassNdx + attachmentNdx), subpassLayout));
+ }
+
+ subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(), colorAttachmentReferences, vector<AttachmentReference>(), AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), vector<AttachmentReference>()));
+ }
+ }
+ else if (allocationType == ALLOCATIONTYPE_GROW_SHRINK)
+ {
+ for (size_t subpassNdx = 0; subpassNdx < attachmentCount; subpassNdx++)
+ {
+ vector<AttachmentReference> colorAttachmentReferences;
+
+ for (size_t attachmentNdx = 0; attachmentNdx < subpassNdx + 1; attachmentNdx++)
+ {
+ const VkImageLayout subpassLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(subpassLayouts), DE_ARRAY_END(subpassLayouts));
+
+ colorAttachmentReferences.push_back(AttachmentReference((deUint32)attachmentNdx, subpassLayout));
+ }
+
+ subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(), colorAttachmentReferences, vector<AttachmentReference>(), AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), vector<AttachmentReference>()));
+ }
+
+ for (size_t subpassNdx = 0; subpassNdx < attachmentCount; subpassNdx++)
+ {
+ vector<AttachmentReference> colorAttachmentReferences;
+
+ for (size_t attachmentNdx = 0; attachmentNdx < (attachmentCount - subpassNdx); attachmentNdx++)
+ {
+ const VkImageLayout subpassLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(subpassLayouts), DE_ARRAY_END(subpassLayouts));
+
+ colorAttachmentReferences.push_back(AttachmentReference((deUint32)attachmentNdx, subpassLayout));
+ }
+
+ subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(), colorAttachmentReferences, vector<AttachmentReference>(), AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), vector<AttachmentReference>()));
+ }
+ }
+ else
+ DE_FATAL("Unknown allocation type");
+
+ {
+ const TestConfig::RenderTypes render = rng.choose<TestConfig::RenderTypes>(DE_ARRAY_BEGIN(renderCommands), DE_ARRAY_END(renderCommands));
+ const TestConfig::CommandBufferTypes commandBuffer = rng.choose<TestConfig::CommandBufferTypes>(DE_ARRAY_BEGIN(commandBuffers), DE_ARRAY_END(commandBuffers));
+ const TestConfig::ImageMemory imageMemory = rng.choose<TestConfig::ImageMemory>(DE_ARRAY_BEGIN(imageMemories), DE_ARRAY_END(imageMemories));
+
+ const string testCaseName = de::toString(testCaseNdx);
+ const UVec2 targetSize = rng.choose<UVec2>(DE_ARRAY_BEGIN(targetSizes), DE_ARRAY_END(targetSizes));
+ const UVec2 renderPos = rng.choose<UVec2>(DE_ARRAY_BEGIN(renderPositions), DE_ARRAY_END(renderPositions));
+ const UVec2 renderSize = rng.choose<UVec2>(DE_ARRAY_BEGIN(renderSizes), DE_ARRAY_END(renderSizes));
+
+ vector<SubpassDependency> deps;
+
+ for (size_t subpassNdx = 0; subpassNdx < subpasses.size() - 1; subpassNdx++)
+ {
+ const bool byRegion = rng.getBool();
+ deps.push_back(SubpassDependency((deUint32)subpassNdx, (deUint32)subpassNdx + 1,
+ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
+ | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
+ | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
+ | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
+
+ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
+ | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
+ | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
+ | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
+
+ VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
+ VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, // \todo [pyry] Correct?
+
+ byRegion ? (VkBool32)VK_TRUE : (VkBool32)VK_FALSE));
+ }
+
+ const RenderPass renderPass (attachments, subpasses, deps);
+
+ addFunctionCaseWithPrograms<TestConfig>(allocationTypeGroup.get(), testCaseName.c_str(), testCaseName.c_str(), createTestShaders, renderPassTest, TestConfig(renderPass, render, commandBuffer, imageMemory, targetSize, renderPos, renderSize, 80329));
+ }
+ }
+
+ group->addChild(allocationTypeGroup.release());
+ }
+
+ return group;
+}
+
+de::MovePtr<tcu::TestCaseGroup> createSimpleTestGroup (tcu::TestContext& testCtx)
+{
+ const UVec2 targetSize (64, 64);
+ const UVec2 renderPos (0, 0);
+ const UVec2 renderSize (64, 64);
+ de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "simple", "Simple basic render pass tests"));
+
+ // color
+ {
+ const RenderPass renderPass (vector<Attachment>(1, Attachment(VK_FORMAT_R8G8B8A8_UNORM,
+ VK_SAMPLE_COUNT_1_BIT,
+ VK_ATTACHMENT_LOAD_OP_CLEAR,
+ VK_ATTACHMENT_STORE_OP_STORE,
+ VK_ATTACHMENT_LOAD_OP_DONT_CARE,
+ VK_ATTACHMENT_STORE_OP_DONT_CARE,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
+ vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS,
+ 0u,
+ vector<AttachmentReference>(),
+ vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
+ vector<AttachmentReference>(),
+ AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL),
+ vector<AttachmentReference>())),
+ vector<SubpassDependency>());
+
+ addFunctionCaseWithPrograms<TestConfig>(group.get(), "color", "Single color attachment case.", createTestShaders, renderPassTest, TestConfig(renderPass, TestConfig::RENDERTYPES_DRAW, TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, 90239));
+ }
+
+ // depth
+ {
+ const RenderPass renderPass (vector<Attachment>(1, Attachment(VK_FORMAT_X8_D24_UNORM_PACK32,
+ VK_SAMPLE_COUNT_1_BIT,
+ VK_ATTACHMENT_LOAD_OP_CLEAR,
+ VK_ATTACHMENT_STORE_OP_STORE,
+ VK_ATTACHMENT_LOAD_OP_DONT_CARE,
+ VK_ATTACHMENT_STORE_OP_DONT_CARE,
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)),
+ vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS,
+ 0u,
+ vector<AttachmentReference>(),
+ vector<AttachmentReference>(),
+ vector<AttachmentReference>(),
+ AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
+ vector<AttachmentReference>())),
+ vector<SubpassDependency>());
+
+ addFunctionCaseWithPrograms<TestConfig>(group.get(), "depth", "Single depth attachment case.", createTestShaders, renderPassTest, TestConfig(renderPass, TestConfig::RENDERTYPES_DRAW, TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, 90239));
+ }
+
+ // stencil
+ {
+ const RenderPass renderPass (vector<Attachment>(1, Attachment(VK_FORMAT_S8_UINT,
+ VK_SAMPLE_COUNT_1_BIT,
+ VK_ATTACHMENT_LOAD_OP_DONT_CARE,
+ VK_ATTACHMENT_STORE_OP_DONT_CARE,
+ VK_ATTACHMENT_LOAD_OP_CLEAR,
+ VK_ATTACHMENT_STORE_OP_STORE,
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)),
+ vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS,
+ 0u,
+ vector<AttachmentReference>(),
+ vector<AttachmentReference>(),
+ vector<AttachmentReference>(),
+ AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
+ vector<AttachmentReference>())),
+ vector<SubpassDependency>());
+
+ addFunctionCaseWithPrograms<TestConfig>(group.get(), "stencil", "Single stencil attachment case.", createTestShaders, renderPassTest, TestConfig(renderPass, TestConfig::RENDERTYPES_DRAW, TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, 90239));
+ }
+
+ // depth_stencil
+ {
+ const RenderPass renderPass (vector<Attachment>(1, Attachment(VK_FORMAT_D24_UNORM_S8_UINT,
+ VK_SAMPLE_COUNT_1_BIT,
+ VK_ATTACHMENT_LOAD_OP_CLEAR,
+ VK_ATTACHMENT_STORE_OP_STORE,
+ VK_ATTACHMENT_LOAD_OP_CLEAR,
+ VK_ATTACHMENT_STORE_OP_STORE,
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)),
+ vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS,
+ 0u,
+ vector<AttachmentReference>(),
+ vector<AttachmentReference>(),
+ vector<AttachmentReference>(),
+ AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
+ vector<AttachmentReference>())),
+ vector<SubpassDependency>());
+
+ addFunctionCaseWithPrograms<TestConfig>(group.get(), "depth_stencil", "Single depth stencil attachment case.", createTestShaders, renderPassTest, TestConfig(renderPass, TestConfig::RENDERTYPES_DRAW, TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, 90239));
+ }
+
+ // color_depth
+ {
+ const Attachment attachments[] =
+ {
+ Attachment(VK_FORMAT_R8G8B8A8_UNORM,
+ VK_SAMPLE_COUNT_1_BIT,
+ VK_ATTACHMENT_LOAD_OP_CLEAR,
+ VK_ATTACHMENT_STORE_OP_STORE,
+ VK_ATTACHMENT_LOAD_OP_DONT_CARE,
+ VK_ATTACHMENT_STORE_OP_DONT_CARE,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL),
+ Attachment(VK_FORMAT_X8_D24_UNORM_PACK32,
+ VK_SAMPLE_COUNT_1_BIT,
+ VK_ATTACHMENT_LOAD_OP_CLEAR,
+ VK_ATTACHMENT_STORE_OP_STORE,
+ VK_ATTACHMENT_LOAD_OP_DONT_CARE,
+ VK_ATTACHMENT_STORE_OP_DONT_CARE,
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
+ };
+
+ const RenderPass renderPass (vector<Attachment>(DE_ARRAY_BEGIN(attachments), DE_ARRAY_END(attachments)),
+ vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS,
+ 0u,
+ vector<AttachmentReference>(),
+ vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
+ vector<AttachmentReference>(),
+ AttachmentReference(1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
+ vector<AttachmentReference>())),
+ vector<SubpassDependency>());
+
+ addFunctionCaseWithPrograms<TestConfig>(group.get(), "color_depth", "Color and depth attachment case.", createTestShaders, renderPassTest, TestConfig(renderPass, TestConfig::RENDERTYPES_DRAW, TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, 90239));
+ }
+
+ // color_stencil
+ {
+ const Attachment attachments[] =
+ {
+ Attachment(VK_FORMAT_R8G8B8A8_UNORM,
+ VK_SAMPLE_COUNT_1_BIT,
+ VK_ATTACHMENT_LOAD_OP_CLEAR,
+ VK_ATTACHMENT_STORE_OP_STORE,
+ VK_ATTACHMENT_LOAD_OP_DONT_CARE,
+ VK_ATTACHMENT_STORE_OP_DONT_CARE,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL),
+ Attachment(VK_FORMAT_S8_UINT,
+ VK_SAMPLE_COUNT_1_BIT,
+ VK_ATTACHMENT_LOAD_OP_CLEAR,
+ VK_ATTACHMENT_STORE_OP_STORE,
+ VK_ATTACHMENT_LOAD_OP_DONT_CARE,
+ VK_ATTACHMENT_STORE_OP_DONT_CARE,
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
+ };
+
+ const RenderPass renderPass (vector<Attachment>(DE_ARRAY_BEGIN(attachments), DE_ARRAY_END(attachments)),
+ vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS,
+ 0u,
+ vector<AttachmentReference>(),
+ vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
+ vector<AttachmentReference>(),
+ AttachmentReference(1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
+ vector<AttachmentReference>())),
+ vector<SubpassDependency>());
+
+
+ addFunctionCaseWithPrograms<TestConfig>(group.get(), "color_stencil", "Color and stencil attachment case.", createTestShaders, renderPassTest, TestConfig(renderPass, TestConfig::RENDERTYPES_DRAW, TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, 90239));
+ }
+
+ // color_depth_stencil
+ {
+ const Attachment attachments[] =
+ {
+ Attachment(VK_FORMAT_R8G8B8A8_UNORM,
+ VK_SAMPLE_COUNT_1_BIT,
+ VK_ATTACHMENT_LOAD_OP_CLEAR,
+ VK_ATTACHMENT_STORE_OP_STORE,
+ VK_ATTACHMENT_LOAD_OP_DONT_CARE,
+ VK_ATTACHMENT_STORE_OP_DONT_CARE,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL),
+ Attachment(VK_FORMAT_D24_UNORM_S8_UINT,
+ VK_SAMPLE_COUNT_1_BIT,
+ VK_ATTACHMENT_LOAD_OP_CLEAR,
+ VK_ATTACHMENT_STORE_OP_STORE,
+ VK_ATTACHMENT_LOAD_OP_CLEAR,
+ VK_ATTACHMENT_STORE_OP_STORE,
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
+ };
+
+ const RenderPass renderPass (vector<Attachment>(DE_ARRAY_BEGIN(attachments), DE_ARRAY_END(attachments)),
+ vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS,
+ 0u,
+ vector<AttachmentReference>(),
+ vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
+ vector<AttachmentReference>(),
+ AttachmentReference(1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
+ vector<AttachmentReference>())),
+ vector<SubpassDependency>());
+
+ addFunctionCaseWithPrograms<TestConfig>(group.get(), "color_depth_stencil", "Color, depth and stencil attachment case.", createTestShaders, renderPassTest, TestConfig(renderPass, TestConfig::RENDERTYPES_DRAW, TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, 90239));
+ }
+
+ return group;
+}
+
+std::string formatToName (VkFormat format)
+{
+ const std::string formatStr = de::toString(format);
+ const std::string prefix = "VK_FORMAT_";
+
+ DE_ASSERT(formatStr.substr(0, prefix.length()) == prefix);
+
+ return de::toLower(formatStr.substr(prefix.length()));
+}
+
+de::MovePtr<tcu::TestCaseGroup> createFormatTestGroup(tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "formats", "Tests for different image formats."));
+
+ const UVec2 targetSize (64, 64);
+ const UVec2 renderPos (0, 0);
+ const UVec2 renderSize (64, 64);
+
+ const struct
+ {
+ const char* const str;
+ const VkAttachmentLoadOp op;
+ } loadOps[] =
+ {
+ { "clear", VK_ATTACHMENT_LOAD_OP_CLEAR },
+ { "load", VK_ATTACHMENT_LOAD_OP_LOAD },
+ { "dont_care", VK_ATTACHMENT_LOAD_OP_DONT_CARE }
+ };
+
+ const struct
+ {
+ const char* const str;
+ const TestConfig::RenderTypes types;
+ } renderTypes[] =
+ {
+ { "clear", TestConfig::RENDERTYPES_CLEAR },
+ { "draw", TestConfig::RENDERTYPES_DRAW },
+ { "clear_draw", TestConfig::RENDERTYPES_CLEAR|TestConfig::RENDERTYPES_DRAW }
+ };
+
+ for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_colorFormats); formatNdx++)
+ {
+ const VkFormat format = s_colorFormats[formatNdx];
+ de::MovePtr<tcu::TestCaseGroup> formatGroup (new tcu::TestCaseGroup(testCtx, formatToName(format).c_str(), de::toString(format).c_str()));
+
+ for (size_t loadOpNdx = 0; loadOpNdx < DE_LENGTH_OF_ARRAY(loadOps); loadOpNdx++)
+ {
+ const VkAttachmentLoadOp loadOp = loadOps[loadOpNdx].op;
+ de::MovePtr<tcu::TestCaseGroup> loadOpGroup (new tcu::TestCaseGroup(testCtx, loadOps[loadOpNdx].str, loadOps[loadOpNdx].str));
+
+ for (size_t renderTypeNdx = 0; renderTypeNdx < DE_LENGTH_OF_ARRAY(renderTypes); renderTypeNdx++)
+ {
+ const RenderPass renderPass (vector<Attachment>(1, Attachment(format,
+ VK_SAMPLE_COUNT_1_BIT,
+ loadOp,
+ VK_ATTACHMENT_STORE_OP_STORE,
+ VK_ATTACHMENT_LOAD_OP_DONT_CARE,
+ VK_ATTACHMENT_STORE_OP_DONT_CARE,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
+ vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS,
+ 0u,
+ vector<AttachmentReference>(),
+ vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
+ vector<AttachmentReference>(),
+ AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL),
+ vector<AttachmentReference>())),
+ vector<SubpassDependency>());
+
+ addFunctionCaseWithPrograms<TestConfig>(loadOpGroup.get(), renderTypes[renderTypeNdx].str, renderTypes[renderTypeNdx].str, createTestShaders, renderPassTest, TestConfig(renderPass, renderTypes[renderTypeNdx].types, TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, 90239));
+ }
+
+ formatGroup->addChild(loadOpGroup.release());
+ }
+
+ group->addChild(formatGroup.release());
+ }
+
+ return group;
+}
+
+} // anonymous
+
+tcu::TestCaseGroup* createRenderPassTests (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> renderpassTests (new tcu::TestCaseGroup(testCtx, "renderpass", "RenderPass Tests"));
+
+ renderpassTests->addChild(createSimpleTestGroup(testCtx).release());
+ renderpassTests->addChild(createFormatTestGroup(testCtx).release());
+ renderpassTests->addChild(createAttachmentTestCaseGroup(testCtx).release());
+ renderpassTests->addChild(createAttachmentAllocationTestGroup(testCtx).release());
+
+ return renderpassTests.release();
+}
+
+} // vkt
--- /dev/null
+#ifndef _VKTRENDERPASSTESTS_HPP
+#define _VKTRENDERPASSTESTS_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief RenderPass tests
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+
+tcu::TestCaseGroup* createRenderPassTests (tcu::TestContext& testCtx);
+
+} // vkt
+
+#endif // _VKTRENDERPASSTESTS_HPP
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief ShaderLibrary Vulkan implementation
+ *//*--------------------------------------------------------------------*/
+
+#include "vktShaderLibrary.hpp"
+#include "vktTestCase.hpp"
+
+#include "vkPrograms.hpp"
+#include "vkRef.hpp"
+#include "vkRefUtil.hpp"
+#include "vkMemUtil.hpp"
+#include "vkQueryUtil.hpp"
+#include "vkBuilderUtil.hpp"
+#include "vkTypeUtil.hpp"
+
+#include "gluShaderLibrary.hpp"
+#include "gluShaderUtil.hpp"
+
+#include "tcuStringTemplate.hpp"
+#include "tcuTexture.hpp"
+#include "tcuTestLog.hpp"
+#include "tcuVector.hpp"
+#include "tcuVectorUtil.hpp"
+
+#include "deStringUtil.hpp"
+#include "deArrayUtil.hpp"
+#include "deMemory.h"
+
+#include <sstream>
+#include <map>
+
+namespace vkt
+{
+
+using std::string;
+using std::vector;
+using std::map;
+using std::pair;
+using std::ostringstream;
+
+using de::MovePtr;
+using de::UniquePtr;
+
+using glu::ShaderType;
+using glu::ProgramSources;
+using glu::DataType;
+
+using glu::sl::ShaderCaseSpecification;
+using glu::sl::ProgramSpecializationParams;
+using glu::sl::RequiredExtension;
+using glu::sl::Value;
+using glu::sl::ValueBlock;
+
+using tcu::TestStatus;
+using tcu::StringTemplate;
+using tcu::Vec2;
+using tcu::ConstPixelBufferAccess;
+using tcu::TextureFormat;
+using tcu::TestLog;
+
+using vk::SourceCollections;
+using vk::Move;
+using vk::Unique;
+
+namespace
+{
+
+enum
+{
+ REFERENCE_UNIFORM_BINDING = 0,
+ USER_UNIFORM_BINDING = 1
+};
+
+string getShaderName (ShaderType shaderType, size_t progNdx)
+{
+ ostringstream str;
+ str << glu::getShaderTypeName(shaderType);
+ if (progNdx > 0)
+ str << "_" << progNdx;
+ return str.str();
+}
+
+void genUniformBlock (ostringstream& out, const string& blockName, const string& instanceName, int setNdx, int bindingNdx, const vector<Value>& uniforms)
+{
+ out << "layout(";
+
+ if (setNdx != 0)
+ out << "set = " << setNdx << ", ";
+
+ out << "binding = " << bindingNdx << ", std140) uniform " << blockName << "\n"
+ << "{\n";
+
+ for (vector<Value>::const_iterator val = uniforms.begin(); val != uniforms.end(); ++val)
+ out << "\t" << glu::declare(val->type, val->name, 1) << ";\n";
+
+ out << "}";
+
+ if (!instanceName.empty())
+ out << " " << instanceName;
+
+ out << ";\n";
+}
+
+void declareReferenceBlock (ostringstream& out, const ValueBlock& valueBlock)
+{
+ if (!valueBlock.outputs.empty())
+ genUniformBlock(out, "Reference", "ref", 0, REFERENCE_UNIFORM_BINDING, valueBlock.outputs);
+}
+
+void declareUniforms (ostringstream& out, const ValueBlock& valueBlock)
+{
+ if (!valueBlock.uniforms.empty())
+ genUniformBlock(out, "Uniforms", "", 0, USER_UNIFORM_BINDING, valueBlock.uniforms);
+}
+
+DataType getTransportType (DataType valueType)
+{
+ if (isDataTypeBoolOrBVec(valueType))
+ return glu::getDataTypeIntVec(getDataTypeScalarSize(valueType));
+ else
+ return valueType;
+}
+
+int getNumTransportLocations (DataType valueType)
+{
+ return isDataTypeMatrix(valueType) ? getDataTypeMatrixNumColumns(valueType) : 1;
+}
+
+// This functions builds a matching vertex shader for a 'both' case, when
+// the fragment shader is being tested.
+// We need to build attributes and varyings for each 'input'.
+string genVertexShader (const ShaderCaseSpecification& spec)
+{
+ ostringstream res;
+ int curInputLoc = 0;
+ int curOutputLoc = 0;
+
+ res << glu::getGLSLVersionDeclaration(spec.targetVersion) << "\n";
+
+ // Declarations (position + attribute/varying for each input).
+ res << "precision highp float;\n";
+ res << "precision highp int;\n";
+ res << "\n";
+ res << "layout(location = 0) in highp vec4 dEQP_Position;\n";
+ curInputLoc += 1;
+
+ for (size_t ndx = 0; ndx < spec.values.inputs.size(); ndx++)
+ {
+ const Value& val = spec.values.inputs[ndx];
+ const DataType valueType = val.type.getBasicType();
+ const DataType transportType = getTransportType(valueType);
+ const char* const transportTypeStr = getDataTypeName(transportType);
+ const int numLocs = getNumTransportLocations(valueType);
+
+ res << "layout(location = " << curInputLoc << ") in " << transportTypeStr << " a_" << val.name << ";\n";
+ res << "layout(location = " << curOutputLoc << ") flat out " << transportTypeStr << " " << (transportType != valueType ? "v_" : "") << val.name << ";\n";
+
+ curInputLoc += numLocs;
+ curOutputLoc += numLocs;
+ }
+ res << "\n";
+
+ // Main function.
+ // - gl_Position = dEQP_Position;
+ // - for each input: write attribute directly to varying
+ res << "void main()\n";
+ res << "{\n";
+ res << " gl_Position = dEQP_Position;\n";
+ for (size_t ndx = 0; ndx < spec.values.inputs.size(); ndx++)
+ {
+ const Value& val = spec.values.inputs[ndx];
+ const string& name = val.name;
+
+ res << " " << (getTransportType(val.type.getBasicType()) != val.type.getBasicType() ? "v_" : "")
+ << name << " = a_" << name << ";\n";
+ }
+
+ res << "}\n";
+ return res.str();
+}
+
+void genCompareOp (ostringstream& output, const char* dstVec4Var, const ValueBlock& valueBlock, const char* checkVarName)
+{
+ bool isFirstOutput = true;
+
+ for (size_t ndx = 0; ndx < valueBlock.outputs.size(); ndx++)
+ {
+ const Value& val = valueBlock.outputs[ndx];
+
+ // Check if we're only interested in one variable (then skip if not the right one).
+ if (checkVarName && val.name != checkVarName)
+ continue;
+
+ // Prefix.
+ if (isFirstOutput)
+ {
+ output << "bool RES = ";
+ isFirstOutput = false;
+ }
+ else
+ output << "RES = RES && ";
+
+ // Generate actual comparison.
+ if (getDataTypeScalarType(val.type.getBasicType()) == glu::TYPE_FLOAT)
+ output << "isOk(" << val.name << ", ref." << val.name << ", 0.05);\n";
+ else
+ output << "isOk(" << val.name << ", ref." << val.name << ");\n";
+ }
+
+ if (isFirstOutput)
+ output << dstVec4Var << " = vec4(1.0);\n";
+ else
+ output << dstVec4Var << " = vec4(RES, RES, RES, 1.0);\n";
+}
+
+string genFragmentShader (const ShaderCaseSpecification& spec)
+{
+ ostringstream shader;
+ ostringstream setup;
+ int curInLoc = 0;
+
+ shader << glu::getGLSLVersionDeclaration(spec.targetVersion) << "\n";
+
+ shader << "precision highp float;\n";
+ shader << "precision highp int;\n";
+ shader << "\n";
+
+ shader << "layout(location = 0) out mediump vec4 dEQP_FragColor;\n";
+ shader << "\n";
+
+ genCompareFunctions(shader, spec.values, false);
+ shader << "\n";
+
+ // Declarations (varying, reference for each output).
+ for (size_t ndx = 0; ndx < spec.values.outputs.size(); ndx++)
+ {
+ const Value& val = spec.values.outputs[ndx];
+ const DataType valueType = val.type.getBasicType();
+ const char* const valueTypeStr = getDataTypeName(valueType);
+ const DataType transportType = getTransportType(valueType);
+ const char* const transportTypeStr = getDataTypeName(transportType);
+ const int numLocs = getNumTransportLocations(valueType);
+
+ shader << "layout(location = " << curInLoc << ") flat in " << transportTypeStr << " " << (valueType != transportType ? "v_" : "") << val.name << ";\n";
+
+ if (valueType != transportType)
+ setup << " " << valueTypeStr << " " << val.name << " = " << valueTypeStr << "(v_" << val.name << ");\n";
+
+ curInLoc += numLocs;
+ }
+
+ declareReferenceBlock(shader, spec.values);
+
+ shader << "\n";
+ shader << "void main()\n";
+ shader << "{\n";
+
+ shader << setup.str();
+
+ shader << " ";
+ genCompareOp(shader, "dEQP_FragColor", spec.values, DE_NULL);
+
+ shader << "}\n";
+ return shader.str();
+}
+
+// Specialize a shader for the vertex shader test case.
+string specializeVertexShader (const ShaderCaseSpecification& spec, const string& src)
+{
+ ostringstream decl;
+ ostringstream setup;
+ ostringstream output;
+ int curInputLoc = 0;
+ int curOutputLoc = 0;
+
+ // generated from "both" case
+ DE_ASSERT(spec.caseType == glu::sl::CASETYPE_VERTEX_ONLY);
+
+ // Output (write out position).
+ output << "gl_Position = dEQP_Position;\n";
+
+ // Declarations (position + attribute for each input, varying for each output).
+ decl << "layout(location = 0) in highp vec4 dEQP_Position;\n";
+ curInputLoc += 1;
+
+ for (size_t ndx = 0; ndx < spec.values.inputs.size(); ndx++)
+ {
+ const Value& val = spec.values.inputs[ndx];
+ const DataType valueType = val.type.getBasicType();
+ const char* const valueTypeStr = getDataTypeName(valueType);
+ const DataType transportType = getTransportType(valueType);
+ const char* const transportTypeStr = getDataTypeName(transportType);
+ const int numLocs = getNumTransportLocations(valueType);
+
+ decl << "layout(location = " << curInputLoc << ") in ";
+
+ curInputLoc += numLocs;
+
+ if (valueType == transportType)
+ decl << transportTypeStr << " " << val.name << ";\n";
+ else
+ {
+ decl << transportTypeStr << " a_" << val.name << ";\n";
+ setup << valueTypeStr << " " << val.name << " = " << valueTypeStr << "(a_" << val.name << ");\n";
+ }
+ }
+
+ declareUniforms(decl, spec.values);
+
+ for (size_t ndx = 0; ndx < spec.values.outputs.size(); ndx++)
+ {
+ const Value& val = spec.values.outputs[ndx];
+ const DataType valueType = val.type.getBasicType();
+ const char* const valueTypeStr = getDataTypeName(valueType);
+ const DataType transportType = getTransportType(valueType);
+ const char* const transportTypeStr = getDataTypeName(transportType);
+ const int numLocs = getNumTransportLocations(valueType);
+
+ decl << "layout(location = " << curOutputLoc << ") flat out ";
+
+ curOutputLoc += numLocs;
+
+ if (valueType == transportType)
+ decl << transportTypeStr << " " << val.name << ";\n";
+ else
+ {
+ decl << transportTypeStr << " v_" << val.name << ";\n";
+ decl << valueTypeStr << " " << val.name << ";\n";
+
+ output << "v_" << val.name << " = " << transportTypeStr << "(" << val.name << ");\n";
+ }
+ }
+
+ // Shader specialization.
+ map<string, string> params;
+ params.insert(pair<string, string>("DECLARATIONS", decl.str()));
+ params.insert(pair<string, string>("SETUP", setup.str()));
+ params.insert(pair<string, string>("OUTPUT", output.str()));
+ params.insert(pair<string, string>("POSITION_FRAG_COLOR", "gl_Position"));
+
+ StringTemplate tmpl (src);
+ const string baseSrc = tmpl.specialize(params);
+ const string withExt = injectExtensionRequirements(baseSrc, spec.programs[0].requiredExtensions, glu::SHADERTYPE_VERTEX);
+
+ return withExt;
+}
+
+// Specialize a shader for the fragment shader test case.
+string specializeFragmentShader (const ShaderCaseSpecification& spec, const string& src)
+{
+ ostringstream decl;
+ ostringstream setup;
+ ostringstream output;
+ int curInputLoc = 0;
+
+ // generated from "both" case
+ DE_ASSERT(spec.caseType == glu::sl::CASETYPE_FRAGMENT_ONLY);
+
+ genCompareFunctions(decl, spec.values, false);
+ genCompareOp(output, "dEQP_FragColor", spec.values, DE_NULL);
+
+ decl << "layout(location = 0) out mediump vec4 dEQP_FragColor;\n";
+
+ for (size_t ndx = 0; ndx < spec.values.inputs.size(); ndx++)
+ {
+ const Value& val = spec.values.inputs[ndx];
+ const DataType valueType = val.type.getBasicType();
+ const char* const valueTypeStr = getDataTypeName(valueType);
+ const DataType transportType = getTransportType(valueType);
+ const char* const transportTypeStr = getDataTypeName(transportType);
+ const int numLocs = getNumTransportLocations(valueType);
+
+ decl << "layout(location = " << curInputLoc << ") flat in ";
+
+ curInputLoc += numLocs;
+
+ if (valueType == transportType)
+ decl << transportTypeStr << " " << val.name << ";\n";
+ else
+ {
+ decl << transportTypeStr << " v_" << val.name << ";\n";
+ setup << valueTypeStr << " " << val.name << " = " << valueTypeStr << "(v_" << val.name << ");\n";
+ }
+ }
+
+ declareUniforms(decl, spec.values);
+ declareReferenceBlock(decl, spec.values);
+
+ for (size_t ndx = 0; ndx < spec.values.outputs.size(); ndx++)
+ {
+ const Value& val = spec.values.outputs[ndx];
+ const DataType basicType = val.type.getBasicType();
+ const char* const refTypeStr = getDataTypeName(basicType);
+
+ decl << refTypeStr << " " << val.name << ";\n";
+ }
+
+ // Shader specialization.
+ map<string, string> params;
+ params.insert(pair<string, string>("DECLARATIONS", decl.str()));
+ params.insert(pair<string, string>("SETUP", setup.str()));
+ params.insert(pair<string, string>("OUTPUT", output.str()));
+ params.insert(pair<string, string>("POSITION_FRAG_COLOR", "dEQP_FragColor"));
+
+ StringTemplate tmpl (src);
+ const string baseSrc = tmpl.specialize(params);
+ const string withExt = injectExtensionRequirements(baseSrc, spec.programs[0].requiredExtensions, glu::SHADERTYPE_FRAGMENT);
+
+ return withExt;
+}
+
+map<string, string> generateVertexSpecialization (const ProgramSpecializationParams& specParams)
+{
+ ostringstream decl;
+ ostringstream setup;
+ map<string, string> params;
+ int curInputLoc = 0;
+
+ decl << "layout(location = 0) in highp vec4 dEQP_Position;\n";
+ curInputLoc += 1;
+
+ for (size_t ndx = 0; ndx < specParams.caseSpec.values.inputs.size(); ndx++)
+ {
+ const Value& val = specParams.caseSpec.values.inputs[ndx];
+ const DataType valueType = val.type.getBasicType();
+ const char* const valueTypeStr = getDataTypeName(valueType);
+ const DataType transportType = getTransportType(valueType);
+ const char* const transportTypeStr = getDataTypeName(transportType);
+ const int numLocs = getNumTransportLocations(valueType);
+
+ decl << "layout(location = " << curInputLoc << ") in ";
+
+ curInputLoc += numLocs;
+
+ if (valueType == transportType)
+ decl << transportTypeStr << " " << val.name << ";\n";
+ else
+ {
+ decl << transportTypeStr << " a_" << val.name << ";\n";
+ setup << valueTypeStr << " " << val.name << " = " << valueTypeStr << "(a_" << val.name << ");\n";
+ }
+ }
+
+ declareUniforms(decl, specParams.caseSpec.values);
+
+ params.insert(pair<string, string>("VERTEX_DECLARATIONS", decl.str()));
+ params.insert(pair<string, string>("VERTEX_SETUP", setup.str()));
+ params.insert(pair<string, string>("VERTEX_OUTPUT", string("gl_Position = dEQP_Position;\n")));
+
+ return params;
+}
+
+map<string, string> generateFragmentSpecialization (const ProgramSpecializationParams& specParams)
+{
+ ostringstream decl;
+ ostringstream output;
+ map<string, string> params;
+
+ genCompareFunctions(decl, specParams.caseSpec.values, false);
+ genCompareOp(output, "dEQP_FragColor", specParams.caseSpec.values, DE_NULL);
+
+ decl << "layout(location = 0) out mediump vec4 dEQP_FragColor;\n";
+
+ for (size_t ndx = 0; ndx < specParams.caseSpec.values.outputs.size(); ndx++)
+ {
+ const Value& val = specParams.caseSpec.values.outputs[ndx];
+ const char* const refTypeStr = getDataTypeName(val.type.getBasicType());
+
+ decl << refTypeStr << " " << val.name << ";\n";
+ }
+
+ declareReferenceBlock(decl, specParams.caseSpec.values);
+ declareUniforms(decl, specParams.caseSpec.values);
+
+ params.insert(pair<string, string>("FRAGMENT_DECLARATIONS", decl.str()));
+ params.insert(pair<string, string>("FRAGMENT_OUTPUT", output.str()));
+ params.insert(pair<string, string>("FRAG_COLOR", "dEQP_FragColor"));
+
+ return params;
+}
+
+map<string, string> generateGeometrySpecialization (const ProgramSpecializationParams& specParams)
+{
+ ostringstream decl;
+ map<string, string> params;
+
+ decl << "layout (triangles) in;\n";
+ decl << "layout (triangle_strip, max_vertices=3) out;\n";
+ decl << "\n";
+
+ declareUniforms(decl, specParams.caseSpec.values);
+
+ params.insert(pair<string, string>("GEOMETRY_DECLARATIONS", decl.str()));
+
+ return params;
+}
+
+map<string, string> generateTessControlSpecialization (const ProgramSpecializationParams& specParams)
+{
+ ostringstream decl;
+ ostringstream output;
+ map<string, string> params;
+
+ decl << "layout (vertices=3) out;\n";
+ decl << "\n";
+
+ declareUniforms(decl, specParams.caseSpec.values);
+
+ output << "gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
+ "gl_TessLevelInner[0] = 2.0;\n"
+ "gl_TessLevelInner[1] = 2.0;\n"
+ "gl_TessLevelOuter[0] = 2.0;\n"
+ "gl_TessLevelOuter[1] = 2.0;\n"
+ "gl_TessLevelOuter[2] = 2.0;\n"
+ "gl_TessLevelOuter[3] = 2.0;";
+
+ params.insert(pair<string, string>("TESSELLATION_CONTROL_DECLARATIONS", decl.str()));
+ params.insert(pair<string, string>("TESSELLATION_CONTROL_OUTPUT", output.str()));
+ params.insert(pair<string, string>("GL_MAX_PATCH_VERTICES", de::toString(specParams.maxPatchVertices)));
+
+ return params;
+}
+
+map<string, string> generateTessEvalSpecialization (const ProgramSpecializationParams& specParams)
+{
+ ostringstream decl;
+ ostringstream output;
+ map<string, string> params;
+
+ decl << "layout (triangles) in;\n";
+ decl << "\n";
+
+ declareUniforms(decl, specParams.caseSpec.values);
+
+ output << "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";
+
+ params.insert(pair<string, string>("TESSELLATION_EVALUATION_DECLARATIONS", decl.str()));
+ params.insert(pair<string, string>("TESSELLATION_EVALUATION_OUTPUT", output.str()));
+ params.insert(pair<string, string>("GL_MAX_PATCH_VERTICES", de::toString(specParams.maxPatchVertices)));
+
+ return params;
+}
+
+void specializeShaderSources (ProgramSources& dst,
+ const ProgramSources& src,
+ const ProgramSpecializationParams& specParams,
+ glu::ShaderType shaderType,
+ map<string, string> (*specializationGenerator) (const ProgramSpecializationParams& specParams))
+{
+ if (!src.sources[shaderType].empty())
+ {
+ const map<string, string> tmplParams = specializationGenerator(specParams);
+
+ for (size_t ndx = 0; ndx < src.sources[shaderType].size(); ++ndx)
+ {
+ const StringTemplate tmpl (src.sources[shaderType][ndx]);
+ const string baseGLSLCode = tmpl.specialize(tmplParams);
+ const string sourceWithExts = injectExtensionRequirements(baseGLSLCode, specParams.requiredExtensions, shaderType);
+
+ dst << glu::ShaderSource(shaderType, sourceWithExts);
+ }
+ }
+}
+
+void specializeProgramSources (glu::ProgramSources& dst,
+ const glu::ProgramSources& src,
+ const ProgramSpecializationParams& specParams)
+{
+ specializeShaderSources(dst, src, specParams, glu::SHADERTYPE_VERTEX, generateVertexSpecialization);
+ specializeShaderSources(dst, src, specParams, glu::SHADERTYPE_FRAGMENT, generateFragmentSpecialization);
+ specializeShaderSources(dst, src, specParams, glu::SHADERTYPE_GEOMETRY, generateGeometrySpecialization);
+ specializeShaderSources(dst, src, specParams, glu::SHADERTYPE_TESSELLATION_CONTROL, generateTessControlSpecialization);
+ specializeShaderSources(dst, src, specParams, glu::SHADERTYPE_TESSELLATION_EVALUATION, generateTessEvalSpecialization);
+
+ dst << glu::ProgramSeparable(src.separable);
+}
+
+struct ValueBufferLayout
+{
+ struct Entry
+ {
+ int offset;
+ int vecStride; //! Applies to matrices only
+
+ Entry (void) : offset(0), vecStride(0) {}
+ Entry (int offset_, int vecStride_) : offset(offset_), vecStride(vecStride_) {}
+ };
+
+ vector<Entry> entries;
+ int size;
+
+ ValueBufferLayout (void) : size(0) {}
+};
+
+ValueBufferLayout computeStd140Layout (const vector<Value>& values)
+{
+ ValueBufferLayout layout;
+
+ layout.entries.resize(values.size());
+
+ for (size_t ndx = 0; ndx < values.size(); ++ndx)
+ {
+ const DataType basicType = values[ndx].type.getBasicType();
+ const bool isMatrix = isDataTypeMatrix(basicType);
+ const int numVecs = isMatrix ? getDataTypeMatrixNumColumns(basicType) : 1;
+ const DataType vecType = isMatrix ? glu::getDataTypeFloatVec(getDataTypeMatrixNumRows(basicType)) : basicType;
+ const int vecSize = getDataTypeScalarSize(vecType);
+ const int alignment = ((isMatrix || vecSize == 3) ? 4 : vecSize)*int(sizeof(deUint32));
+
+ layout.size = deAlign32(layout.size, alignment);
+ layout.entries[ndx] = ValueBufferLayout::Entry(layout.size, alignment);
+ layout.size += alignment*(numVecs-1) + vecSize*int(sizeof(deUint32));
+ }
+
+ return layout;
+}
+
+ValueBufferLayout computeStd430Layout (const vector<Value>& values)
+{
+ ValueBufferLayout layout;
+
+ layout.entries.resize(values.size());
+
+ for (size_t ndx = 0; ndx < values.size(); ++ndx)
+ {
+ const DataType basicType = values[ndx].type.getBasicType();
+ const int numVecs = isDataTypeMatrix(basicType) ? getDataTypeMatrixNumColumns(basicType) : 1;
+ const DataType vecType = isDataTypeMatrix(basicType) ? glu::getDataTypeFloatVec(getDataTypeMatrixNumRows(basicType)) : basicType;
+ const int vecSize = getDataTypeScalarSize(vecType);
+ const int alignment = (vecSize == 3 ? 4 : vecSize)*int(sizeof(deUint32));
+
+ layout.size = deAlign32(layout.size, alignment);
+ layout.entries[ndx] = ValueBufferLayout::Entry(layout.size, alignment);
+ layout.size += alignment*(numVecs-1) + vecSize*int(sizeof(deUint32));
+ }
+
+ return layout;
+}
+
+void copyToLayout (void* dst, const ValueBufferLayout::Entry& entryLayout, const Value& value, int arrayNdx)
+{
+ const DataType basicType = value.type.getBasicType();
+ const int scalarSize = getDataTypeScalarSize(basicType);
+ const int numVecs = isDataTypeMatrix(basicType) ? getDataTypeMatrixNumColumns(basicType) : 1;
+ const int numComps = isDataTypeMatrix(basicType) ? getDataTypeMatrixNumRows(basicType) : scalarSize;
+
+ DE_ASSERT(size_t((arrayNdx+1)*scalarSize) <= value.elements.size());
+
+ for (int vecNdx = 0; vecNdx < numVecs; vecNdx++)
+ deMemcpy((deUint8*)dst + entryLayout.offset + vecNdx*entryLayout.vecStride,
+ &value.elements[arrayNdx*scalarSize + vecNdx*numComps],
+ numComps*sizeof(deUint32));
+}
+
+void copyToLayout (void* dst, const ValueBufferLayout& layout, const vector<Value>& values, int arrayNdx)
+{
+ DE_ASSERT(layout.entries.size() == values.size());
+
+ for (size_t ndx = 0; ndx < values.size(); ndx++)
+ copyToLayout(dst, layout.entries[ndx], values[ndx], arrayNdx);
+}
+
+deUint32 getShaderStages (const ShaderCaseSpecification& spec)
+{
+ if (spec.caseType == glu::sl::CASETYPE_COMPLETE)
+ {
+ deUint32 stages = 0u;
+
+ for (size_t progNdx = 0; progNdx < spec.programs.size(); progNdx++)
+ {
+ for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++)
+ {
+ if (!spec.programs[progNdx].sources.sources[shaderType].empty())
+ stages |= (1u << shaderType);
+ }
+ }
+
+ return stages;
+ }
+ else
+ return (1u << glu::SHADERTYPE_VERTEX) | (1u << glu::SHADERTYPE_FRAGMENT);
+}
+
+class PipelineProgram
+{
+public:
+ PipelineProgram (Context& context, const ShaderCaseSpecification& spec);
+
+ deUint32 getStages (void) const { return m_stages; }
+
+ bool hasShader (glu::ShaderType type) const { return (m_stages & (1u << type)) != 0; }
+ vk::VkShaderModule getShader (glu::ShaderType type) const { return *m_shaderModules[type]; }
+
+private:
+ const deUint32 m_stages;
+ Move<vk::VkShaderModule> m_shaderModules[glu::SHADERTYPE_LAST];
+};
+
+PipelineProgram::PipelineProgram (Context& context, const ShaderCaseSpecification& spec)
+ : m_stages(getShaderStages(spec))
+{
+ // \note Currently only a single source program is supported as framework lacks SPIR-V linking capability
+ TCU_CHECK_INTERNAL(spec.programs.size() == 1);
+
+ for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++)
+ {
+ if ((m_stages & (1u << shaderType)) != 0)
+ {
+ m_shaderModules[shaderType] = vk::createShaderModule(context.getDeviceInterface(), context.getDevice(),
+ context.getBinaryCollection().get(getShaderName((glu::ShaderType)shaderType, 0)), 0u);
+ }
+ }
+}
+
+vector<vk::VkPipelineShaderStageCreateInfo> getPipelineShaderStageCreateInfo (const PipelineProgram& program)
+{
+ vector<vk::VkPipelineShaderStageCreateInfo> infos;
+
+ for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++)
+ {
+ if (program.hasShader((glu::ShaderType)shaderType))
+ {
+ const vk::VkPipelineShaderStageCreateInfo info =
+ {
+ vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ (vk::VkPipelineShaderStageCreateFlags)0,
+ vk::getVkShaderStage((glu::ShaderType)shaderType), // stage
+ program.getShader((glu::ShaderType)shaderType), // module
+ "main",
+ DE_NULL, // pSpecializationInfo
+ };
+
+ infos.push_back(info);
+ }
+ }
+
+ return infos;
+}
+
+Move<vk::VkBuffer> createBuffer (Context& context, vk::VkDeviceSize size, vk::VkBufferUsageFlags usageFlags)
+{
+ const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
+ const vk::VkBufferCreateInfo params =
+ {
+ vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ 0u, // flags
+ size, // size
+ usageFlags, // usage
+ vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
+ 1u, // queueFamilyCount
+ &queueFamilyIndex, // pQueueFamilyIndices
+ };
+
+ return vk::createBuffer(context.getDeviceInterface(), context.getDevice(), ¶ms);
+}
+
+Move<vk::VkImage> createImage2D (Context& context, int width, int height, vk::VkFormat format, vk::VkImageTiling tiling, vk::VkImageUsageFlags usageFlags)
+{
+ const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
+ const vk::VkImageCreateInfo params =
+ {
+ vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ 0u, // flags
+ vk::VK_IMAGE_TYPE_2D, // imageType
+ format, // format
+ { width, height, 1 }, // extent
+ 1u, // mipLevels
+ 1u, // arraySize
+ vk::VK_SAMPLE_COUNT_1_BIT, // samples
+ tiling, // tiling
+ usageFlags, // usage
+ vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
+ 1u, // queueFamilyCount
+ &queueFamilyIndex, // pQueueFamilyIndices
+ vk::VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout
+ };
+
+ return vk::createImage(context.getDeviceInterface(), context.getDevice(), ¶ms);
+}
+
+Move<vk::VkImageView> createAttachmentView (Context& context, vk::VkImage image, vk::VkFormat format)
+{
+ const vk::VkImageViewCreateInfo params =
+ {
+ vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ 0u, // flags
+ image, // image
+ vk::VK_IMAGE_VIEW_TYPE_2D, // viewType
+ format, // format
+ vk::makeComponentMappingRGBA(), // channels
+ {
+ vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
+ 0u, // baseMipLevel
+ 1u, // mipLevels
+ 0u, // baseArrayLayer
+ 1u, // arraySize
+ }, // subresourceRange
+ };
+
+ return vk::createImageView(context.getDeviceInterface(), context.getDevice(), ¶ms);
+}
+
+Move<vk::VkRenderPass> createRenderPass (Context& context, vk::VkFormat colorAttFormat)
+{
+ const vk::VkAttachmentDescription colorAttDesc =
+ {
+ 0u, // flags
+ colorAttFormat, // format
+ vk::VK_SAMPLE_COUNT_1_BIT, // samples
+ vk::VK_ATTACHMENT_LOAD_OP_CLEAR, // loadOp
+ vk::VK_ATTACHMENT_STORE_OP_STORE, // storeOp
+ vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // stencilLoadOp
+ vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // stencilStoreOp
+ vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // initialLayout
+ vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // finalLayout
+ };
+ const vk::VkAttachmentReference colorAttRef =
+ {
+ 0u, // attachment
+ vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // layout
+ };
+ const vk::VkAttachmentReference dsAttRef =
+ {
+ vk::VK_NO_ATTACHMENT, // attachment
+ vk::VK_IMAGE_LAYOUT_GENERAL, // layout
+ };
+ const vk::VkSubpassDescription subpassDesc =
+ {
+ (vk::VkSubpassDescriptionFlags)0,
+ vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint
+ 0u, // inputCount
+ DE_NULL, // pInputAttachments
+ 1u, // colorCount
+ &colorAttRef, // pColorAttachments
+ DE_NULL, // pResolveAttachments
+ &dsAttRef, // depthStencilAttachment
+ 0u, // preserveCount
+ DE_NULL, // pPreserveAttachments
+
+ };
+ const vk::VkRenderPassCreateInfo renderPassParams =
+ {
+ vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ (vk::VkRenderPassCreateFlags)0,
+ 1u, // attachmentCount
+ &colorAttDesc, // pAttachments
+ 1u, // subpassCount
+ &subpassDesc, // pSubpasses
+ 0u, // dependencyCount
+ DE_NULL, // pDependencies
+ };
+
+ return vk::createRenderPass(context.getDeviceInterface(), context.getDevice(), &renderPassParams);
+}
+
+vk::VkShaderStageFlags getVkStageFlags (deUint32 stages)
+{
+ vk::VkShaderStageFlags vkStages = 0u;
+
+ for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++)
+ {
+ if ((stages & (1u << shaderType)) != 0)
+ vkStages |= vk::getVkShaderStage((glu::ShaderType)shaderType);
+ }
+
+ return vkStages;
+}
+
+Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout (Context& context, deUint32 shaderStages)
+{
+ DE_STATIC_ASSERT(REFERENCE_UNIFORM_BINDING == 0);
+ DE_STATIC_ASSERT(USER_UNIFORM_BINDING == 1);
+
+ return vk::DescriptorSetLayoutBuilder()
+ .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, vk::VK_SHADER_STAGE_FRAGMENT_BIT)
+ .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, getVkStageFlags(shaderStages))
+ .build(context.getDeviceInterface(), context.getDevice());
+}
+
+Move<vk::VkPipelineLayout> createPipelineLayout (Context& context, vk::VkDescriptorSetLayout descriptorSetLayout)
+{
+ const vk::VkPipelineLayoutCreateInfo params =
+ {
+ vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ (vk::VkPipelineLayoutCreateFlags)0,
+ 1u, // descriptorSetCount
+ &descriptorSetLayout, // pSetLayouts
+ 0u, // pushConstantRangeCount
+ DE_NULL, // pPushConstantRanges
+ };
+
+ return vk::createPipelineLayout(context.getDeviceInterface(), context.getDevice(), ¶ms);
+}
+
+vk::VkFormat getFloatVecFormat (int scalarSize)
+{
+ const vk::VkFormat vecFmts[] =
+ {
+ vk::VK_FORMAT_R32_SFLOAT,
+ vk::VK_FORMAT_R32G32_SFLOAT,
+ vk::VK_FORMAT_R32G32B32_SFLOAT,
+ vk::VK_FORMAT_R32G32B32A32_SFLOAT,
+ };
+ return de::getSizedArrayElement<4>(vecFmts, scalarSize-1);
+}
+
+vector<vk::VkVertexInputAttributeDescription> getVertexAttributeDescriptions (const vector<Value>& inputValues, const ValueBufferLayout& layout)
+{
+ vector<vk::VkVertexInputAttributeDescription> attribs;
+
+ // Position
+ {
+ const vk::VkVertexInputAttributeDescription posDesc =
+ {
+ 0u, // location
+ 0u, // binding
+ vk::VK_FORMAT_R32G32_SFLOAT, // format
+ 0u, // offset
+ };
+
+ attribs.push_back(posDesc);
+ }
+
+ // Input values
+ for (size_t inputNdx = 0; inputNdx < inputValues.size(); inputNdx++)
+ {
+ const Value& input = inputValues[inputNdx];
+ const ValueBufferLayout::Entry& layoutEntry = layout.entries[inputNdx];
+ const DataType basicType = input.type.getBasicType();
+ const int numVecs = isDataTypeMatrix(basicType)
+ ? getDataTypeMatrixNumColumns(basicType)
+ : 1;
+ const int vecSize = isDataTypeMatrix(basicType)
+ ? getDataTypeMatrixNumRows(basicType)
+ : getDataTypeScalarSize(basicType);
+ const vk::VkFormat vecFmt = getFloatVecFormat(vecSize);
+
+ for (int vecNdx = 0; vecNdx < numVecs; vecNdx++)
+ {
+ const deUint32 curLoc = (deUint32)attribs.size();
+ const deUint32 offset = (deUint32)(layoutEntry.offset + layoutEntry.vecStride*vecNdx);
+ const vk::VkVertexInputAttributeDescription desc =
+ {
+ curLoc, // location
+ 1u, // binding
+ vecFmt, // format
+ offset, // offset
+ };
+
+ attribs.push_back(desc);
+ }
+ }
+
+ return attribs;
+}
+
+Move<vk::VkPipeline> createPipeline (Context& context,
+ const vector<Value>& inputValues,
+ const ValueBufferLayout& inputLayout,
+ const PipelineProgram& program,
+ vk::VkRenderPass renderPass,
+ vk::VkPipelineLayout pipelineLayout,
+ tcu::IVec2 renderSize)
+{
+ const vector<vk::VkPipelineShaderStageCreateInfo> shaderStageParams (getPipelineShaderStageCreateInfo(program));
+ const vector<vk::VkVertexInputAttributeDescription> vertexAttribParams (getVertexAttributeDescriptions(inputValues, inputLayout));
+ const vk::VkPipelineDepthStencilStateCreateInfo depthStencilParams =
+ {
+ vk::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ (vk::VkPipelineDepthStencilStateCreateFlags)0,
+ vk::VK_FALSE, // depthTestEnable
+ vk::VK_FALSE, // depthWriteEnable
+ vk::VK_COMPARE_OP_ALWAYS, // depthCompareOp
+ vk::VK_FALSE, // depthBoundsTestEnable
+ vk::VK_FALSE, // stencilTestEnable
+ {
+ vk::VK_STENCIL_OP_KEEP, // stencilFailOp;
+ vk::VK_STENCIL_OP_KEEP, // stencilPassOp;
+ vk::VK_STENCIL_OP_KEEP, // stencilDepthFailOp;
+ vk::VK_COMPARE_OP_ALWAYS, // stencilCompareOp;
+ 0u, // stencilCompareMask
+ 0u, // stencilWriteMask
+ 0u, // stencilReference
+ }, // front;
+ {
+ vk::VK_STENCIL_OP_KEEP, // stencilFailOp;
+ vk::VK_STENCIL_OP_KEEP, // stencilPassOp;
+ vk::VK_STENCIL_OP_KEEP, // stencilDepthFailOp;
+ vk::VK_COMPARE_OP_ALWAYS, // stencilCompareOp;
+ 0u, // stencilCompareMask
+ 0u, // stencilWriteMask
+ 0u, // stencilReference
+ }, // back;
+ -1.0f, // minDepthBounds
+ +1.0f, // maxDepthBounds
+ };
+ const vk::VkViewport viewport0 =
+ {
+ 0.0f, // originX
+ 0.0f, // originY
+ (float)renderSize.x(), // width
+ (float)renderSize.y(), // height
+ 0.0f, // minDepth
+ 1.0f, // maxDepth
+ };
+ const vk::VkRect2D scissor0 =
+ {
+ { 0u, 0u }, // offset
+ { renderSize.x(), renderSize.y() } // extent
+ };
+ const vk::VkPipelineViewportStateCreateInfo viewportParams =
+ {
+ vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ (vk::VkPipelineViewportStateCreateFlags)0,
+ 1u, // viewportCount
+ &viewport0, // pViewports
+ 1u, // scissorCount
+ &scissor0, // pScissors
+ };
+ const vk::VkPipelineMultisampleStateCreateInfo multisampleParams =
+ {
+ vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ (vk::VkPipelineMultisampleStateCreateFlags)0,
+ vk::VK_SAMPLE_COUNT_1_BIT, // rasterSamples
+ DE_FALSE, // sampleShadingEnable
+ 0.0f, // minSampleShading
+ DE_NULL, // pSampleMask
+ vk::VK_FALSE, // alphaToCoverageEnable
+ vk::VK_FALSE, // alphaToOneEnable
+ };
+ const vk::VkPipelineRasterizationStateCreateInfo rasterParams =
+ {
+ vk::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ (vk::VkPipelineRasterizationStateCreateFlags)0,
+ DE_TRUE, // depthClipEnable
+ DE_FALSE, // rasterizerDiscardEnable
+ vk::VK_POLYGON_MODE_FILL, // fillMode
+ vk::VK_CULL_MODE_NONE, // cullMode;
+ vk::VK_FRONT_FACE_COUNTER_CLOCKWISE, // frontFace;
+ vk::VK_FALSE, // depthBiasEnable
+ 0.0f, // depthBiasConstantFactor
+ 0.0f, // depthBiasClamp
+ 0.0f, // depthBiasSlopeFactor
+ 1.0f, // lineWidth
+ };
+ const vk::VkPipelineInputAssemblyStateCreateInfo inputAssemblyParams =
+ {
+ vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ (vk::VkPipelineInputAssemblyStateCreateFlags)0,
+ vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // topology
+ DE_FALSE, // primitiveRestartEnable
+ };
+ const vk::VkVertexInputBindingDescription vertexBindings[] =
+ {
+ {
+ 0u, // binding
+ (deUint32)sizeof(tcu::Vec2), // stride
+ vk::VK_VERTEX_INPUT_RATE_VERTEX, // stepRate
+ },
+ {
+ 1u, // binding
+ 0u, // stride
+ vk::VK_VERTEX_INPUT_RATE_INSTANCE, // stepRate
+ },
+ };
+ const vk::VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
+ {
+ vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ (vk::VkPipelineVertexInputStateCreateFlags)0,
+ DE_LENGTH_OF_ARRAY(vertexBindings), // bindingCount
+ vertexBindings, // pVertexBindingDescriptions
+ (deUint32)vertexAttribParams.size(), // attributeCount
+ &vertexAttribParams[0], // pVertexAttributeDescriptions
+ };
+ const vk::VkColorComponentFlags allCompMask = vk::VK_COLOR_COMPONENT_R_BIT
+ | vk::VK_COLOR_COMPONENT_G_BIT
+ | vk::VK_COLOR_COMPONENT_B_BIT
+ | vk::VK_COLOR_COMPONENT_A_BIT;
+ const vk::VkPipelineColorBlendAttachmentState attBlendParams =
+ {
+ vk::VK_FALSE, // blendEnable
+ vk::VK_BLEND_FACTOR_ONE, // srcBlendColor
+ vk::VK_BLEND_FACTOR_ZERO, // destBlendColor
+ vk::VK_BLEND_OP_ADD, // blendOpColor
+ vk::VK_BLEND_FACTOR_ONE, // srcBlendAlpha
+ vk::VK_BLEND_FACTOR_ZERO, // destBlendAlpha
+ vk::VK_BLEND_OP_ADD, // blendOpAlpha
+ allCompMask, // componentWriteMask
+ };
+ const vk::VkPipelineColorBlendStateCreateInfo blendParams =
+ {
+ vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ (vk::VkPipelineColorBlendStateCreateFlags)0,
+ vk::VK_FALSE, // logicOpEnable
+ vk::VK_LOGIC_OP_COPY, // logicOp
+ 1u, // attachmentCount
+ &attBlendParams, // pAttachments
+ { 0.0f, 0.0f, 0.0f, 0.0f }, // blendConstants
+ };
+ const vk::VkPipelineDynamicStateCreateInfo dynStateParams =
+ {
+ vk::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ (vk::VkPipelineDynamicStateCreateFlags)0,
+ 0u, // dynamicStateCount
+ DE_NULL, // pDynamicStates
+ };
+ const vk::VkGraphicsPipelineCreateInfo pipelineParams =
+ {
+ vk::VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ 0u, // flags
+ (deUint32)shaderStageParams.size(), // stageCount
+ &shaderStageParams[0], // pStages
+ &vertexInputStateParams, // pVertexInputState
+ &inputAssemblyParams, // pInputAssemblyState
+ DE_NULL, // pTessellationState
+ &viewportParams, // pViewportState
+ &rasterParams, // pRasterState
+ &multisampleParams, // pMultisampleState
+ &depthStencilParams, // pDepthStencilState
+ &blendParams, // pColorBlendState
+ &dynStateParams, // pDynamicState
+ pipelineLayout, // layout
+ renderPass, // renderPass
+ 0u, // subpass
+ DE_NULL, // basePipelineHandle
+ 0u, // basePipelineIndex
+ };
+
+ return vk::createGraphicsPipeline(context.getDeviceInterface(), context.getDevice(), DE_NULL, &pipelineParams);
+}
+
+Move<vk::VkFramebuffer> createFramebuffer (Context& context, vk::VkRenderPass renderPass, vk::VkImageView colorAttView, int width, int height)
+{
+ const vk::VkFramebufferCreateInfo framebufferParams =
+ {
+ vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ (vk::VkFramebufferCreateFlags)0,
+ renderPass, // renderPass
+ 1u, // attachmentCount
+ &colorAttView, // pAttachments
+ (deUint32)width, // width
+ (deUint32)height, // height
+ 1u, // layers
+ };
+
+ return vk::createFramebuffer(context.getDeviceInterface(), context.getDevice(), &framebufferParams);
+}
+
+Move<vk::VkCommandPool> createCommandPool (Context& context)
+{
+ const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
+ const vk::VkCommandPoolCreateInfo params =
+ {
+ vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ (vk::VkCommandPoolCreateFlags)0,
+ queueFamilyIndex, // queueFamilyIndex
+ };
+
+ return vk::createCommandPool(context.getDeviceInterface(), context.getDevice(), ¶ms);
+}
+
+Move<vk::VkDescriptorPool> createDescriptorPool (Context& context)
+{
+ return vk::DescriptorPoolBuilder()
+ .addType(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2u)
+ .build(context.getDeviceInterface(), context.getDevice(), vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
+}
+
+Move<vk::VkDescriptorSet> allocateDescriptorSet (Context& context, vk::VkDescriptorPool descriptorPool, vk::VkDescriptorSetLayout setLayout)
+{
+ const vk::VkDescriptorSetAllocateInfo params =
+ {
+ vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+ DE_NULL,
+ descriptorPool,
+ 1u,
+ &setLayout
+ };
+
+ return vk::allocateDescriptorSet(context.getDeviceInterface(), context.getDevice(), ¶ms);
+}
+
+Move<vk::VkCommandBuffer> allocateCommandBuffer (Context& context, vk::VkCommandPool cmdPool)
+{
+ const vk::VkCommandBufferAllocateInfo params =
+ {
+ vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType
+ DE_NULL, // pNext
+ cmdPool, // commandPool
+ vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level
+ 1u, // bufferCount
+ };
+
+ return vk::allocateCommandBuffer(context.getDeviceInterface(), context.getDevice(), ¶ms);
+}
+
+MovePtr<vk::Allocation> allocateAndBindMemory (Context& context, vk::VkBuffer buffer, vk::MemoryRequirement memReqs)
+{
+ const vk::DeviceInterface& vkd = context.getDeviceInterface();
+ const vk::VkMemoryRequirements bufReqs = vk::getBufferMemoryRequirements(vkd, context.getDevice(), buffer);
+ MovePtr<vk::Allocation> memory = context.getDefaultAllocator().allocate(bufReqs, memReqs);
+
+ vkd.bindBufferMemory(context.getDevice(), buffer, memory->getMemory(), memory->getOffset());
+
+ return memory;
+}
+
+MovePtr<vk::Allocation> allocateAndBindMemory (Context& context, vk::VkImage image, vk::MemoryRequirement memReqs)
+{
+ const vk::DeviceInterface& vkd = context.getDeviceInterface();
+ const vk::VkMemoryRequirements imgReqs = vk::getImageMemoryRequirements(vkd, context.getDevice(), image);
+ MovePtr<vk::Allocation> memory = context.getDefaultAllocator().allocate(imgReqs, memReqs);
+
+ vkd.bindImageMemory(context.getDevice(), image, memory->getMemory(), memory->getOffset());
+
+ return memory;
+}
+
+void writeValuesToMem (Context& context, const vk::Allocation& dst, const ValueBufferLayout& layout, const vector<Value>& values, int arrayNdx)
+{
+ copyToLayout(dst.getHostPtr(), layout, values, arrayNdx);
+
+ // \note Buffers are not allocated with coherency / uncached requirement so we need to manually flush CPU write caches
+ flushMappedMemoryRange(context.getDeviceInterface(), context.getDevice(), dst.getMemory(), dst.getOffset(), (vk::VkDeviceSize)layout.size);
+}
+
+class ShaderCaseInstance : public TestInstance
+{
+public:
+ ShaderCaseInstance (Context& context, const ShaderCaseSpecification& spec);
+ ~ShaderCaseInstance (void);
+
+ TestStatus iterate (void);
+
+private:
+ enum
+ {
+ RENDER_WIDTH = 64,
+ RENDER_HEIGHT = 64,
+
+ POSITIONS_OFFSET = 0,
+ POSITIONS_SIZE = (int)sizeof(Vec2)*4,
+
+ INDICES_OFFSET = POSITIONS_SIZE,
+ INDICES_SIZE = (int)sizeof(deUint16)*6,
+
+ TOTAL_POS_NDX_SIZE = POSITIONS_SIZE+INDICES_SIZE
+ };
+
+ const ShaderCaseSpecification& m_spec;
+
+ const Unique<vk::VkBuffer> m_posNdxBuffer;
+ const UniquePtr<vk::Allocation> m_posNdxMem;
+
+ const ValueBufferLayout m_inputLayout;
+ const Unique<vk::VkBuffer> m_inputBuffer; // Input values (attributes). Can be NULL if no inputs present
+ const UniquePtr<vk::Allocation> m_inputMem; // Input memory, can be NULL if no input buffer exists
+
+ const ValueBufferLayout m_referenceLayout;
+ const Unique<vk::VkBuffer> m_referenceBuffer; // Output (reference) values. Can be NULL if no outputs present
+ const UniquePtr<vk::Allocation> m_referenceMem; // Output (reference) memory, can be NULL if no reference buffer exists
+
+ const ValueBufferLayout m_uniformLayout;
+ const Unique<vk::VkBuffer> m_uniformBuffer; // Uniform values. Can be NULL if no uniforms present
+ const UniquePtr<vk::Allocation> m_uniformMem; // Uniform memory, can be NULL if no uniform buffer exists
+
+ const Unique<vk::VkBuffer> m_readImageBuffer;
+ const UniquePtr<vk::Allocation> m_readImageMem;
+
+ const Unique<vk::VkImage> m_rtImage;
+ const UniquePtr<vk::Allocation> m_rtMem;
+ const Unique<vk::VkImageView> m_rtView;
+
+ const Unique<vk::VkRenderPass> m_renderPass;
+ const Unique<vk::VkFramebuffer> m_framebuffer;
+ const PipelineProgram m_program;
+ const Unique<vk::VkDescriptorSetLayout> m_descriptorSetLayout;
+ const Unique<vk::VkPipelineLayout> m_pipelineLayout;
+ const Unique<vk::VkPipeline> m_pipeline;
+
+ const Unique<vk::VkDescriptorPool> m_descriptorPool;
+ const Unique<vk::VkDescriptorSet> m_descriptorSet;
+
+ const Unique<vk::VkCommandPool> m_cmdPool;
+ const Unique<vk::VkCommandBuffer> m_cmdBuffer;
+
+ int m_subCaseNdx;
+};
+
+ShaderCaseInstance::ShaderCaseInstance (Context& context, const ShaderCaseSpecification& spec)
+ : TestInstance (context)
+ , m_spec (spec)
+
+ , m_posNdxBuffer (createBuffer(context, (vk::VkDeviceSize)TOTAL_POS_NDX_SIZE, vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT|vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT))
+ , m_posNdxMem (allocateAndBindMemory(context, *m_posNdxBuffer, vk::MemoryRequirement::HostVisible))
+
+ , m_inputLayout (computeStd430Layout(spec.values.inputs))
+ , m_inputBuffer (m_inputLayout.size > 0 ? createBuffer(context, (vk::VkDeviceSize)m_inputLayout.size, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT) : Move<vk::VkBuffer>())
+ , m_inputMem (m_inputLayout.size > 0 ? allocateAndBindMemory(context, *m_inputBuffer, vk::MemoryRequirement::HostVisible) : MovePtr<vk::Allocation>())
+
+ , m_referenceLayout (computeStd140Layout(spec.values.outputs))
+ , m_referenceBuffer (m_referenceLayout.size > 0 ? createBuffer(context, (vk::VkDeviceSize)m_referenceLayout.size, vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) : Move<vk::VkBuffer>())
+ , m_referenceMem (m_referenceLayout.size > 0 ? allocateAndBindMemory(context, *m_referenceBuffer, vk::MemoryRequirement::HostVisible) : MovePtr<vk::Allocation>())
+
+ , m_uniformLayout (computeStd140Layout(spec.values.uniforms))
+ , m_uniformBuffer (m_uniformLayout.size > 0 ? createBuffer(context, (vk::VkDeviceSize)m_uniformLayout.size, vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) : Move<vk::VkBuffer>())
+ , m_uniformMem (m_uniformLayout.size > 0 ? allocateAndBindMemory(context, *m_uniformBuffer, vk::MemoryRequirement::HostVisible) : MovePtr<vk::Allocation>())
+
+ , m_readImageBuffer (createBuffer(context, (vk::VkDeviceSize)(RENDER_WIDTH*RENDER_HEIGHT*4), vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT))
+ , m_readImageMem (allocateAndBindMemory(context, *m_readImageBuffer, vk::MemoryRequirement::HostVisible))
+
+ , m_rtImage (createImage2D(context, RENDER_WIDTH, RENDER_HEIGHT, vk::VK_FORMAT_R8G8B8A8_UNORM, vk::VK_IMAGE_TILING_OPTIMAL, vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT))
+ , m_rtMem (allocateAndBindMemory(context, *m_rtImage, vk::MemoryRequirement::Any))
+ , m_rtView (createAttachmentView(context, *m_rtImage, vk::VK_FORMAT_R8G8B8A8_UNORM))
+
+ , m_renderPass (createRenderPass(context, vk::VK_FORMAT_R8G8B8A8_UNORM))
+ , m_framebuffer (createFramebuffer(context, *m_renderPass, *m_rtView, RENDER_WIDTH, RENDER_HEIGHT))
+ , m_program (context, spec)
+ , m_descriptorSetLayout (createDescriptorSetLayout(context, m_program.getStages()))
+ , m_pipelineLayout (createPipelineLayout(context, *m_descriptorSetLayout))
+ , m_pipeline (createPipeline(context, spec.values.inputs, m_inputLayout, m_program, *m_renderPass, *m_pipelineLayout, tcu::IVec2(RENDER_WIDTH, RENDER_HEIGHT)))
+
+ , m_descriptorPool (createDescriptorPool(context))
+ , m_descriptorSet (allocateDescriptorSet(context, *m_descriptorPool, *m_descriptorSetLayout))
+
+ , m_cmdPool (createCommandPool(context))
+ , m_cmdBuffer (allocateCommandBuffer(context, *m_cmdPool))
+
+ , m_subCaseNdx (0)
+{
+ const vk::DeviceInterface& vkd = context.getDeviceInterface();
+ const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
+
+ {
+ const Vec2 s_positions[] =
+ {
+ Vec2(-1.0f, -1.0f),
+ Vec2(-1.0f, +1.0f),
+ Vec2(+1.0f, -1.0f),
+ Vec2(+1.0f, +1.0f)
+ };
+ const deUint16 s_indices[] =
+ {
+ 0, 1, 2,
+ 1, 3, 2
+ };
+
+ DE_STATIC_ASSERT(sizeof(s_positions) == POSITIONS_SIZE);
+ DE_STATIC_ASSERT(sizeof(s_indices) == INDICES_SIZE);
+
+ deMemcpy((deUint8*)m_posNdxMem->getHostPtr() + POSITIONS_OFFSET, &s_positions[0], sizeof(s_positions));
+ deMemcpy((deUint8*)m_posNdxMem->getHostPtr() + INDICES_OFFSET, &s_indices[0], sizeof(s_indices));
+
+ flushMappedMemoryRange(m_context.getDeviceInterface(), context.getDevice(), m_posNdxMem->getMemory(), m_posNdxMem->getOffset(), sizeof(s_positions)+sizeof(s_indices));
+ }
+
+ if (!m_spec.values.uniforms.empty())
+ {
+ const vk::VkDescriptorBufferInfo bufInfo =
+ {
+ *m_uniformBuffer,
+ (vk::VkDeviceSize)0, // offset
+ (vk::VkDeviceSize)m_uniformLayout.size
+ };
+
+ vk::DescriptorSetUpdateBuilder()
+ .writeSingle(*m_descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(USER_UNIFORM_BINDING),
+ vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &bufInfo)
+ .update(vkd, m_context.getDevice());
+ }
+
+ if (!m_spec.values.outputs.empty())
+ {
+ const vk::VkDescriptorBufferInfo bufInfo =
+ {
+ *m_referenceBuffer,
+ (vk::VkDeviceSize)0, // offset
+ (vk::VkDeviceSize)m_referenceLayout.size
+ };
+
+ vk::DescriptorSetUpdateBuilder()
+ .writeSingle(*m_descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(REFERENCE_UNIFORM_BINDING),
+ vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &bufInfo)
+ .update(vkd, m_context.getDevice());
+ }
+
+ // Record command buffer
+
+ {
+ const vk::VkCommandBufferBeginInfo beginInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
+ DE_NULL, // pNext
+ 0u, // flags
+ (vk::VkRenderPass)0, // renderPass
+ 0u, // subpass
+ (vk::VkFramebuffer)0, // framebuffer
+ vk::VK_FALSE, // occlusionQueryEnable
+ (vk::VkQueryControlFlags)0,
+ (vk::VkQueryPipelineStatisticFlags)0
+ };
+
+ VK_CHECK(vkd.beginCommandBuffer(*m_cmdBuffer, &beginInfo));
+ }
+
+ {
+ const vk::VkMemoryBarrier vertFlushBarrier =
+ {
+ vk::VK_STRUCTURE_TYPE_MEMORY_BARRIER, // sType
+ DE_NULL, // pNext
+ vk::VK_ACCESS_HOST_WRITE_BIT, // srcAccessMask
+ vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT|vk::VK_ACCESS_UNIFORM_READ_BIT, // dstAccessMask
+ };
+ const vk::VkImageMemoryBarrier colorAttBarrier =
+ {
+ vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
+ DE_NULL, // pNext
+ 0u, // srcAccessMask
+ vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // dstAccessMask
+ vk::VK_IMAGE_LAYOUT_UNDEFINED, // oldLayout
+ vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // newLayout
+ queueFamilyIndex, // srcQueueFamilyIndex
+ queueFamilyIndex, // destQueueFamilyIndex
+ *m_rtImage, // image
+ {
+ vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
+ 0u, // baseMipLevel
+ 1u, // mipLevels
+ 0u, // baseArraySlice
+ 1u, // arraySize
+ } // subresourceRange
+ };
+ const void* const barriers[] = { &vertFlushBarrier, &colorAttBarrier };
+
+ vkd.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
+ DE_FALSE, (deUint32)DE_LENGTH_OF_ARRAY(barriers), barriers);
+ }
+
+ {
+ const vk::VkClearValue clearValue = vk::makeClearValueColorF32(0.125f, 0.25f, 0.75f, 1.0f);
+ const vk::VkRenderPassBeginInfo passBeginInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // sType
+ DE_NULL, // pNext
+ *m_renderPass, // renderPass
+ *m_framebuffer, // framebuffer
+ { { 0, 0 }, { RENDER_WIDTH, RENDER_HEIGHT } }, // renderArea
+ 1u, // clearValueCount
+ &clearValue, // pClearValues
+ };
+
+ vkd.cmdBeginRenderPass(*m_cmdBuffer, &passBeginInfo, vk::VK_SUBPASS_CONTENTS_INLINE);
+ }
+
+ vkd.cmdBindPipeline (*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
+ vkd.cmdBindDescriptorSets (*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1u, &*m_descriptorSet, 0u, DE_NULL);
+
+ {
+ const vk::VkBuffer buffers[] = { *m_posNdxBuffer, *m_inputBuffer };
+ const vk::VkDeviceSize offsets[] = { POSITIONS_OFFSET, 0u };
+ const deUint32 numBuffers = buffers[1] != 0 ? 2u : 1u;
+ vkd.cmdBindVertexBuffers(*m_cmdBuffer, 0u, numBuffers, buffers, offsets);
+ }
+
+ vkd.cmdBindIndexBuffer (*m_cmdBuffer, *m_posNdxBuffer, (vk::VkDeviceSize)INDICES_OFFSET, vk::VK_INDEX_TYPE_UINT16);
+ vkd.cmdDrawIndexed (*m_cmdBuffer, 6u, 1u, 0u, 0u, 0u);
+ vkd.cmdEndRenderPass (*m_cmdBuffer);
+
+ {
+ const vk::VkImageMemoryBarrier renderFinishBarrier =
+ {
+ vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
+ DE_NULL, // pNext
+ vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // srcAccessMask
+ vk::VK_ACCESS_TRANSFER_READ_BIT, // dstAccessMask
+ vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // oldLayout
+ vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // newLayout
+ queueFamilyIndex, // srcQueueFamilyIndex
+ queueFamilyIndex, // destQueueFamilyIndex
+ *m_rtImage, // image
+ {
+ vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
+ 0u, // baseMipLevel
+ 1u, // mipLevels
+ 0u, // baseArraySlice
+ 1u, // arraySize
+ } // subresourceRange
+ };
+ const void* const barriers[] = { &renderFinishBarrier };
+
+ vkd.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
+ DE_FALSE, DE_LENGTH_OF_ARRAY(barriers), barriers);
+ }
+
+ {
+ const vk::VkBufferImageCopy copyParams =
+ {
+ (vk::VkDeviceSize)0u, // bufferOffset
+ (deUint32)RENDER_WIDTH, // bufferRowLength
+ (deUint32)RENDER_HEIGHT, // bufferImageHeight
+ {
+ vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspect
+ 0u, // mipLevel
+ 0u, // arrayLayer
+ 1u, // arraySize
+ }, // imageSubresource
+ { 0u, 0u, 0u }, // imageOffset
+ { RENDER_WIDTH, RENDER_HEIGHT, 1u } // imageExtent
+ };
+
+ vkd.cmdCopyImageToBuffer(*m_cmdBuffer, *m_rtImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *m_readImageBuffer, 1u, ©Params);
+ }
+
+ {
+ const vk::VkBufferMemoryBarrier copyFinishBarrier =
+ {
+ vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // sType
+ DE_NULL, // pNext
+ vk::VK_ACCESS_TRANSFER_WRITE_BIT, // srcAccessMask
+ vk::VK_ACCESS_HOST_READ_BIT, // dstAccessMask
+ queueFamilyIndex, // srcQueueFamilyIndex
+ queueFamilyIndex, // destQueueFamilyIndex
+ *m_readImageBuffer, // buffer
+ 0u, // offset
+ (vk::VkDeviceSize)(RENDER_WIDTH*RENDER_HEIGHT*4) // size
+ };
+ const void* const barriers[] = { ©FinishBarrier };
+
+ vkd.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT,
+ DE_FALSE, (deUint32)DE_LENGTH_OF_ARRAY(barriers), barriers);
+ }
+
+ VK_CHECK(vkd.endCommandBuffer(*m_cmdBuffer));
+}
+
+ShaderCaseInstance::~ShaderCaseInstance (void)
+{
+}
+
+int getNumSubCases (const ValueBlock& values)
+{
+ if (!values.outputs.empty())
+ return int(values.outputs[0].elements.size() / values.outputs[0].type.getScalarSize());
+ else
+ return 1; // Always run at least one iteration even if no output values are specified
+}
+
+bool checkResultImage (const ConstPixelBufferAccess& result)
+{
+ const tcu::IVec4 refPix (255, 255, 255, 255);
+
+ for (int y = 0; y < result.getHeight(); y++)
+ {
+ for (int x = 0; x < result.getWidth(); x++)
+ {
+ const tcu::IVec4 resPix = result.getPixelInt(x, y);
+
+ if (boolAny(notEqual(resPix, refPix)))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+TestStatus ShaderCaseInstance::iterate (void)
+{
+ const vk::DeviceInterface& vkd = m_context.getDeviceInterface();
+ const vk::VkDevice device = m_context.getDevice();
+ const vk::VkQueue queue = m_context.getUniversalQueue();
+
+ if (!m_spec.values.inputs.empty())
+ writeValuesToMem(m_context, *m_inputMem, m_inputLayout, m_spec.values.inputs, m_subCaseNdx);
+
+ if (!m_spec.values.outputs.empty())
+ writeValuesToMem(m_context, *m_referenceMem, m_referenceLayout, m_spec.values.outputs, m_subCaseNdx);
+
+ if (!m_spec.values.uniforms.empty())
+ writeValuesToMem(m_context, *m_uniformMem, m_uniformLayout, m_spec.values.uniforms, m_subCaseNdx);
+
+ {
+ const vk::VkSubmitInfo submitInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
+ DE_NULL,
+ 0u, // waitSemaphoreCount
+ (const vk::VkSemaphore*)0, // pWaitSemaphores
+ 1u,
+ &m_cmdBuffer.get(),
+ 0u, // signalSemaphoreCount
+ (const vk::VkSemaphore*)0, // pSignalSemaphores
+ };
+ const vk::VkFenceCreateInfo fenceParams =
+ {
+ vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ 0u, // flags
+ };
+ const Unique<vk::VkFence> fence (vk::createFence(vkd, device, &fenceParams));
+
+ VK_CHECK(vkd.queueSubmit (queue, 1u, &submitInfo, *fence));
+ VK_CHECK(vkd.waitForFences (device, 1u, &fence.get(), DE_TRUE, ~0ull));
+ }
+
+ {
+ const ConstPixelBufferAccess imgAccess (TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), RENDER_WIDTH, RENDER_HEIGHT, 1, m_readImageMem->getHostPtr());
+
+ invalidateMappedMemoryRange(vkd, device, m_readImageMem->getMemory(), m_readImageMem->getOffset(), (vk::VkDeviceSize)(RENDER_WIDTH*RENDER_HEIGHT*4));
+
+ if (!checkResultImage(imgAccess))
+ {
+ TestLog& log = m_context.getTestContext().getLog();
+
+ log << TestLog::Message << "ERROR: Got non-white pixels on sub-case " << m_subCaseNdx << TestLog::EndMessage
+ << TestLog::Image("Result", "Result", imgAccess);
+
+ dumpValues(log, m_spec.values, m_subCaseNdx);
+
+ return TestStatus::fail(string("Got invalid pixels at sub-case ") + de::toString(m_subCaseNdx));
+ }
+ }
+
+ if (++m_subCaseNdx < getNumSubCases(m_spec.values))
+ return TestStatus::incomplete();
+ else
+ return TestStatus::pass("All sub-cases passed");
+}
+
+class ShaderCase : public TestCase
+{
+public:
+ ShaderCase (tcu::TestContext& testCtx, const string& name, const string& description, const ShaderCaseSpecification& spec);
+
+
+ void initPrograms (SourceCollections& programCollection) const;
+ TestInstance* createInstance (Context& context) const;
+
+private:
+ const ShaderCaseSpecification m_spec;
+};
+
+ShaderCase::ShaderCase (tcu::TestContext& testCtx, const string& name, const string& description, const ShaderCaseSpecification& spec)
+ : TestCase (testCtx, name, description)
+ , m_spec (spec)
+{
+}
+
+void ShaderCase::initPrograms (SourceCollections& sourceCollection) const
+{
+ vector<ProgramSources> specializedSources (m_spec.programs.size());
+
+ DE_ASSERT(isValid(m_spec));
+
+ if (m_spec.expectResult != glu::sl::EXPECT_PASS)
+ TCU_THROW(InternalError, "Only EXPECT_PASS is supported");
+
+ if (m_spec.caseType == glu::sl::CASETYPE_VERTEX_ONLY)
+ {
+ DE_ASSERT(m_spec.programs.size() == 1 && m_spec.programs[0].sources.sources[glu::SHADERTYPE_VERTEX].size() == 1);
+ specializedSources[0] << glu::VertexSource(specializeVertexShader(m_spec, m_spec.programs[0].sources.sources[glu::SHADERTYPE_VERTEX][0]))
+ << glu::FragmentSource(genFragmentShader(m_spec));
+ }
+ else if (m_spec.caseType == glu::sl::CASETYPE_FRAGMENT_ONLY)
+ {
+ DE_ASSERT(m_spec.programs.size() == 1 && m_spec.programs[0].sources.sources[glu::SHADERTYPE_FRAGMENT].size() == 1);
+ specializedSources[0] << glu::VertexSource(genVertexShader(m_spec))
+ << glu::FragmentSource(specializeFragmentShader(m_spec, m_spec.programs[0].sources.sources[glu::SHADERTYPE_FRAGMENT][0]));
+ }
+ else
+ {
+ DE_ASSERT(m_spec.caseType == glu::sl::CASETYPE_COMPLETE);
+
+ const int maxPatchVertices = 4; // \todo [2015-08-05 pyry] Query
+
+ for (size_t progNdx = 0; progNdx < m_spec.programs.size(); progNdx++)
+ {
+ const ProgramSpecializationParams progSpecParams (m_spec, m_spec.programs[progNdx].requiredExtensions, maxPatchVertices);
+
+ specializeProgramSources(specializedSources[progNdx], m_spec.programs[progNdx].sources, progSpecParams);
+ }
+ }
+
+ for (size_t progNdx = 0; progNdx < specializedSources.size(); progNdx++)
+ {
+ for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++)
+ {
+ if (!specializedSources[progNdx].sources[shaderType].empty())
+ {
+ glu::ProgramSources& curSrc = sourceCollection.glslSources.add(getShaderName((glu::ShaderType)shaderType, progNdx));
+ curSrc.sources[shaderType] = specializedSources[progNdx].sources[shaderType];
+ }
+ }
+ }
+}
+
+TestInstance* ShaderCase::createInstance (Context& context) const
+{
+ return new ShaderCaseInstance(context, m_spec);
+}
+
+class ShaderCaseFactory : public glu::sl::ShaderCaseFactory
+{
+public:
+ ShaderCaseFactory (tcu::TestContext& testCtx)
+ : m_testCtx(testCtx)
+ {
+ }
+
+ tcu::TestCaseGroup* createGroup (const string& name, const string& description, const vector<tcu::TestNode*>& children)
+ {
+ return new tcu::TestCaseGroup(m_testCtx, name.c_str(), description.c_str(), children);
+ }
+
+ tcu::TestCase* createCase (const string& name, const string& description, const ShaderCaseSpecification& spec)
+ {
+ return new ShaderCase(m_testCtx, name, description, spec);
+ }
+
+private:
+ tcu::TestContext& m_testCtx;
+};
+
+class ShaderLibraryGroup : public tcu::TestCaseGroup
+{
+public:
+ ShaderLibraryGroup (tcu::TestContext& testCtx, const string& name, const string& description, const string& filename)
+ : tcu::TestCaseGroup (testCtx, name.c_str(), description.c_str())
+ , m_filename (filename)
+ {
+ }
+
+ void init (void)
+ {
+ ShaderCaseFactory caseFactory (m_testCtx);
+ const vector<tcu::TestNode*> children = glu::sl::parseFile(m_testCtx.getArchive(), m_filename, &caseFactory);
+
+ for (size_t ndx = 0; ndx < children.size(); ndx++)
+ {
+ try
+ {
+ addChild(children[ndx]);
+ }
+ catch (...)
+ {
+ for (; ndx < children.size(); ndx++)
+ delete children[ndx];
+ throw;
+ }
+ }
+ }
+
+private:
+ const string m_filename;
+};
+
+} // anonymous
+
+MovePtr<tcu::TestCaseGroup> createShaderLibraryGroup (tcu::TestContext& testCtx, const string& name, const string& description, const string& filename)
+{
+ return MovePtr<tcu::TestCaseGroup>(new ShaderLibraryGroup(testCtx, name, description, filename));
+}
+
+} // vkt
--- /dev/null
+#ifndef _VKTSHADERLIBRARY_HPP
+#define _VKTSHADERLIBRARY_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief ShaderLibrary Vulkan implementation
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+#include "deUniquePtr.hpp"
+
+namespace vkt
+{
+
+de::MovePtr<tcu::TestCaseGroup> createShaderLibraryGroup (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const std::string& filename);
+
+} // vkt
+
+#endif // _VKTSHADERLIBRARY_HPP
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Vulkan test case base classes
+ *//*--------------------------------------------------------------------*/
+
+#include "vktTestCase.hpp"
+
+#include "vkRef.hpp"
+#include "vkRefUtil.hpp"
+#include "vkQueryUtil.hpp"
+#include "vkDeviceUtil.hpp"
+#include "vkMemUtil.hpp"
+#include "vkPlatform.hpp"
+
+#include "deMemory.h"
+
+namespace vkt
+{
+
+// Default device utilities
+
+using std::vector;
+using namespace vk;
+
+static deUint32 findQueueFamilyIndexWithCaps (const InstanceInterface& vkInstance, VkPhysicalDevice physicalDevice, VkQueueFlags requiredCaps)
+{
+ const vector<VkQueueFamilyProperties> queueProps = getPhysicalDeviceQueueFamilyProperties(vkInstance, physicalDevice);
+
+ for (size_t queueNdx = 0; queueNdx < queueProps.size(); queueNdx++)
+ {
+ if ((queueProps[queueNdx].queueFlags & requiredCaps) == requiredCaps)
+ return (deUint32)queueNdx;
+ }
+
+ TCU_THROW(NotSupportedError, "No matching queue found");
+}
+
+Move<VkDevice> createDefaultDevice (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, deUint32 queueIndex, const VkPhysicalDeviceFeatures& enabledFeatures)
+{
+ VkDeviceQueueCreateInfo queueInfo;
+ VkDeviceCreateInfo deviceInfo;
+ const float queuePriority = 1.0f;
+
+ deMemset(&queueInfo, 0, sizeof(queueInfo));
+ deMemset(&deviceInfo, 0, sizeof(deviceInfo));
+
+ queueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
+ queueInfo.pNext = DE_NULL;
+ queueInfo.flags = (VkDeviceQueueCreateFlags)0u;
+ queueInfo.queueFamilyIndex = queueIndex;
+ queueInfo.queueCount = 1u;
+ queueInfo.pQueuePriorities = &queuePriority;
+
+ deviceInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
+ deviceInfo.pNext = DE_NULL;
+ deviceInfo.queueCreateInfoCount = 1u;
+ deviceInfo.pQueueCreateInfos = &queueInfo;
+ deviceInfo.enabledExtensionNameCount = 0u;
+ deviceInfo.ppEnabledExtensionNames = DE_NULL;
+ deviceInfo.enabledLayerNameCount = 0u;
+ deviceInfo.ppEnabledLayerNames = DE_NULL;
+ deviceInfo.pEnabledFeatures = &enabledFeatures;
+
+ return createDevice(vki, physicalDevice, &deviceInfo);
+};
+
+class DefaultDevice
+{
+public:
+ DefaultDevice (const PlatformInterface& vkPlatform, const tcu::CommandLine& cmdLine);
+ ~DefaultDevice (void);
+
+ VkInstance getInstance (void) const { return *m_instance; }
+ const InstanceInterface& getInstanceInterface (void) const { return m_instanceInterface; }
+
+ VkPhysicalDevice getPhysicalDevice (void) const { return m_physicalDevice; }
+ const VkPhysicalDeviceFeatures& getDeviceFeatures (void) const { return m_deviceFeatures; }
+ VkDevice getDevice (void) const { return *m_device; }
+ const DeviceInterface& getDeviceInterface (void) const { return m_deviceInterface; }
+
+ deUint32 getUniversalQueueFamilyIndex (void) const { return m_universalQueueFamilyIndex; }
+ VkQueue getUniversalQueue (void) const;
+
+private:
+ const Unique<VkInstance> m_instance;
+ const InstanceDriver m_instanceInterface;
+
+ const VkPhysicalDevice m_physicalDevice;
+
+ const deUint32 m_universalQueueFamilyIndex;
+ const VkPhysicalDeviceFeatures m_deviceFeatures;
+
+ const Unique<VkDevice> m_device;
+ const DeviceDriver m_deviceInterface;
+};
+
+DefaultDevice::DefaultDevice (const PlatformInterface& vkPlatform, const tcu::CommandLine& cmdLine)
+ : m_instance (createDefaultInstance(vkPlatform))
+ , m_instanceInterface (vkPlatform, *m_instance)
+ , m_physicalDevice (chooseDevice(m_instanceInterface, *m_instance, cmdLine))
+ , m_universalQueueFamilyIndex (findQueueFamilyIndexWithCaps(m_instanceInterface, m_physicalDevice, VK_QUEUE_GRAPHICS_BIT|VK_QUEUE_COMPUTE_BIT))
+ , m_deviceFeatures (getPhysicalDeviceFeatures(m_instanceInterface, m_physicalDevice)) // \note All supported features are enabled
+ , m_device (createDefaultDevice(m_instanceInterface, m_physicalDevice, m_universalQueueFamilyIndex, m_deviceFeatures))
+ , m_deviceInterface (m_instanceInterface, *m_device)
+{
+}
+
+DefaultDevice::~DefaultDevice (void)
+{
+}
+
+VkQueue DefaultDevice::getUniversalQueue (void) const
+{
+ VkQueue queue = 0;
+ m_deviceInterface.getDeviceQueue(*m_device, m_universalQueueFamilyIndex, 0, &queue);
+ return queue;
+}
+
+// Allocator utilities
+
+vk::Allocator* createAllocator (DefaultDevice* device)
+{
+ const VkPhysicalDeviceMemoryProperties memoryProperties = vk::getPhysicalDeviceMemoryProperties(device->getInstanceInterface(), device->getPhysicalDevice());
+
+ // \todo [2015-07-24 jarkko] support allocator selection/configuration from command line (or compile time)
+ return new SimpleAllocator(device->getDeviceInterface(), device->getDevice(), memoryProperties);
+}
+
+// Context
+
+Context::Context (tcu::TestContext& testCtx,
+ const vk::PlatformInterface& platformInterface,
+ vk::ProgramCollection<vk::ProgramBinary>& progCollection)
+ : m_testCtx (testCtx)
+ , m_platformInterface (platformInterface)
+ , m_progCollection (progCollection)
+ , m_device (new DefaultDevice(m_platformInterface, testCtx.getCommandLine()))
+ , m_allocator (createAllocator(m_device.get()))
+{
+}
+
+Context::~Context (void)
+{
+}
+
+vk::VkInstance Context::getInstance (void) const { return m_device->getInstance(); }
+const vk::InstanceInterface& Context::getInstanceInterface (void) const { return m_device->getInstanceInterface(); }
+vk::VkPhysicalDevice Context::getPhysicalDevice (void) const { return m_device->getPhysicalDevice(); }
+const vk::VkPhysicalDeviceFeatures& Context::getDeviceFeatures (void) const { return m_device->getDeviceFeatures(); }
+vk::VkDevice Context::getDevice (void) const { return m_device->getDevice(); }
+const vk::DeviceInterface& Context::getDeviceInterface (void) const { return m_device->getDeviceInterface(); }
+deUint32 Context::getUniversalQueueFamilyIndex (void) const { return m_device->getUniversalQueueFamilyIndex(); }
+vk::VkQueue Context::getUniversalQueue (void) const { return m_device->getUniversalQueue(); }
+vk::Allocator& Context::getDefaultAllocator (void) const { return *m_allocator; }
+
+// TestCase
+
+void TestCase::initPrograms (SourceCollections&) const
+{
+}
+
+} // vkt
--- /dev/null
+#ifndef _VKTTESTCASE_HPP
+#define _VKTTESTCASE_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Vulkan test case base classes
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+#include "vkDefs.hpp"
+#include "deUniquePtr.hpp"
+
+namespace glu
+{
+struct ProgramSources;
+}
+
+namespace vk
+{
+class PlatformInterface;
+class ProgramBinary;
+template<typename Program> class ProgramCollection;
+class Allocator;
+struct SourceCollections;
+}
+
+namespace vkt
+{
+
+class DefaultDevice;
+
+class Context
+{
+public:
+ Context (tcu::TestContext& testCtx,
+ const vk::PlatformInterface& platformInterface,
+ vk::ProgramCollection<vk::ProgramBinary>& progCollection);
+ ~Context (void);
+
+ tcu::TestContext& getTestContext (void) const { return m_testCtx; }
+ const vk::PlatformInterface& getPlatformInterface (void) const { return m_platformInterface; }
+ vk::ProgramCollection<vk::ProgramBinary>& getBinaryCollection (void) const { return m_progCollection; }
+
+ // Default instance & device, selected with --deqp-vk-device-id=N
+ vk::VkInstance getInstance (void) const;
+ const vk::InstanceInterface& getInstanceInterface (void) const;
+ vk::VkPhysicalDevice getPhysicalDevice (void) const;
+ const vk::VkPhysicalDeviceFeatures& getDeviceFeatures (void) const;
+ vk::VkDevice getDevice (void) const;
+ const vk::DeviceInterface& getDeviceInterface (void) const;
+ deUint32 getUniversalQueueFamilyIndex (void) const;
+ vk::VkQueue getUniversalQueue (void) const;
+
+ vk::Allocator& getDefaultAllocator (void) const;
+
+protected:
+ tcu::TestContext& m_testCtx;
+ const vk::PlatformInterface& m_platformInterface;
+ vk::ProgramCollection<vk::ProgramBinary>& m_progCollection;
+
+ const de::UniquePtr<DefaultDevice> m_device;
+ const de::UniquePtr<vk::Allocator> m_allocator;
+
+private:
+ Context (const Context&); // Not allowed
+ Context& operator= (const Context&); // Not allowed
+};
+
+
+class TestInstance;
+
+class TestCase : public tcu::TestCase
+{
+public:
+ TestCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description);
+ TestCase (tcu::TestContext& testCtx, tcu::TestNodeType type, const std::string& name, const std::string& description);
+ virtual ~TestCase (void) {}
+
+ virtual void initPrograms (vk::SourceCollections& programCollection) const;
+ virtual TestInstance* createInstance (Context& context) const = 0;
+
+ IterateResult iterate (void) { DE_ASSERT(false); return STOP; } // Deprecated in this module
+};
+
+class TestInstance
+{
+public:
+ TestInstance (Context& context) : m_context(context) {}
+ virtual ~TestInstance (void) {}
+
+ virtual tcu::TestStatus iterate (void) = 0;
+
+protected:
+ Context& m_context;
+
+private:
+ TestInstance (const TestInstance&);
+ TestInstance& operator= (const TestInstance&);
+};
+
+inline TestCase::TestCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description)
+ : tcu::TestCase(testCtx, name.c_str(), description.c_str())
+{
+}
+
+inline TestCase::TestCase (tcu::TestContext& testCtx, tcu::TestNodeType type, const std::string& name, const std::string& description)
+ : tcu::TestCase(testCtx, type, name.c_str(), description.c_str())
+{
+}
+
+} // vkt
+
+#endif // _VKTTESTCASE_HPP
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief TestCase utilities
+ *//*--------------------------------------------------------------------*/
+
+#include "vktTestCaseUtil.hpp"
+
+DE_EMPTY_CPP_FILE
--- /dev/null
+#ifndef _VKTTESTCASEUTIL_HPP
+#define _VKTTESTCASEUTIL_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief TestCase utilities
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "vktTestCase.hpp"
+
+namespace vkt
+{
+
+template<typename Arg0>
+struct NoPrograms1
+{
+ void init (vk::SourceCollections&, Arg0) const {}
+};
+
+template<typename Instance, typename Arg0, typename Programs = NoPrograms1<Arg0> >
+class InstanceFactory1 : public TestCase
+{
+public:
+ InstanceFactory1 (tcu::TestContext& testCtx, tcu::TestNodeType type, const std::string& name, const std::string& desc, const Arg0& arg0)
+ : TestCase (testCtx, type, name, desc)
+ , m_progs ()
+ , m_arg0 (arg0)
+ {}
+
+ InstanceFactory1 (tcu::TestContext& testCtx, tcu::TestNodeType type, const std::string& name, const std::string& desc, const Programs& progs, const Arg0& arg0)
+ : TestCase (testCtx, type, name, desc)
+ , m_progs (progs)
+ , m_arg0 (arg0)
+ {}
+
+ void initPrograms (vk::SourceCollections& dst) const { m_progs.init(dst, m_arg0); }
+ TestInstance* createInstance (Context& context) const { return new Instance(context, m_arg0); }
+
+private:
+ const Programs m_progs;
+ const Arg0 m_arg0;
+};
+
+class FunctionInstance0 : public TestInstance
+{
+public:
+ typedef tcu::TestStatus (*Function) (Context& context);
+
+ FunctionInstance0 (Context& context, Function function)
+ : TestInstance (context)
+ , m_function (function)
+ {}
+
+ tcu::TestStatus iterate (void) { return m_function(m_context); }
+
+private:
+ const Function m_function;
+};
+
+template<typename Arg0>
+class FunctionInstance1 : public TestInstance
+{
+public:
+ typedef tcu::TestStatus (*Function) (Context& context, Arg0 arg0);
+
+ struct Args
+ {
+ Args (Function func_, Arg0 arg0_) : func(func_), arg0(arg0_) {}
+
+ Function func;
+ Arg0 arg0;
+ };
+
+ FunctionInstance1 (Context& context, const Args& args)
+ : TestInstance (context)
+ , m_args (args)
+ {}
+
+ tcu::TestStatus iterate (void) { return m_args.func(m_context, m_args.arg0); }
+
+private:
+ const Args m_args;
+};
+
+class FunctionPrograms0
+{
+public:
+ typedef void (*Function) (vk::SourceCollections& dst);
+
+ FunctionPrograms0 (Function func)
+ : m_func(func)
+ {}
+
+ void init (vk::SourceCollections& dst, FunctionInstance0::Function) const { m_func(dst); }
+
+private:
+ const Function m_func;
+};
+
+template<typename Arg0>
+class FunctionPrograms1
+{
+public:
+ typedef void (*Function) (vk::SourceCollections& dst, Arg0 arg0);
+
+ FunctionPrograms1 (Function func)
+ : m_func(func)
+ {}
+
+ void init (vk::SourceCollections& dst, const typename FunctionInstance1<Arg0>::Args& args) const { m_func(dst, args.arg0); }
+
+private:
+ const Function m_func;
+};
+
+// createFunctionCase
+
+inline TestCase* createFunctionCase (tcu::TestContext& testCtx,
+ tcu::TestNodeType type,
+ const std::string& name,
+ const std::string& desc,
+ FunctionInstance0::Function testFunction)
+{
+ return new InstanceFactory1<FunctionInstance0, FunctionInstance0::Function>(testCtx, type, name, desc, testFunction);
+}
+
+inline TestCase* createFunctionCaseWithPrograms (tcu::TestContext& testCtx,
+ tcu::TestNodeType type,
+ const std::string& name,
+ const std::string& desc,
+ FunctionPrograms0::Function initPrograms,
+ FunctionInstance0::Function testFunction)
+{
+ return new InstanceFactory1<FunctionInstance0, FunctionInstance0::Function, FunctionPrograms0>(
+ testCtx, type, name, desc, FunctionPrograms0(initPrograms), testFunction);
+}
+
+template<typename Arg0>
+TestCase* createFunctionCase (tcu::TestContext& testCtx,
+ tcu::TestNodeType type,
+ const std::string& name,
+ const std::string& desc,
+ typename FunctionInstance1<Arg0>::Function testFunction,
+ Arg0 arg0)
+{
+ return new InstanceFactory1<FunctionInstance1<Arg0>, typename FunctionInstance1<Arg0>::Args>(
+ testCtx, type, name, desc, typename FunctionInstance1<Arg0>::Args(testFunction, arg0));
+}
+
+template<typename Arg0>
+TestCase* createFunctionCaseWithPrograms (tcu::TestContext& testCtx,
+ tcu::TestNodeType type,
+ const std::string& name,
+ const std::string& desc,
+ typename FunctionPrograms1<Arg0>::Function initPrograms,
+ typename FunctionInstance1<Arg0>::Function testFunction,
+ Arg0 arg0)
+{
+ return new InstanceFactory1<FunctionInstance1<Arg0>, typename FunctionInstance1<Arg0>::Args, FunctionPrograms1<Arg0> >(
+ testCtx, type, name, desc, FunctionPrograms1<Arg0>(initPrograms), typename FunctionInstance1<Arg0>::Args(testFunction, arg0));
+}
+
+// addFunctionCase
+
+inline void addFunctionCase (tcu::TestCaseGroup* group,
+ const std::string& name,
+ const std::string& desc,
+ FunctionInstance0::Function testFunc)
+{
+ group->addChild(createFunctionCase(group->getTestContext(), tcu::NODETYPE_SELF_VALIDATE, name, desc, testFunc));
+}
+
+inline void addFunctionCaseWithPrograms (tcu::TestCaseGroup* group,
+ const std::string& name,
+ const std::string& desc,
+ FunctionPrograms0::Function initPrograms,
+ FunctionInstance0::Function testFunc)
+{
+ group->addChild(createFunctionCaseWithPrograms(group->getTestContext(), tcu::NODETYPE_SELF_VALIDATE, name, desc, initPrograms, testFunc));
+}
+
+template<typename Arg0>
+void addFunctionCase (tcu::TestCaseGroup* group,
+ const std::string& name,
+ const std::string& desc,
+ typename FunctionInstance1<Arg0>::Function testFunc,
+ Arg0 arg0)
+{
+ group->addChild(createFunctionCase<Arg0>(group->getTestContext(), tcu::NODETYPE_SELF_VALIDATE, name, desc, testFunc, arg0));
+}
+
+template<typename Arg0>
+void addFunctionCase (tcu::TestCaseGroup* group,
+ tcu::TestNodeType type,
+ const std::string& name,
+ const std::string& desc,
+ typename FunctionInstance1<Arg0>::Function testFunc,
+ Arg0 arg0)
+{
+ group->addChild(createFunctionCase<Arg0>(group->getTestContext(), type, name, desc, testFunc, arg0));
+}
+
+template<typename Arg0>
+void addFunctionCaseWithPrograms (tcu::TestCaseGroup* group,
+ const std::string& name,
+ const std::string& desc,
+ typename FunctionPrograms1<Arg0>::Function initPrograms,
+ typename FunctionInstance1<Arg0>::Function testFunc,
+ Arg0 arg0)
+{
+ group->addChild(createFunctionCaseWithPrograms<Arg0>(group->getTestContext(), tcu::NODETYPE_SELF_VALIDATE, name, desc, initPrograms, testFunc, arg0));
+}
+
+template<typename Arg0>
+void addFunctionCaseWithPrograms (tcu::TestCaseGroup* group,
+ tcu::TestNodeType type,
+ const std::string& name,
+ const std::string& desc,
+ typename FunctionPrograms1<Arg0>::Function initPrograms,
+ typename FunctionInstance1<Arg0>::Function testFunc,
+ Arg0 arg0)
+{
+ group->addChild(createFunctionCaseWithPrograms<Arg0>(group->getTestContext(), type, name, desc, initPrograms, testFunc, arg0));
+}
+
+} // vkt
+
+#endif // _VKTTESTCASEUTIL_HPP
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Vulkan Test Package
+ *//*--------------------------------------------------------------------*/
+
+#include "vktTestPackage.hpp"
+
+#include "tcuPlatform.hpp"
+#include "tcuTestCase.hpp"
+#include "tcuTestLog.hpp"
+
+#include "vkPlatform.hpp"
+#include "vkPrograms.hpp"
+#include "vkBinaryRegistry.hpp"
+#include "vkGlslToSpirV.hpp"
+#include "vkSpirVAsm.hpp"
+
+#include "deUniquePtr.hpp"
+
+#include "vktInfo.hpp"
+#include "vktApiTests.hpp"
+#include "vktPipelineTests.hpp"
+#include "vktBindingModelTests.hpp"
+#include "vktSpvAsmTests.hpp"
+#include "vktShaderLibrary.hpp"
+#include "vktRenderPassTests.hpp"
+#include "vktMemoryTests.hpp"
+#include "vktShaderRenderDiscardTests.hpp"
+
+#include <vector>
+#include <sstream>
+
+namespace // compilation
+{
+
+vk::ProgramBinary* compileProgram (const glu::ProgramSources& source, glu::ShaderProgramInfo* buildInfo)
+{
+ return vk::buildProgram(source, vk::PROGRAM_FORMAT_SPIRV, buildInfo);
+}
+
+vk::ProgramBinary* compileProgram (const vk::SpirVAsmSource& source, vk::SpirVProgramInfo* buildInfo)
+{
+ return vk::assembleProgram(source, buildInfo);
+}
+
+template <typename InfoType, typename IteratorType>
+vk::ProgramBinary* buildProgram (const std::string& casePath,
+ IteratorType iter,
+ const vk::BinaryRegistryReader& prebuiltBinRegistry,
+ tcu::TestLog& log,
+ vk::BinaryCollection* progCollection)
+{
+ const vk::ProgramIdentifier progId (casePath, iter.getName());
+ const tcu::ScopedLogSection progSection (log, iter.getName(), "Program: " + iter.getName());
+ de::MovePtr<vk::ProgramBinary> binProg;
+ InfoType buildInfo;
+
+ try
+ {
+ binProg = de::MovePtr<vk::ProgramBinary>(compileProgram(iter.getProgram(), &buildInfo));
+ log << buildInfo;
+ }
+ catch (const tcu::NotSupportedError& err)
+ {
+ // Try to load from cache
+ log << err << tcu::TestLog::Message << "Building from source not supported, loading stored binary instead" << tcu::TestLog::EndMessage;
+
+ binProg = de::MovePtr<vk::ProgramBinary>(prebuiltBinRegistry.loadProgram(progId));
+
+ log << iter.getProgram();
+ }
+ catch (const tcu::Exception&)
+ {
+ // Build failed for other reason
+ log << buildInfo;
+ throw;
+ }
+
+ TCU_CHECK_INTERNAL(binProg);
+
+ {
+ vk::ProgramBinary* const returnBinary = binProg.get();
+
+ progCollection->add(progId.programName, binProg);
+
+ return returnBinary;
+ }
+}
+
+} // anonymous(compilation)
+
+namespace vkt
+{
+
+using std::vector;
+using de::UniquePtr;
+using de::MovePtr;
+using tcu::TestLog;
+
+// TestCaseExecutor
+
+class TestCaseExecutor : public tcu::TestCaseExecutor
+{
+public:
+ TestCaseExecutor (tcu::TestContext& testCtx);
+ ~TestCaseExecutor (void);
+
+ virtual void init (tcu::TestCase* testCase, const std::string& path);
+ virtual void deinit (tcu::TestCase* testCase);
+
+ virtual tcu::TestNode::IterateResult iterate (tcu::TestCase* testCase);
+
+private:
+ vk::BinaryCollection m_progCollection;
+ vk::BinaryRegistryReader m_prebuiltBinRegistry;
+
+ de::UniquePtr<vk::Library> m_library;
+ Context m_context;
+
+ TestInstance* m_instance; //!< Current test case instance
+};
+
+static MovePtr<vk::Library> createLibrary (tcu::TestContext& testCtx)
+{
+ return MovePtr<vk::Library>(testCtx.getPlatform().getVulkanPlatform().createLibrary());
+}
+
+TestCaseExecutor::TestCaseExecutor (tcu::TestContext& testCtx)
+ : m_prebuiltBinRegistry (testCtx.getArchive(), "vulkan/prebuilt")
+ , m_library (createLibrary(testCtx))
+ , m_context (testCtx, m_library->getPlatformInterface(), m_progCollection)
+ , m_instance (DE_NULL)
+{
+}
+
+TestCaseExecutor::~TestCaseExecutor (void)
+{
+ delete m_instance;
+}
+
+void TestCaseExecutor::init (tcu::TestCase* testCase, const std::string& casePath)
+{
+ const TestCase* vktCase = dynamic_cast<TestCase*>(testCase);
+ tcu::TestLog& log = m_context.getTestContext().getLog();
+ vk::SourceCollections sourceProgs;
+
+ DE_UNREF(casePath); // \todo [2015-03-13 pyry] Use this to identify ProgramCollection storage path
+
+ if (!vktCase)
+ TCU_THROW(InternalError, "Test node not an instance of vkt::TestCase");
+
+ m_progCollection.clear();
+ vktCase->initPrograms(sourceProgs);
+
+ for (vk::GlslSourceCollection::Iterator progIter = sourceProgs.glslSources.begin(); progIter != sourceProgs.glslSources.end(); ++progIter)
+ {
+ vk::ProgramBinary* binProg = buildProgram<glu::ShaderProgramInfo, vk::GlslSourceCollection::Iterator>(casePath, progIter, m_prebuiltBinRegistry, log, &m_progCollection);
+
+ try
+ {
+ std::ostringstream disasm;
+
+ vk::disassembleSpirV(binProg->getSize(), binProg->getBinary(), &disasm);
+
+ log << TestLog::KernelSource(disasm.str());
+ }
+ catch (const tcu::NotSupportedError& err)
+ {
+ log << err;
+ }
+ }
+
+ for (vk::SpirVAsmCollection::Iterator asmIterator = sourceProgs.spirvAsmSources.begin(); asmIterator != sourceProgs.spirvAsmSources.end(); ++asmIterator)
+ {
+ buildProgram<vk::SpirVProgramInfo, vk::SpirVAsmCollection::Iterator>(casePath, asmIterator, m_prebuiltBinRegistry, log, &m_progCollection);
+ }
+
+ DE_ASSERT(!m_instance);
+ m_instance = vktCase->createInstance(m_context);
+}
+
+void TestCaseExecutor::deinit (tcu::TestCase*)
+{
+ delete m_instance;
+ m_instance = DE_NULL;
+}
+
+tcu::TestNode::IterateResult TestCaseExecutor::iterate (tcu::TestCase*)
+{
+ DE_ASSERT(m_instance);
+
+ const tcu::TestStatus result = m_instance->iterate();
+
+ if (result.isComplete())
+ {
+ // Vulkan tests shouldn't set result directly
+ DE_ASSERT(m_context.getTestContext().getTestResult() == QP_TEST_RESULT_LAST);
+ m_context.getTestContext().setTestResult(result.getCode(), result.getDescription().c_str());
+ return tcu::TestNode::STOP;
+ }
+ else
+ return tcu::TestNode::CONTINUE;
+}
+
+// GLSL shader tests
+
+tcu::TestCaseGroup* createGlslTests (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> glslTests (new tcu::TestCaseGroup(testCtx, "glsl", "GLSL shader execution tests"));
+
+ // ShaderLibrary-based tests
+ static const struct
+ {
+ const char* name;
+ const char* description;
+ } s_es310Tests[] =
+ {
+ { "arrays", "Arrays" },
+ { "conditionals", "Conditional statements" },
+ { "constant_expressions", "Constant expressions" },
+ { "constants", "Constants" },
+ { "conversions", "Type conversions" },
+ { "functions", "Functions" },
+ { "linkage", "Linking" },
+ { "scoping", "Scoping" },
+ { "swizzles", "Swizzles" },
+ };
+
+ for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_es310Tests); ndx++)
+ glslTests->addChild(createShaderLibraryGroup(testCtx,
+ s_es310Tests[ndx].name,
+ s_es310Tests[ndx].description,
+ std::string("vulkan/glsl/es310/") + s_es310Tests[ndx].name + ".test").release());
+
+ // ShaderRenderCase-based tests
+ glslTests->addChild(sr::createDiscardTests(testCtx));
+
+ return glslTests.release();
+}
+
+// TestPackage
+
+TestPackage::TestPackage (tcu::TestContext& testCtx)
+ : tcu::TestPackage(testCtx, "dEQP-VK", "dEQP Vulkan Tests")
+{
+}
+
+TestPackage::~TestPackage (void)
+{
+}
+
+tcu::TestCaseExecutor* TestPackage::createExecutor (void) const
+{
+ return new TestCaseExecutor(m_testCtx);
+}
+
+void TestPackage::init (void)
+{
+ addChild(createInfoTests (m_testCtx));
+ addChild(api::createTests (m_testCtx));
+ addChild(pipeline::createTests (m_testCtx));
+ addChild(BindingModel::createTests (m_testCtx));
+ addChild(SpirVAssembly::createTests (m_testCtx));
+ addChild(createGlslTests (m_testCtx));
+ addChild(createRenderPassTests (m_testCtx));
+ addChild(memory::createTests (m_testCtx));
+}
+
+} // vkt
--- /dev/null
+#ifndef _VKTTESTPACKAGE_HPP
+#define _VKTTESTPACKAGE_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Vulkan Test Package
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestPackage.hpp"
+#include "tcuResource.hpp"
+#include "vktTestCase.hpp"
+
+namespace vkt
+{
+
+class TestPackage : public tcu::TestPackage
+{
+public:
+ TestPackage (tcu::TestContext& testCtx);
+ virtual ~TestPackage (void);
+
+ virtual void init (void);
+ tcu::TestCaseExecutor* createExecutor (void) const;
+};
+
+} // vkt
+
+#endif // _VKTTESTPACKAGE_HPP
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Vulkan Test Package Entry Point.
+ *//*--------------------------------------------------------------------*/
+
+#include "vktTestPackage.hpp"
+
+// Register package to test executor.
+
+static tcu::TestPackage* createTestPackage (tcu::TestContext& testCtx)
+{
+ return new vkt::TestPackage(testCtx);
+}
+
+tcu::TestPackageDescriptor g_vktPackageDescriptor("dEQP-VK", createTestPackage);
--- /dev/null
+add_subdirectory(vulkan)
DE_DECLARE_COMMAND_LINE_OPT(EGLPixmapType, std::string);
DE_DECLARE_COMMAND_LINE_OPT(LogImages, bool);
DE_DECLARE_COMMAND_LINE_OPT(TestOOM, bool);
+DE_DECLARE_COMMAND_LINE_OPT(VKDeviceID, int);
static void parseIntList (const char* src, std::vector<int>* dst)
{
<< Option<EGLDisplayType> (DE_NULL, "deqp-egl-display-type", "EGL native display type")
<< Option<EGLWindowType> (DE_NULL, "deqp-egl-window-type", "EGL native window type")
<< Option<EGLPixmapType> (DE_NULL, "deqp-egl-pixmap-type", "EGL native pixmap type")
+ << Option<VKDeviceID> (DE_NULL, "deqp-vk-device-id", "Vulkan device ID (IDs start from 1)", "1")
<< Option<LogImages> (DE_NULL, "deqp-log-images", "Enable or disable logging of result images", s_enableNames, "enable")
<< Option<TestOOM> (DE_NULL, "deqp-test-oom", "Run tests that exhaust memory on purpose", s_enableNames, TEST_OOM_DEFAULT);
}
return isOk;
}
-const char* CommandLine::getLogFileName (void) const { return m_cmdLine.getOption<opt::LogFilename>().c_str(); }
-deUint32 CommandLine::getLogFlags (void) const { return m_logFlags; }
-RunMode CommandLine::getRunMode (void) const { return m_cmdLine.getOption<opt::RunMode>(); }
-const char* CommandLine::getCaseListExportFile (void) const { return m_cmdLine.getOption<opt::ExportFilenamePattern>().c_str();}
-WindowVisibility CommandLine::getVisibility (void) const { return m_cmdLine.getOption<opt::Visibility>(); }
-bool CommandLine::isWatchDogEnabled (void) const { return m_cmdLine.getOption<opt::WatchDog>(); }
-bool CommandLine::isCrashHandlingEnabled (void) const { return m_cmdLine.getOption<opt::CrashHandler>(); }
-int CommandLine::getBaseSeed (void) const { return m_cmdLine.getOption<opt::BaseSeed>(); }
-int CommandLine::getTestIterationCount (void) const { return m_cmdLine.getOption<opt::TestIterationCount>(); }
-int CommandLine::getSurfaceWidth (void) const { return m_cmdLine.getOption<opt::SurfaceWidth>(); }
-int CommandLine::getSurfaceHeight (void) const { return m_cmdLine.getOption<opt::SurfaceHeight>(); }
-SurfaceType CommandLine::getSurfaceType (void) const { return m_cmdLine.getOption<opt::SurfaceType>(); }
-ScreenRotation CommandLine::getScreenRotation (void) const { return m_cmdLine.getOption<opt::ScreenRotation>(); }
-int CommandLine::getGLConfigId (void) const { return m_cmdLine.getOption<opt::GLConfigID>(); }
-int CommandLine::getCLPlatformId (void) const { return m_cmdLine.getOption<opt::CLPlatformID>(); }
-const std::vector<int>& CommandLine::getCLDeviceIds (void) const { return m_cmdLine.getOption<opt::CLDeviceIDs>(); }
-bool CommandLine::isOutOfMemoryTestEnabled (void) const { return m_cmdLine.getOption<opt::TestOOM>(); }
+const char* CommandLine::getLogFileName (void) const { return m_cmdLine.getOption<opt::LogFilename>().c_str(); }
+deUint32 CommandLine::getLogFlags (void) const { return m_logFlags; }
+RunMode CommandLine::getRunMode (void) const { return m_cmdLine.getOption<opt::RunMode>(); }
+const char* CommandLine::getCaseListExportFile (void) const { return m_cmdLine.getOption<opt::ExportFilenamePattern>().c_str(); }
+WindowVisibility CommandLine::getVisibility (void) const { return m_cmdLine.getOption<opt::Visibility>(); }
+bool CommandLine::isWatchDogEnabled (void) const { return m_cmdLine.getOption<opt::WatchDog>(); }
+bool CommandLine::isCrashHandlingEnabled (void) const { return m_cmdLine.getOption<opt::CrashHandler>(); }
+int CommandLine::getBaseSeed (void) const { return m_cmdLine.getOption<opt::BaseSeed>(); }
+int CommandLine::getTestIterationCount (void) const { return m_cmdLine.getOption<opt::TestIterationCount>(); }
+int CommandLine::getSurfaceWidth (void) const { return m_cmdLine.getOption<opt::SurfaceWidth>(); }
+int CommandLine::getSurfaceHeight (void) const { return m_cmdLine.getOption<opt::SurfaceHeight>(); }
+SurfaceType CommandLine::getSurfaceType (void) const { return m_cmdLine.getOption<opt::SurfaceType>(); }
+ScreenRotation CommandLine::getScreenRotation (void) const { return m_cmdLine.getOption<opt::ScreenRotation>(); }
+int CommandLine::getGLConfigId (void) const { return m_cmdLine.getOption<opt::GLConfigID>(); }
+int CommandLine::getCLPlatformId (void) const { return m_cmdLine.getOption<opt::CLPlatformID>(); }
+const std::vector<int>& CommandLine::getCLDeviceIds (void) const { return m_cmdLine.getOption<opt::CLDeviceIDs>(); }
+int CommandLine::getVKDeviceId (void) const { return m_cmdLine.getOption<opt::VKDeviceID>(); }
+bool CommandLine::isOutOfMemoryTestEnabled (void) const { return m_cmdLine.getOption<opt::TestOOM>(); }
const char* CommandLine::getGLContextType (void) const
{
//! Get EGL native pixmap factory (--deqp-egl-pixmap-type)
const char* getEGLPixmapType (void) const;
+ //! Get Vulkan device ID (--deqp-vk-device-id)
+ int getVKDeviceId (void) const;
+
//! Should we run tests that exhaust memory (--deqp-test-oom)
bool isOutOfMemoryTestEnabled(void) const;
const glu::Platform& Platform::getGLPlatform (void) const
{
- throw tcu::NotSupportedError("OpenGL (ES) is not supported", DE_NULL, __FILE__, __LINE__);
+ TCU_THROW(NotSupportedError, "OpenGL (ES) is not supported");
}
const eglu::Platform& Platform::getEGLPlatform (void) const
{
- throw tcu::NotSupportedError("EGL is not supported", DE_NULL, __FILE__, __LINE__);
+ TCU_THROW(NotSupportedError, "EGL is not supported");
+}
+
+const vk::Platform& Platform::getVulkanPlatform (void) const
+{
+ TCU_THROW(NotSupportedError, "Vulkan is not supported");
}
} // tcu
class Platform;
}
+namespace vk
+{
+class Platform;
+}
+
namespace tcu
{
* \return Reference to EGL platform interface.
*//*--------------------------------------------------------------------*/
virtual const eglu::Platform& getEGLPlatform (void) const;
+
+ virtual const vk::Platform& getVulkanPlatform (void) const;
};
} // tcu
return 0;
}
}
-
} // TexVerifierUtil
} // tcu
QueryPerformanceFrequency(&freq);
DE_ASSERT(freq.LowPart != 0 || freq.HighPart != 0);
/* \todo [2010-03-26 kalle] consider adding a 32bit-friendly implementation */
- DE_ASSERT(freq.QuadPart >= 1000000);
- return count.QuadPart / (freq.QuadPart / 1000000);
+
+ if (count.QuadPart < MAXLONGLONG / 1000000)
+ {
+ DE_ASSERT(freq.QuadPart != 0);
+ return count.QuadPart * 1000000 / freq.QuadPart;
+ }
+ else
+ {
+ DE_ASSERT(freq.QuadPart >= 1000000);
+ return count.QuadPart / (freq.QuadPart / 1000000);
+ }
#elif (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_ANDROID)
struct timespec currTime;
endif ()
add_library(tcutil-platform STATIC ${TCUTIL_PLATFORM_SRCS})
+
+# Add vkutil to the deps before tcutil so that it picks up the c++11 dependencies
+target_link_libraries(tcutil-platform vkutil)
+
target_link_libraries(tcutil-platform tcutil ${TCUTIL_PLATFORM_LIBS})
# Always link to glutil as some platforms such as Win32 always support GL
#include "deUniquePtr.hpp"
#include "gluPlatform.hpp"
+#include "vkPlatform.hpp"
#include "tcuX11.hpp"
+#include "tcuFunctionLibrary.hpp"
#if defined (DEQP_SUPPORT_GLX)
# include "tcuX11GlxPlatform.hpp"
}
};
+class VulkanLibrary : public vk::Library
+{
+public:
+ VulkanLibrary (void)
+ : m_library ("libvulkan.so")
+ , m_driver (m_library)
+ {
+ }
+
+ const vk::PlatformInterface& getPlatformInterface (void) const
+ {
+ return m_driver;
+ }
+
+private:
+ const tcu::DynamicFunctionLibrary m_library;
+ const vk::PlatformDriver m_driver;
+};
+
+class X11VulkanPlatform : public vk::Platform
+{
+public:
+ vk::Library* createLibrary (void) const
+ {
+ return new VulkanLibrary();
+ }
+};
+
class X11Platform : public tcu::Platform
{
public:
- X11Platform (void);
- bool processEvents (void) { return !m_eventState.getQuitFlag(); }
- const glu::Platform& getGLPlatform (void) const { return m_glPlatform; }
+ X11Platform (void);
+ bool processEvents (void) { return !m_eventState.getQuitFlag(); }
+ const glu::Platform& getGLPlatform (void) const { return m_glPlatform; }
#if defined (DEQP_SUPPORT_EGL)
- const eglu::Platform& getEGLPlatform (void) const { return m_eglPlatform; }
+ const eglu::Platform& getEGLPlatform (void) const { return m_eglPlatform; }
#endif // DEQP_SUPPORT_EGL
+ const vk::Platform& getVulkanPlatform (void) const { return m_vkPlatform; }
+
private:
EventState m_eventState;
#if defined (DEQP_SUPPORT_EGL)
x11::egl::Platform m_eglPlatform;
#endif // DEQP_SPPORT_EGL
X11GLPlatform m_glPlatform;
+ X11VulkanPlatform m_vkPlatform;
};
X11Platform::X11Platform (void)
#include "egluUtil.hpp"
#include "eglwLibrary.hpp"
#include "eglwEnums.hpp"
+#include "tcuFunctionLibrary.hpp"
// Assume no call translation is needed
#include <android/native_window.h>
return new NativeDisplay();
}
+// Vulkan
+
+class VulkanLibrary : public vk::Library
+{
+public:
+ VulkanLibrary (void)
+ : m_library ("libvulkan.so")
+ , m_driver (m_library)
+ {
+ }
+
+ const vk::PlatformInterface& getPlatformInterface (void) const
+ {
+ return m_driver;
+ }
+
+private:
+ const tcu::DynamicFunctionLibrary m_library;
+ const vk::PlatformDriver m_driver;
+};
+
// Platform
Platform::Platform (void)
return true;
}
+vk::Library* Platform::createLibrary (void) const
+{
+ return new VulkanLibrary();
+}
+
} // Android
} // tcu
#include "tcuPlatform.hpp"
#include "egluPlatform.hpp"
#include "gluPlatform.hpp"
+#include "vkPlatform.hpp"
#include "tcuAndroidWindow.hpp"
namespace tcu
namespace Android
{
-class Platform : public tcu::Platform, private eglu::Platform, private glu::Platform
+class Platform : public tcu::Platform, private eglu::Platform, private glu::Platform, private vk::Platform
{
public:
Platform (void);
virtual const glu::Platform& getGLPlatform (void) const { return static_cast<const glu::Platform&>(*this); }
virtual const eglu::Platform& getEGLPlatform (void) const { return static_cast<const eglu::Platform&>(*this); }
+ virtual const vk::Platform& getVulkanPlatform (void) const { return static_cast<const vk::Platform&>(*this); }
WindowRegistry& getWindowRegistry (void) { return m_windowRegistry; }
+ vk::Library* createLibrary (void) const;
+
private:
WindowRegistry m_windowRegistry;
};
#include "tcuNullRenderContext.hpp"
#include "egluNativeDisplay.hpp"
#include "eglwLibrary.hpp"
+#include "vkNullDriver.hpp"
namespace tcu
{
{
}
+vk::Library* Platform::createLibrary (void) const
+{
+ return vk::createNullDriver();
+}
+
} // null
} // tcu
#include "tcuPlatform.hpp"
#include "gluPlatform.hpp"
#include "egluPlatform.hpp"
+#include "vkPlatform.hpp"
namespace tcu
{
namespace null
{
-class Platform : public tcu::Platform, private glu::Platform, private eglu::Platform
+class Platform : public tcu::Platform, private glu::Platform, private eglu::Platform, private vk::Platform
{
public:
- Platform (void);
- virtual ~Platform (void);
+ Platform (void);
+ virtual ~Platform (void);
+
+ virtual const glu::Platform& getGLPlatform (void) const { return static_cast<const glu::Platform&>(*this); }
+ virtual const eglu::Platform& getEGLPlatform (void) const { return static_cast<const eglu::Platform&>(*this); }
+ virtual const vk::Platform& getVulkanPlatform (void) const { return static_cast<const vk::Platform&>(*this); }
+
+private:
+ virtual vk::Library* createLibrary (void) const;
- virtual const glu::Platform& getGLPlatform (void) const { return static_cast<const glu::Platform&>(*this); }
- virtual const eglu::Platform& getEGLPlatform (void) const { return static_cast<const eglu::Platform&>(*this); }
};
} // null
#include "tcuWin32Platform.hpp"
#include "tcuWGLContextFactory.hpp"
+#include "tcuFunctionLibrary.hpp"
#if defined(DEQP_SUPPORT_EGL)
# include "tcuWin32EGLNativeDisplayFactory.hpp"
namespace tcu
{
+class VulkanLibrary : public vk::Library
+{
+public:
+ VulkanLibrary (void)
+ : m_library ("vulkan-0.dll")
+ , m_driver (m_library)
+ {
+ }
+
+ const vk::PlatformInterface& getPlatformInterface (void) const
+ {
+ return m_driver;
+ }
+
+private:
+ const tcu::DynamicFunctionLibrary m_library;
+ const vk::PlatformDriver m_driver;
+};
+
Win32Platform::Win32Platform (void)
: m_instance(GetModuleHandle(NULL))
{
return true;
}
+vk::Library* Win32Platform::createLibrary (void) const
+{
+ return new VulkanLibrary();
+}
+
} // tcu
// Create platform
#include "tcuDefs.hpp"
#include "tcuPlatform.hpp"
#include "gluPlatform.hpp"
+#include "vkPlatform.hpp"
#include "tcuWin32API.h"
#if defined(DEQP_SUPPORT_EGL)
namespace tcu
{
-class Win32Platform : public tcu::Platform, private glu::Platform
+class Win32Platform : public tcu::Platform, private glu::Platform, private vk::Platform
#if defined(DEQP_SUPPORT_EGL)
, private eglu::Platform
#endif
const eglu::Platform& getEGLPlatform (void) const { return static_cast<const eglu::Platform&>(*this); }
#endif
+ const vk::Platform& getVulkanPlatform (void) const { return static_cast<const vk::Platform&>(*this); }
+
private:
+ vk::Library* createLibrary (void) const;
+
HINSTANCE m_instance;
};
#include "rrFragmentOperations.hpp"
#include "tcuVectorUtil.hpp"
#include "tcuTextureUtil.hpp"
+#include <limits>
using tcu::IVec2;
using tcu::Vec3;
void FragmentProcessor::executeBlendFactorComputeRGB (const Vec4& blendColor, const BlendState& blendRGBState)
{
-#define SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, FACTOR_EXPRESSION) \
- for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++) \
- { \
- if (m_sampleRegister[regSampleNdx].isAlive) \
- { \
- const Vec4& src = m_sampleRegister[regSampleNdx].clampedBlendSrcColor; \
- const Vec4& src1 = m_sampleRegister[regSampleNdx].clampedBlendSrc1Color; \
- const Vec4& dst = m_sampleRegister[regSampleNdx].clampedBlendDstColor; \
- DE_UNREF(src); \
- DE_UNREF(src1); \
- DE_UNREF(dst); \
- \
- m_sampleRegister[regSampleNdx].FACTOR_NAME = clamp((FACTOR_EXPRESSION), Vec3(0.0f), Vec3(1.0f)); \
- } \
+#define SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, FACTOR_EXPRESSION) \
+ for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++) \
+ { \
+ if (m_sampleRegister[regSampleNdx].isAlive) \
+ { \
+ const Vec4& src = m_sampleRegister[regSampleNdx].clampedBlendSrcColor; \
+ const Vec4& src1 = m_sampleRegister[regSampleNdx].clampedBlendSrc1Color; \
+ const Vec4& dst = m_sampleRegister[regSampleNdx].clampedBlendDstColor; \
+ DE_UNREF(src); \
+ DE_UNREF(src1); \
+ DE_UNREF(dst); \
+ \
+ m_sampleRegister[regSampleNdx].FACTOR_NAME = (FACTOR_EXPRESSION); \
+ } \
}
#define SWITCH_SRC_OR_DST_FACTOR_RGB(FUNC_NAME, FACTOR_NAME) \
void FragmentProcessor::executeBlendFactorComputeA (const Vec4& blendColor, const BlendState& blendAState)
{
-#define SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, FACTOR_EXPRESSION) \
- for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++) \
- { \
- if (m_sampleRegister[regSampleNdx].isAlive) \
- { \
- const Vec4& src = m_sampleRegister[regSampleNdx].clampedBlendSrcColor; \
- const Vec4& src1 = m_sampleRegister[regSampleNdx].clampedBlendSrc1Color; \
- const Vec4& dst = m_sampleRegister[regSampleNdx].clampedBlendDstColor; \
- DE_UNREF(src); \
- DE_UNREF(src1); \
- DE_UNREF(dst); \
- \
- m_sampleRegister[regSampleNdx].FACTOR_NAME = clamp((FACTOR_EXPRESSION), 0.0f, 1.0f); \
- } \
+#define SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, FACTOR_EXPRESSION) \
+ for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++) \
+ { \
+ if (m_sampleRegister[regSampleNdx].isAlive) \
+ { \
+ const Vec4& src = m_sampleRegister[regSampleNdx].clampedBlendSrcColor; \
+ const Vec4& src1 = m_sampleRegister[regSampleNdx].clampedBlendSrc1Color; \
+ const Vec4& dst = m_sampleRegister[regSampleNdx].clampedBlendDstColor; \
+ DE_UNREF(src); \
+ DE_UNREF(src1); \
+ DE_UNREF(dst); \
+ \
+ m_sampleRegister[regSampleNdx].FACTOR_NAME = (FACTOR_EXPRESSION); \
+ } \
}
#define SWITCH_SRC_OR_DST_FACTOR_A(FUNC_NAME, FACTOR_NAME) \
switch (fragmentDataType)
{
case rr::GENERICVECTYPE_FLOAT:
+ {
+ // Select min/max clamping values for blending factors and operands
+ Vec4 minClampValue;
+ Vec4 maxClampValue;
+
+ if (colorbufferClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT)
+ {
+ minClampValue = Vec4(0.0f);
+ maxClampValue = Vec4(1.0f);
+ }
+ else if (colorbufferClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT)
+ {
+ minClampValue = Vec4(-1.0f);
+ maxClampValue = Vec4(1.0f);
+ }
+ else
+ {
+ // No clamping
+ minClampValue = Vec4(-std::numeric_limits<float>::infinity());
+ maxClampValue = Vec4(std::numeric_limits<float>::infinity());
+ }
+
// Blend calculation - only if using blend.
if (state.blendMode == BLENDMODE_STANDARD)
{
const Fragment& frag = inputFragments[groupFirstFragNdx + regSampleNdx/numSamplesPerFragment];
Vec4 dstColor = colorBuffer.getPixel(fragSampleNdx, frag.pixelCoord.x(), frag.pixelCoord.y());
- m_sampleRegister[regSampleNdx].clampedBlendSrcColor = clamp(frag.value.get<float>(), Vec4(0.0f), Vec4(1.0f));
- m_sampleRegister[regSampleNdx].clampedBlendSrc1Color = clamp(frag.value1.get<float>(), Vec4(0.0f), Vec4(1.0f));
- m_sampleRegister[regSampleNdx].clampedBlendDstColor = clamp(sRGBTarget ? tcu::sRGBToLinear(dstColor) : dstColor, Vec4(0.0f), Vec4(1.0f));
+ m_sampleRegister[regSampleNdx].clampedBlendSrcColor = clamp(frag.value.get<float>(), minClampValue, maxClampValue);
+ m_sampleRegister[regSampleNdx].clampedBlendSrc1Color = clamp(frag.value1.get<float>(), minClampValue, maxClampValue);
+ m_sampleRegister[regSampleNdx].clampedBlendDstColor = clamp(sRGBTarget ? tcu::sRGBToLinear(dstColor) : dstColor, minClampValue, maxClampValue);
}
}
const Vec4 srcColor = frag.value.get<float>();
const Vec4 dstColor = colorBuffer.getPixel(fragSampleNdx, frag.pixelCoord.x(), frag.pixelCoord.y());
- m_sampleRegister[regSampleNdx].clampedBlendSrcColor = unpremultiply(clamp(srcColor, Vec4(0.0f), Vec4(1.0f)));
- m_sampleRegister[regSampleNdx].clampedBlendDstColor = unpremultiply(clamp(sRGBTarget ? tcu::sRGBToLinear(dstColor) : dstColor, Vec4(0.0f), Vec4(1.0f)));
+ m_sampleRegister[regSampleNdx].clampedBlendSrcColor = unpremultiply(clamp(srcColor, minClampValue, maxClampValue));
+ m_sampleRegister[regSampleNdx].clampedBlendDstColor = unpremultiply(clamp(sRGBTarget ? tcu::sRGBToLinear(dstColor) : dstColor, minClampValue, maxClampValue));
}
}
}
}
+ // Clamp result values in sample register
+ if (colorbufferClass != tcu::TEXTURECHANNELCLASS_FLOATING_POINT)
+ {
+ for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++)
+ {
+ if (m_sampleRegister[regSampleNdx].isAlive)
+ {
+ m_sampleRegister[regSampleNdx].blendedRGB = clamp(m_sampleRegister[regSampleNdx].blendedRGB, minClampValue.swizzle(0, 1, 2), maxClampValue.swizzle(0, 1, 2));
+ m_sampleRegister[regSampleNdx].blendedA = clamp(m_sampleRegister[regSampleNdx].blendedA, minClampValue.w(), maxClampValue.w());
+ }
+ }
+ }
+
// Finally, write the colors to the color buffer.
if (state.colorMask[0] && state.colorMask[1] && state.colorMask[2] && state.colorMask[3])
else if (state.colorMask[0] || state.colorMask[1] || state.colorMask[2] || state.colorMask[3])
executeMaskedColorWrite(groupFirstFragNdx, numSamplesPerFragment, inputFragments, colorMaskFactor, colorMaskNegationFactor, sRGBTarget, colorBuffer);
break;
-
+ }
case rr::GENERICVECTYPE_INT32:
// Write fragments
for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++)
ditSRGB8ConversionTest.cpp
ditTextureFormatTests.cpp
ditTextureFormatTests.hpp
+ ditVulkanTests.cpp
+ ditVulkanTests.hpp
)
set(DE_INTERNAL_TESTS_LIBS
tcutil
referencerenderer
+ vkutil
)
add_deqp_module(de-internal-tests "${DE_INTERNAL_TESTS_SRCS}" "${DE_INTERNAL_TESTS_LIBS}" ditTestPackageEntry.cpp)
#include "ditFrameworkTests.hpp"
#include "ditTextureFormatTests.hpp"
+#include "ditVulkanTests.hpp"
+
#include "tcuFloatFormat.hpp"
#include "tcuEither.hpp"
#include "tcuTestLog.hpp"
addChild(new CaseListParserTests (m_testCtx));
addChild(new ReferenceRendererTests (m_testCtx));
addChild(createTextureFormatTests (m_testCtx));
+ addChild(createVulkanTests (m_testCtx));
}
} // dit
--- /dev/null
+/*-------------------------------------------------------------------------
+ * drawElements Internal Test Module
+ * ---------------------------------
+ *
+ * Copyright 2015 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 Vulkan framework tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "ditVulkanTests.hpp"
+#include "ditTestCase.hpp"
+
+#include "vkImageUtil.hpp"
+
+#include "deUniquePtr.hpp"
+
+namespace dit
+{
+
+tcu::TestCaseGroup* createVulkanTests (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "vulkan", "Vulkan Framework Tests"));
+
+ group->addChild(new SelfCheckCase(testCtx, "image_util", "ImageUtil self-check tests", vk::imageUtilSelfTest));
+
+ return group.release();
+}
+
+} // dit
--- /dev/null
+#ifndef _DITVULKANTESTS_HPP
+#define _DITVULKANTESTS_HPP
+/*-------------------------------------------------------------------------
+ * drawElements Internal Test Module
+ * ---------------------------------
+ *
+ * Copyright 2015 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 Vulkan framework tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace dit
+{
+
+tcu::TestCaseGroup* createVulkanTests (tcu::TestContext& testCtx);
+
+} // dit
+
+#endif // _DITVULKANTESTS_HPP
self.binName = binName
MODULES = [
- Module("dE-IT", "internal", "de-internal-tests"),
- Module("dEQP-EGL", "egl", "deqp-egl"),
- Module("dEQP-GLES2", "gles2", "deqp-gles2"),
- Module("dEQP-GLES3", "gles3", "deqp-gles3"),
- Module("dEQP-GLES31", "gles31", "deqp-gles31"),
+ Module("dE-IT", "internal", "de-internal-tests"),
+ Module("dEQP-EGL", "egl", "deqp-egl"),
+ Module("dEQP-GLES2", "gles2", "deqp-gles2"),
+ Module("dEQP-GLES3", "gles3", "deqp-gles3"),
+ Module("dEQP-GLES31", "gles31", "deqp-gles31"),
+ Module("dEQP-VK", "../external/vulkancts/modules/vulkan", "deqp-vk"),
]
DEFAULT_BUILD_DIR = os.path.join(tempfile.gettempdir(), "deqp-caselists", "{targetName}-{buildType}")