/*------------------------------------------------------------------------
 * Vulkan Conformance Tests
 * ------------------------
 *
 * Copyright (c) 2019 Valve Corporation.
 * Copyright (c) 2019 The Khronos Group Inc.
 *
 * 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 VK_EXT_blend_operation_advanced tests
 *//*--------------------------------------------------------------------*/

#include "vktPipelineBlendOperationAdvancedTests.hpp"
#include "vktPipelineImageUtil.hpp"
#include "vktPipelineReferenceRenderer.hpp"
#include "vktTestCaseUtil.hpp"
#include "vkCmdUtil.hpp"
#include "vkImageUtil.hpp"
#include "vkRefUtil.hpp"
#include "vkQueryUtil.hpp"
#include "vkTypeUtil.hpp"
#include "vkBuilderUtil.hpp"
#include "vkObjUtil.hpp"

#include "tcuTestLog.hpp"
#include "tcuImageCompare.hpp"
#include "tcuCommandLine.hpp"

namespace vkt
{
namespace pipeline
{

using namespace vk;

namespace
{
using tcu::Vec3;
using tcu::Vec4;

const deUint32 widthArea	= 32u;
const deUint32 heightArea	= 32u;

static const float A1 = 0.750f; // Between 1    and 0.5
static const float A2 = 0.375f; // Between 0.5  and 0.25
static const float A3 = 0.125f; // Between 0.25 and 0.0

const Vec4 srcColors[] = {
					   // Test that pre-multiplied is converted correctly.
					   // Should not test invalid premultiplied colours (1, 1, 1, 0).
					   { 1.000f, 0.750f, 0.500f, 1.00f },
					   { 0.250f, 0.125f, 0.000f, 1.00f },

					   // Test clamping.
					   { 1.000f, 0.750f, 0.500f, 1.00f },
					   { 0.250f, 0.125f, 0.000f, 1.00f },
					   { 1.000f, 0.750f, 0.500f, 1.00f },
					   { 0.250f, 0.125f, 0.000f, 1.00f },

					   // Combinations that test other branches of blend equations.
					   { 1.000f, 0.750f, 0.500f, 1.00f },
					   { 0.250f, 0.125f, 0.000f, 1.00f },
					   { 1.000f, 0.750f, 0.500f, 1.00f },
					   { 0.250f, 0.125f, 0.000f, 1.00f },
					   { 1.000f, 0.750f, 0.500f, 1.00f },
					   { 0.250f, 0.125f, 0.000f, 1.00f },
					   { 1.000f, 0.750f, 0.500f, 1.00f },
					   { 0.250f, 0.125f, 0.000f, 1.00f },
					   { 1.000f, 0.750f, 0.500f, 1.00f },
					   { 0.250f, 0.125f, 0.000f, 1.00f },

					   // Above block with few different pre-multiplied alpha values.
					   { 1.000f * A1, 0.750f * A1, 0.500f * A1, 1.00f * A1},
					   { 0.250f * A1, 0.125f * A1, 0.000f * A1, 1.00f * A1},
					   { 1.000f * A1, 0.750f * A1, 0.500f * A1, 1.00f * A1},
					   { 0.250f * A1, 0.125f * A1, 0.000f * A1, 1.00f * A1},
					   { 1.000f * A1, 0.750f * A1, 0.500f * A1, 1.00f * A1},
					   { 0.250f * A1, 0.125f * A1, 0.000f * A1, 1.00f * A1},
					   { 1.000f * A1, 0.750f * A1, 0.500f * A1, 1.00f * A1},
					   { 0.250f * A1, 0.125f * A1, 0.000f * A1, 1.00f * A1},
					   { 1.000f * A1, 0.750f * A1, 0.500f * A1, 1.00f * A1},
					   { 0.250f * A1, 0.125f * A1, 0.000f * A1, 1.00f * A1},

					   { 1.000f * A2, 0.750f * A2, 0.500f * A2, 1.00f * A2},
					   { 0.250f * A2, 0.125f * A2, 0.000f * A2, 1.00f * A2},
					   { 1.000f * A2, 0.750f * A2, 0.500f * A2, 1.00f * A2},
					   { 0.250f * A2, 0.125f * A2, 0.000f * A2, 1.00f * A2},
					   { 1.000f * A2, 0.750f * A2, 0.500f * A2, 1.00f * A2},
					   { 0.250f * A2, 0.125f * A2, 0.000f * A2, 1.00f * A2},
					   { 1.000f * A2, 0.750f * A2, 0.500f * A2, 1.00f * A2},
					   { 0.250f * A2, 0.125f * A2, 0.000f * A2, 1.00f * A2},
					   { 1.000f * A2, 0.750f * A2, 0.500f * A2, 1.00f * A2},
					   { 0.250f * A2, 0.125f * A2, 0.000f * A2, 1.00f * A2},

					   { 1.000f * A3, 0.750f * A3, 0.500f * A3, 1.00f * A3},
					   { 0.250f * A3, 0.125f * A3, 0.000f * A3, 1.00f * A3},
					   { 1.000f * A3, 0.750f * A3, 0.500f * A3, 1.00f * A3},
					   { 0.250f * A3, 0.125f * A3, 0.000f * A3, 1.00f * A3},
					   { 1.000f * A3, 0.750f * A3, 0.500f * A3, 1.00f * A3},
					   { 0.250f * A3, 0.125f * A3, 0.000f * A3, 1.00f * A3},
					   { 1.000f * A3, 0.750f * A3, 0.500f * A3, 1.00f * A3},
					   { 0.250f * A3, 0.125f * A3, 0.000f * A3, 1.00f * A3},
					   { 1.000f * A3, 0.750f * A3, 0.500f * A3, 1.00f * A3},
					   { 0.250f * A3, 0.125f * A3, 0.000f * A3, 1.00f * A3},

					   // Add some source colors with alpha component that is different than the respective destination color
					   { 0.750f, 0.750f, 0.500f, 0.750f },
					   { 0.250f, 0.500f, 0.500f, 0.750f },
					   { 0.250f, 0.125f, 0.000f, 0.500f },
					   { 0.250f, 0.250f, 0.500f, 0.500f },
					   { 0.250f, 0.125f, 0.000f, 0.250f },
					   { 0.125f, 0.125f, 0.125f, 0.250f }};

const Vec4 dstColors[] = {
					   // Test that pre-multiplied is converted correctly.
					   // Should not test invalid premultiplied colours (1, 1, 1, 0).
					   { 0.000f, 0.000f, 0.000f, 0.00f },
					   { 0.000f, 0.000f, 0.000f, 0.00f },

					   // Test clamping.
					   { -0.125f, -0.125f, -0.125f, 1.00f },
					   { -0.125f, -0.125f, -0.125f, 1.00f },
					   {  1.125f,  1.125f,  1.125f, 1.00f },
					   {  1.125f,  1.125f,  1.125f, 1.00f },

					   // Combinations that test other branches of blend equations.
					   { 1.000f, 1.000f, 1.000f, 1.00f },
					   { 1.000f, 1.000f, 1.000f, 1.00f },
					   { 0.500f, 0.500f, 0.500f, 1.00f },
					   { 0.500f, 0.500f, 0.500f, 1.00f },
					   { 0.250f, 0.250f, 0.250f, 1.00f },
					   { 0.250f, 0.250f, 0.250f, 1.00f },
					   { 0.125f, 0.125f, 0.125f, 1.00f },
					   { 0.125f, 0.125f, 0.125f, 1.00f },
					   { 0.000f, 0.000f, 0.000f, 1.00f },
					   { 0.000f, 0.000f, 0.000f, 1.00f },

					   // Above block with few different pre-multiplied alpha values.
					   { 1.000f * A1, 1.000f * A1, 1.000f * A1, 1.00f * A1},
					   { 1.000f * A1, 1.000f * A1, 1.000f * A1, 1.00f * A1},
					   { 0.500f * A1, 0.500f * A1, 0.500f * A1, 1.00f * A1},
					   { 0.500f * A1, 0.500f * A1, 0.500f * A1, 1.00f * A1},
					   { 0.250f * A1, 0.250f * A1, 0.250f * A1, 1.00f * A1},
					   { 0.250f * A1, 0.250f * A1, 0.250f * A1, 1.00f * A1},
					   { 0.125f * A1, 0.125f * A1, 0.125f * A1, 1.00f * A1},
					   { 0.125f * A1, 0.125f * A1, 0.125f * A1, 1.00f * A1},
					   { 0.000f * A1, 0.000f * A1, 0.000f * A1, 1.00f * A1},
					   { 0.000f * A1, 0.000f * A1, 0.000f * A1, 1.00f * A1},

					   { 1.000f * A2, 1.000f * A2, 1.000f * A2, 1.00f * A2},
					   { 1.000f * A2, 1.000f * A2, 1.000f * A2, 1.00f * A2},
					   { 0.500f * A2, 0.500f * A2, 0.500f * A2, 1.00f * A2},
					   { 0.500f * A2, 0.500f * A2, 0.500f * A2, 1.00f * A2},
					   { 0.250f * A2, 0.250f * A2, 0.250f * A2, 1.00f * A2},
					   { 0.250f * A2, 0.250f * A2, 0.250f * A2, 1.00f * A2},
					   { 0.125f * A2, 0.125f * A2, 0.125f * A2, 1.00f * A2},
					   { 0.125f * A2, 0.125f * A2, 0.125f * A2, 1.00f * A2},
					   { 0.000f * A2, 0.000f * A2, 0.000f * A2, 1.00f * A2},
					   { 0.000f * A2, 0.000f * A2, 0.000f * A2, 1.00f * A2},

					   { 1.000f * A3, 1.000f * A3, 1.000f * A3, 1.00f * A3},
					   { 1.000f * A3, 1.000f * A3, 1.000f * A3, 1.00f * A3},
					   { 0.500f * A3, 0.500f * A3, 0.500f * A3, 1.00f * A3},
					   { 0.500f * A3, 0.500f * A3, 0.500f * A3, 1.00f * A3},
					   { 0.250f * A3, 0.250f * A3, 0.250f * A3, 1.00f * A3 },
					   { 0.250f * A3, 0.250f * A3, 0.250f * A3, 1.00f * A3 },
					   { 0.125f * A3, 0.125f * A3, 0.125f * A3, 1.00f * A3 },
					   { 0.125f * A3, 0.125f * A3, 0.125f * A3, 1.00f * A3 },
					   { 0.000f * A3, 0.000f * A3, 0.000f * A3, 1.00f * A3 },
					   { 0.000f * A3, 0.000f * A3, 0.000f * A3, 1.00f * A3 },

					   // Add some source colors with alpha component that is different than the respective source color
					   { 1.000f, 1.000f, 1.000f, 1.000f },
					   { 0.250f, 0.250f, 0.250f, 0.500f },
					   { 0.500f, 0.500f, 0.500f, 0.750f },
					   { 0.250f, 0.250f, 0.250f, 0.250f },
					   { 0.250f, 0.250f, 0.250f, 0.500f },
					   { 0.125f, 0.125f, 0.125f, 0.125f }};

const	Vec4	clearColorVec4  (1.0f, 1.0f, 1.0f, 1.0f);

enum TestMode
{
	TEST_MODE_GENERIC = 0,
	TEST_MODE_COHERENT = 1,
};

struct BlendOperationAdvancedParam
{
	TestMode						testMode;
	deUint32						testNumber;
	std::vector<VkBlendOp>			blendOps;
	deBool							coherentOperations;
	deBool							independentBlend;
	deUint32						colorAttachmentsCount;
	VkBool32						premultipliedSrcColor;
	VkBool32						premultipliedDstColor;
	VkBlendOverlapEXT				overlap;
};

// helper functions
const std::string generateTestName (struct BlendOperationAdvancedParam param)
{
	std::ostringstream result;

	result << ((param.testMode == TEST_MODE_COHERENT && !param.coherentOperations) ? "barrier_" : "");
	result << "color_attachments_" << param.colorAttachmentsCount;
	result << "_" << de::toLower(getBlendOverlapEXTStr(param.overlap).toString().substr(3));
	result << (!param.premultipliedSrcColor ? "_nonpremultipliedsrc" : "");
	result << (!param.premultipliedDstColor ? "_nonpremultiplieddst" : "");
	result << "_" << param.testNumber;
	return result.str();
}

const std::string generateTestDescription ()
{
	std::string result("Test advanced blend operations");
	return result;
}

Vec3 calculateWeightingFactors(BlendOperationAdvancedParam param,
									float alphaSrc, float alphaDst)
{
	Vec3 p = Vec3(0.0f, 0.0f, 0.0f);
	switch(param.overlap)
	{
	case VK_BLEND_OVERLAP_UNCORRELATED_EXT:
		p.x() = alphaSrc * alphaDst;
		p.y() = alphaSrc * (1.0f - alphaDst);
		p.z() = alphaDst * (1.0f - alphaSrc);
		break;
	case VK_BLEND_OVERLAP_CONJOINT_EXT:
		p.x() = deFloatMin(alphaSrc, alphaDst);
		p.y() = deFloatMax(alphaSrc - alphaDst, 0.0f);
		p.z() = deFloatMax(alphaDst - alphaSrc, 0.0f);
		break;
	case VK_BLEND_OVERLAP_DISJOINT_EXT:
		p.x() = deFloatMax(alphaSrc + alphaDst - 1.0f, 0.0f);
		p.y() = deFloatMin(alphaSrc, 1.0f - alphaDst);
		p.z() = deFloatMin(alphaDst, 1.0f - alphaSrc);
		break;
	default:
		DE_FATAL("Unsupported Advanced Blend Overlap Mode");
	}
	return p;
}

	Vec3 calculateXYZFactors(VkBlendOp op)
{
	Vec3 xyz = Vec3(0.0f, 0.0f, 0.0f);
	switch (op)
	{
	case VK_BLEND_OP_ZERO_EXT:
		xyz = Vec3(0.0f, 0.0f, 0.0f);
		break;

	case VK_BLEND_OP_DST_ATOP_EXT:
	case VK_BLEND_OP_SRC_EXT:
		xyz = Vec3(1.0f, 1.0f, 0.0f);
		break;

	case VK_BLEND_OP_DST_EXT:
		xyz = Vec3(1.0f, 0.0f, 1.0f);
		break;

	case VK_BLEND_OP_HSL_LUMINOSITY_EXT:
	case VK_BLEND_OP_HSL_COLOR_EXT:
	case VK_BLEND_OP_HSL_SATURATION_EXT:
	case VK_BLEND_OP_HSL_HUE_EXT:
	case VK_BLEND_OP_HARDMIX_EXT:
	case VK_BLEND_OP_PINLIGHT_EXT:
	case VK_BLEND_OP_LINEARLIGHT_EXT:
	case VK_BLEND_OP_VIVIDLIGHT_EXT:
	case VK_BLEND_OP_LINEARBURN_EXT:
	case VK_BLEND_OP_LINEARDODGE_EXT:
	case VK_BLEND_OP_EXCLUSION_EXT:
	case VK_BLEND_OP_DIFFERENCE_EXT:
	case VK_BLEND_OP_SOFTLIGHT_EXT:
	case VK_BLEND_OP_HARDLIGHT_EXT:
	case VK_BLEND_OP_COLORBURN_EXT:
	case VK_BLEND_OP_COLORDODGE_EXT:
	case VK_BLEND_OP_LIGHTEN_EXT:
	case VK_BLEND_OP_DARKEN_EXT:
	case VK_BLEND_OP_OVERLAY_EXT:
	case VK_BLEND_OP_SCREEN_EXT:
	case VK_BLEND_OP_MULTIPLY_EXT:
	case VK_BLEND_OP_SRC_OVER_EXT:
	case VK_BLEND_OP_DST_OVER_EXT:
		xyz = Vec3(1.0f, 1.0f, 1.0f);
		break;

	case VK_BLEND_OP_SRC_IN_EXT:
	case VK_BLEND_OP_DST_IN_EXT:
		xyz = Vec3(1.0f, 0.0f, 0.0f);
		break;

	case VK_BLEND_OP_SRC_OUT_EXT:
		xyz = Vec3(0.0f, 1.0f, 0.0f);
		break;

	case VK_BLEND_OP_DST_OUT_EXT:
		xyz = Vec3(0.0f, 0.0f, 1.0f);
		break;

	case VK_BLEND_OP_INVERT_RGB_EXT:
	case VK_BLEND_OP_INVERT_EXT:
	case VK_BLEND_OP_SRC_ATOP_EXT:
		xyz = Vec3(1.0f, 0.0f, 1.0f);
		break;

	case VK_BLEND_OP_XOR_EXT:
		xyz = Vec3(0.0f, 1.0f, 1.0f);
		break;

	default:
		DE_FATAL("Unsupported f/X/Y/Z Advanced Blend Operations Mode");
	}

	return xyz;
}

float blendOpOverlay(float src, float dst)
{
	if (dst <= 0.5f)
		return (2.0f * src * dst);
	else
		return (1.0f - (2.0f * (1.0f - src) * (1.0f - dst)));
}

float blendOpColorDodge(float src, float dst)
{
	if (dst <= 0.0f)
		return 0.0f;
	else if (src < 1.0f)
		return deFloatMin(1.0f, (dst / (1.0f - src)));
	else
		return 1.0f;
}

float blendOpColorBurn(float src, float dst)
{
	if (dst >= 1.0f)
		return 1.0f;
	else if (src > 0.0f)
		return 1.0f - deFloatMin(1.0f, (1.0f - dst) / src);
	else
		return 0.0f;
}

float blendOpHardlight(float src, float dst)
{
	if (src <= 0.5f)
		return 2.0f * src * dst;
	else
		return 1.0f - (2.0f * (1.0f - src) * (1.0f - dst));
}

float blendOpSoftlight(float src, float dst)
{
	if (src <= 0.5f)
		return dst - ((1.0f - (2.0f * src)) * dst * (1.0f - dst));
	else if (dst <= 0.25f)
		return dst + (((2.0f * src) - 1.0f) * dst * ((((16.0f * dst) - 12.0f) * dst) + 3.0f));
	else
		return dst + (((2.0f * src) - 1.0f) * (deFloatSqrt(dst) - dst));
}

float blendOpLinearDodge(float src, float dst)
{
	if ((src + dst) <= 1.0f)
		return src + dst;
	else
		return 1.0f;
}

float blendOpLinearBurn(float src, float dst)
{
	if ((src + dst) > 1.0f)
		return src + dst - 1.0f;
	else
		return 0.0f;
}

float blendOpVividLight(float src, float dst)
{
	if (src <= 0.0f)
		return 0.0f;
	if (src < 0.5f)
		return 1.0f - (deFloatMin(1.0f, (1.0f - dst) / (2.0f * src)));
	if (src < 1.0f)
		return deFloatMin(1.0f, dst / (2.0f * (1.0f - src)));
	else
		return 1.0f;
}

float blendOpLinearLight(float src, float dst)
{
	if ((2.0f * src + dst) > 2.0f)
		return 1.0f;
	if ((2.0f * src + dst) <= 1.0f)
		return 0.0f;
	return (2.0f * src) + dst - 1.0f;
}

float blendOpPinLight(float src, float dst)
{
	if (((2.0f * src - 1.0f) > dst) && src < 0.5f)
		return 0.0f;
	if (((2.0f * src - 1.0f) > dst) && src >= 0.5f)
		return 2.0f * src - 1.0f;
	if (((2.0f * src - 1.0f) <= dst) && src < (0.5f * dst))
		return 2.0f * src;
	if (((2.0f * src - 1.0f) <= dst) && src >= (0.5f * dst))
		return dst;
	return 0.0f;
}

float blendOpHardmix(float src, float dst)
{
	if ((src + dst) < 1.0f)
		return 0.0f;
	else
		return 1.0f;
}

float minv3(Vec3 c)
{
	return deFloatMin(deFloatMin(c.x(), c.y()), c.z());
}

float maxv3(Vec3 c)
{
	return deFloatMax(deFloatMax(c.x(), c.y()), c.z());
}

float lumv3(Vec3 c)
{
	return dot(c, Vec3(0.3f, 0.59f, 0.11f));
}

float satv3(Vec3 c)
{
	return maxv3(c) - minv3(c);
}

// If any color components are outside [0,1], adjust the color to
// get the components in range.
Vec3 clipColor(Vec3 color)
{
	float lum = lumv3(color);
	float mincol = minv3(color);
	float maxcol = maxv3(color);

	if (mincol < 0.0)
	{
		color = lum + ((color - lum) * lum) / (lum - mincol);
	}
	if (maxcol > 1.0)
	{
		color = lum + ((color - lum) * (1.0f - lum)) / (maxcol - lum);
	}
	return color;
}

// Take the base RGB color <cbase> and override its luminosity
// with that of the RGB color <clum>.
Vec3 setLum(Vec3 cbase, Vec3 clum)
{
	float lbase = lumv3(cbase);
	float llum = lumv3(clum);
	float ldiff = llum - lbase;

	Vec3 color = cbase + Vec3(ldiff);
	return clipColor(color);
}

// Take the base RGB color <cbase> and override its saturation with
// that of the RGB color <csat>.  The override the luminosity of the
// result with that of the RGB color <clum>.
Vec3 setLumSat(Vec3 cbase, Vec3 csat, Vec3 clum)
{
	float minbase = minv3(cbase);
	float sbase = satv3(cbase);
	float ssat = satv3(csat);
	Vec3 color;

	if (sbase > 0)
	{
		// Equivalent (modulo rounding errors) to setting the
		// smallest (R,G,B) component to 0, the largest to <ssat>,
		// and interpolating the "middle" component based on its
		// original value relative to the smallest/largest.
		color = (cbase - minbase) * ssat / sbase;
	} else {
		color = Vec3(0.0f);
	}
	return setLum(color, clum);
}

Vec3 calculateFFunction(VkBlendOp op,
						Vec3 src, Vec3 dst)
{
	Vec3 f = Vec3(0.0f, 0.0f, 0.0f);

	switch (op)
	{
	case VK_BLEND_OP_XOR_EXT:
	case VK_BLEND_OP_SRC_OUT_EXT:
	case VK_BLEND_OP_DST_OUT_EXT:
	case VK_BLEND_OP_ZERO_EXT:
		f = Vec3(0.0f, 0.0f, 0.0f);
		break;

	case VK_BLEND_OP_SRC_ATOP_EXT:
	case VK_BLEND_OP_SRC_IN_EXT:
	case VK_BLEND_OP_SRC_OVER_EXT:
	case VK_BLEND_OP_SRC_EXT:
		f = src;
		break;

	case VK_BLEND_OP_DST_ATOP_EXT:
	case VK_BLEND_OP_DST_IN_EXT:
	case VK_BLEND_OP_DST_OVER_EXT:
	case VK_BLEND_OP_DST_EXT:
		f = dst;
		break;

	case VK_BLEND_OP_MULTIPLY_EXT:
		f = src * dst;
		break;

	case VK_BLEND_OP_SCREEN_EXT:
		f = src + dst - (src*dst);
		break;

	case VK_BLEND_OP_OVERLAY_EXT:
		f.x() = blendOpOverlay(src.x(), dst.x());
		f.y() = blendOpOverlay(src.y(), dst.y());
		f.z() = blendOpOverlay(src.z(), dst.z());
		break;

	case VK_BLEND_OP_DARKEN_EXT:
		f.x() = deFloatMin(src.x(), dst.x());
		f.y() = deFloatMin(src.y(), dst.y());
		f.z() = deFloatMin(src.z(), dst.z());
		break;

	case VK_BLEND_OP_LIGHTEN_EXT:
		f.x() = deFloatMax(src.x(), dst.x());
		f.y() = deFloatMax(src.y(), dst.y());
		f.z() = deFloatMax(src.z(), dst.z());
		break;

	case VK_BLEND_OP_COLORDODGE_EXT:
		f.x() = blendOpColorDodge(src.x(), dst.x());
		f.y() = blendOpColorDodge(src.y(), dst.y());
		f.z() = blendOpColorDodge(src.z(), dst.z());
		break;

	case VK_BLEND_OP_COLORBURN_EXT:
		f.x() = blendOpColorBurn(src.x(), dst.x());
		f.y() = blendOpColorBurn(src.y(), dst.y());
		f.z() = blendOpColorBurn(src.z(), dst.z());
		break;

	case VK_BLEND_OP_HARDLIGHT_EXT:
		f.x() = blendOpHardlight(src.x(), dst.x());
		f.y() = blendOpHardlight(src.y(), dst.y());
		f.z() = blendOpHardlight(src.z(), dst.z());
		break;

	case VK_BLEND_OP_SOFTLIGHT_EXT:
		f.x() = blendOpSoftlight(src.x(), dst.x());
		f.y() = blendOpSoftlight(src.y(), dst.y());
		f.z() = blendOpSoftlight(src.z(), dst.z());
		break;

	case VK_BLEND_OP_DIFFERENCE_EXT:
		f.x() = deFloatAbs(dst.x() - src.x());
		f.y() = deFloatAbs(dst.y() - src.y());
		f.z() = deFloatAbs(dst.z() - src.z());
		break;


	case VK_BLEND_OP_EXCLUSION_EXT:
		f = src + dst - (2.0f * src * dst);
		break;

	case VK_BLEND_OP_INVERT_EXT:
		f = 1.0f - dst;
		break;

	case VK_BLEND_OP_INVERT_RGB_EXT:
		f = src * (1.0f - dst);
		break;

	case VK_BLEND_OP_LINEARDODGE_EXT:
		f.x() = blendOpLinearDodge(src.x(), dst.x());
		f.y() = blendOpLinearDodge(src.y(), dst.y());
		f.z() = blendOpLinearDodge(src.z(), dst.z());
		break;

	case VK_BLEND_OP_LINEARBURN_EXT:
		f.x() = blendOpLinearBurn(src.x(), dst.x());
		f.y() = blendOpLinearBurn(src.y(), dst.y());
		f.z() = blendOpLinearBurn(src.z(), dst.z());
		break;

	case VK_BLEND_OP_VIVIDLIGHT_EXT:
		f.x() = blendOpVividLight(src.x(), dst.x());
		f.y() = blendOpVividLight(src.y(), dst.y());
		f.z() = blendOpVividLight(src.z(), dst.z());
		break;

	case VK_BLEND_OP_LINEARLIGHT_EXT:
		f.x() = blendOpLinearLight(src.x(), dst.x());
		f.y() = blendOpLinearLight(src.y(), dst.y());
		f.z() = blendOpLinearLight(src.z(), dst.z());
		break;

	case VK_BLEND_OP_PINLIGHT_EXT:
		f.x() = blendOpPinLight(src.x(), dst.x());
		f.y() = blendOpPinLight(src.y(), dst.y());
		f.z() = blendOpPinLight(src.z(), dst.z());
		break;

	case VK_BLEND_OP_HARDMIX_EXT:
		f.x() = blendOpHardmix(src.x(), dst.x());
		f.y() = blendOpHardmix(src.y(), dst.y());
		f.z() = blendOpHardmix(src.z(), dst.z());
		break;

	case VK_BLEND_OP_HSL_HUE_EXT:
		f = setLumSat(src, dst, dst);
		break;

	case VK_BLEND_OP_HSL_SATURATION_EXT:
		f = setLumSat(dst, src, dst);
		break;

	case VK_BLEND_OP_HSL_COLOR_EXT:
		f = setLum(src, dst);
		break;

	case VK_BLEND_OP_HSL_LUMINOSITY_EXT:
		f = setLum(dst, src);
		break;

	default:
		DE_FATAL("Unsupported f/X/Y/Z Advanced Blend Operations Mode");
	}

	return f;
}

Vec4 additionalRGBBlendOperations(VkBlendOp op,
								  Vec4 src, Vec4 dst)
{
	Vec4 res = Vec4(0.0f, 0.0f, 0.0f, 1.0f);

	switch (op)
	{
	case VK_BLEND_OP_PLUS_EXT:
		res = src + dst;
		break;

	case VK_BLEND_OP_PLUS_CLAMPED_EXT:
		res.x() = deFloatMin(1.0f, src.x() + dst.x());
		res.y() = deFloatMin(1.0f, src.y() + dst.y());
		res.z() = deFloatMin(1.0f, src.z() + dst.z());
		res.w() = deFloatMin(1.0f, src.w() + dst.w());
		break;

	case VK_BLEND_OP_PLUS_CLAMPED_ALPHA_EXT:
		res.x() = deFloatMin(deFloatMin(1.0f, src.w() + dst.w()), src.x() + dst.x());
		res.y() = deFloatMin(deFloatMin(1.0f, src.w() + dst.w()), src.y() + dst.y());
		res.z() = deFloatMin(deFloatMin(1.0f, src.w() + dst.w()), src.z() + dst.z());
		res.w() = deFloatMin(1.0f, src.w() + dst.w());
		break;

	case VK_BLEND_OP_PLUS_DARKER_EXT:
		res.x() = deFloatMax(0.0f, deFloatMin(1.0f, src.w() + dst.w()) - ((src.w() - src.x()) + (dst.w() - dst.x())));
		res.y() = deFloatMax(0.0f, deFloatMin(1.0f, src.w() + dst.w()) - ((src.w() - src.y()) + (dst.w() - dst.y())));
		res.z() = deFloatMax(0.0f, deFloatMin(1.0f, src.w() + dst.w()) - ((src.w() - src.z()) + (dst.w() - dst.z())));
		res.w() = deFloatMin(1.0f, src.w() + dst.w());
		break;

	case VK_BLEND_OP_MINUS_EXT:
		res = dst - src;
		break;

	case VK_BLEND_OP_MINUS_CLAMPED_EXT:
		res.x() = deFloatMax(0.0f, dst.x() - src.x());
		res.y() = deFloatMax(0.0f, dst.y() - src.y());
		res.z() = deFloatMax(0.0f, dst.z() - src.z());
		res.w() = deFloatMax(0.0f, dst.w() - src.w());
		break;

	case VK_BLEND_OP_CONTRAST_EXT:
		res.x() = (dst.w() / 2.0f) + 2.0f * (dst.x() - (dst.w() / 2.0f)) * (src.x() - (src.w() / 2.0f));
		res.y() = (dst.w() / 2.0f) + 2.0f * (dst.y() - (dst.w() / 2.0f)) * (src.y() - (src.w() / 2.0f));
		res.z() = (dst.w() / 2.0f) + 2.0f * (dst.z() - (dst.w() / 2.0f)) * (src.z() - (src.w() / 2.0f));
		res.w() = dst.w();
		break;

	case VK_BLEND_OP_INVERT_OVG_EXT:
		res.x() = src.w() * (1.0f - dst.x()) + (1.0f - src.w()) * dst.x();
		res.y() = src.w() * (1.0f - dst.y()) + (1.0f - src.w()) * dst.y();
		res.z() = src.w() * (1.0f - dst.z()) + (1.0f - src.w()) * dst.z();
		res.w() = src.w() + dst.w() - src.w() * dst.w();
		break;

	case VK_BLEND_OP_RED_EXT:
		res = dst;
		res.x() = src.x();
		break;

	case VK_BLEND_OP_GREEN_EXT:
		res = dst;
		res.y() = src.y();
		break;

	case VK_BLEND_OP_BLUE_EXT:
		res = dst;
		res.z() = src.z();
		break;

	default:
		DE_FATAL("Unsupported blend operation");
	}
	return res;
}

Vec4 calculateFinalColor(BlendOperationAdvancedParam param, VkBlendOp op,
						 Vec4 source, Vec4 destination)
{
	Vec4 result = Vec4(0.0f, 0.0f, 0.0f, 1.0f);
	Vec3 srcColor = source.xyz();
	Vec3 dstColor = destination.xyz();

	// Calculate weighting factors
	Vec3 p = calculateWeightingFactors(param, source.w(), destination.w());

	if (op > VK_BLEND_OP_MAX && op < VK_BLEND_OP_PLUS_EXT)
	{
		{
			// If srcPremultiplied is set to VK_TRUE, the fragment color components
			// are considered to have been premultiplied by the A component prior to
			// blending. The base source color (Rs',Gs',Bs') is obtained by dividing
			// through by the A component.
			if (param.premultipliedSrcColor)
			{
				if (source.w() != 0.0f)
					srcColor = srcColor / source.w();
				else
					srcColor = Vec3(0.0f, 0.0f, 0.0f);
			}
			// If dstPremultiplied is set to VK_TRUE, the destination components are
			// considered to have been premultiplied by the A component prior to
			// blending. The base destination color (Rd',Gd',Bd') is obtained by dividing
			// through by the A component.
			if (param.premultipliedDstColor)
			{
				if (destination.w() != 0.0f)
					dstColor = dstColor / destination.w();
				else
					dstColor = Vec3(0.0f, 0.0f, 0.0f);
			}
		}

		// Calculate X, Y, Z terms of the equation
		Vec3 xyz = calculateXYZFactors(op);
		Vec3 fSrcDst = calculateFFunction(op, srcColor, dstColor);

		result.x() = fSrcDst.x() * p.x() + xyz.y() * srcColor.x() * p.y() + xyz.z() * dstColor.x() * p.z();
		result.y() = fSrcDst.y() * p.x() + xyz.y() * srcColor.y() * p.y() + xyz.z() * dstColor.y() * p.z();
		result.z() = fSrcDst.z() * p.x() + xyz.y() * srcColor.z() * p.y() + xyz.z() * dstColor.z() * p.z();
		result.w() = xyz.x() * p.x() + xyz.y() * p.y() + xyz.z() * p.z();
	}
	else if (op >= VK_BLEND_OP_PLUS_EXT && op < VK_BLEND_OP_MAX_ENUM)
	{
		// Premultiply colors for additional RGB blend operations. The formula is different than the rest of operations.
		{
			if (!param.premultipliedSrcColor)
			{
				srcColor = srcColor * source.w();
			}

			if (!param.premultipliedDstColor)
			{
				dstColor = dstColor * destination.w();
			}

		}
		Vec4 src = Vec4(srcColor.x(), srcColor.y(), srcColor.z(), source.w());
		Vec4 dst = Vec4(dstColor.x(), dstColor.y(), dstColor.z(), destination.w());
		result = additionalRGBBlendOperations(op, src, dst);
	}
	else
	{
		DE_FATAL("Unsupported Blend Operation");
	}
	return result;
}

static inline void getCoordinates (deUint32 index, deInt32 &x, deInt32 &y)
{
	x = index % widthArea;
	y = index / heightArea;
}

static inline std::vector<Vec4> createPoints (void)
{
	std::vector<Vec4> vertices;
	vertices.push_back(Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
	vertices.push_back(Vec4( 1.0f,  1.0f, 0.0f, 1.0f));
	vertices.push_back(Vec4(-1.0f,  1.0f, 0.0f, 1.0f));
	vertices.push_back(Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
	vertices.push_back(Vec4( 1.0f,  1.0f, 0.0f, 1.0f));
	vertices.push_back(Vec4( 1.0f, -1.0f, 0.0f, 1.0f));
	return vertices;
}

template <class Test>
vkt::TestCase* newTestCase (tcu::TestContext&					testContext,
							const BlendOperationAdvancedParam	testParam)
{
	return new Test(testContext,
					generateTestName(testParam).c_str(),
					generateTestDescription().c_str(),
					testParam);
}

Move<VkRenderPass> makeTestRenderPass (BlendOperationAdvancedParam			param,
									   const DeviceInterface&				vk,
									   const VkDevice						device,
									   const VkFormat						colorFormat,
									   VkAttachmentLoadOp					colorLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR)
{
	const VkAttachmentDescription			colorAttachmentDescription			=
	{
		(VkAttachmentDescriptionFlags)0,				// VkAttachmentDescriptionFlags		flags
		colorFormat,									// VkFormat							format
		VK_SAMPLE_COUNT_1_BIT,							// VkSampleCountFlagBits			samples
		colorLoadOp,									// 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
		(colorLoadOp == VK_ATTACHMENT_LOAD_OP_LOAD) ?
			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL :
			VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout					initialLayout
		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL		// VkImageLayout					finalLayout
	};

	std::vector<VkAttachmentDescription>	attachmentDescriptions;
	std::vector<VkAttachmentReference>		colorAttachmentRefs;


	for (deUint32 i = 0; i < param.colorAttachmentsCount; i++)
	{
		attachmentDescriptions.push_back(colorAttachmentDescription);
		const VkAttachmentReference		colorAttachmentRef	=
		{
			i,											// deUint32		attachment
			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout	layout
		};

		colorAttachmentRefs.push_back(colorAttachmentRef);
	}

	const VkSubpassDescription				subpassDescription					=
	{
		(VkSubpassDescriptionFlags)0,							// VkSubpassDescriptionFlags		flags
		VK_PIPELINE_BIND_POINT_GRAPHICS,						// VkPipelineBindPoint				pipelineBindPoint
		0u,														// deUint32							inputAttachmentCount
		DE_NULL,												// const VkAttachmentReference*		pInputAttachments
		param.colorAttachmentsCount,							// deUint32							colorAttachmentCount
		colorAttachmentRefs.data(),								// const VkAttachmentReference*		pColorAttachments
		DE_NULL,												// const VkAttachmentReference*		pResolveAttachments
		DE_NULL,												// const VkAttachmentReference*		pDepthStencilAttachment
		0u,														// deUint32							preserveAttachmentCount
		DE_NULL													// const deUint32*					pPreserveAttachments
	};

	const VkRenderPassCreateInfo			renderPassInfo						=
	{
		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,									// VkStructureType					sType
		DE_NULL,																	// const void*						pNext
		(VkRenderPassCreateFlags)0,													// VkRenderPassCreateFlags			flags
		(deUint32)attachmentDescriptions.size(),									// deUint32							attachmentCount
		attachmentDescriptions.data(),												// const VkAttachmentDescription*	pAttachments
		1u,																			// deUint32							subpassCount
		&subpassDescription,														// const VkSubpassDescription*		pSubpasses
		0u,																			// deUint32							dependencyCount
		DE_NULL																		// const VkSubpassDependency*		pDependencies
	};

	return createRenderPass(vk, device, &renderPassInfo, DE_NULL);
}

Move<VkBuffer> createBufferAndBindMemory (Context& context, VkDeviceSize size, VkBufferUsageFlags usage, de::MovePtr<Allocation>* pAlloc)
{
	const DeviceInterface&	vk				 = context.getDeviceInterface();
	const VkDevice			vkDevice		 = context.getDevice();
	const deUint32			queueFamilyIndex = context.getUniversalQueueFamilyIndex();

	const VkBufferCreateInfo vertexBufferParams =
	{
		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
		DE_NULL,									// const void*			pNext;
		0u,											// VkBufferCreateFlags	flags;
		size,										// VkDeviceSize			size;
		usage,										// VkBufferUsageFlags	usage;
		VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
		1u,											// deUint32				queueFamilyCount;
		&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
	};

	Move<VkBuffer> vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams);

	*pAlloc = context.getDefaultAllocator().allocate(getBufferMemoryRequirements(vk, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible);
	VK_CHECK(vk.bindBufferMemory(vkDevice, *vertexBuffer, (*pAlloc)->getMemory(), (*pAlloc)->getOffset()));

	return vertexBuffer;
}

Move<VkImage> createImage2DAndBindMemory (Context&							context,
										  VkFormat							format,
										  deUint32							width,
										  deUint32							height,
										  VkImageUsageFlags					usage,
										  VkSampleCountFlagBits				sampleCount,
										  de::details::MovePtr<Allocation>* pAlloc)
{
	const DeviceInterface&	vk				 = context.getDeviceInterface();
	const VkDevice			vkDevice		 = context.getDevice();
	const deUint32			queueFamilyIndex = context.getUniversalQueueFamilyIndex();

	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;
		format,																		// VkFormat				format;
		{ width, height, 1u },														// VkExtent3D			extent;
		1u,																			// deUint32				mipLevels;
		1u,																			// deUint32				arraySize;
		sampleCount,																// deUint32				samples;
		VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling		tiling;
		usage,																		// VkImageUsageFlags	usage;
		VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode		sharingMode;
		1u,																			// deUint32				queueFamilyCount;
		&queueFamilyIndex,															// const deUint32*		pQueueFamilyIndices;
		VK_IMAGE_LAYOUT_UNDEFINED,													// VkImageLayout		initialLayout;
	};

	Move<VkImage> image = createImage(vk, vkDevice, &colorImageParams);

	*pAlloc = context.getDefaultAllocator().allocate(getImageMemoryRequirements(vk, vkDevice, *image), MemoryRequirement::Any);
	VK_CHECK(vk.bindImageMemory(vkDevice, *image, (*pAlloc)->getMemory(), (*pAlloc)->getOffset()));

	return image;
}

// Test Classes
class BlendOperationAdvancedTestInstance : public vkt::TestInstance
{
public:
								BlendOperationAdvancedTestInstance		(Context&				context,
																		 const BlendOperationAdvancedParam	param);
	virtual						~BlendOperationAdvancedTestInstance		(void);
	virtual tcu::TestStatus		iterate									(void);
protected:
			void				prepareRenderPass						(VkFramebuffer framebuffer, VkPipeline pipeline) const;
			void				prepareCommandBuffer					(void) const;
			void				buildPipeline							(VkBool32 premultiplySrc, VkBool32 premultiplyDst);
			void				bindShaderStage							(VkShaderStageFlagBits					stage,
																		 const char*							sourceName,
																		 const char*							entryName);
			deBool				verifyTestResult						(void);
protected:
	const BlendOperationAdvancedParam		m_param;
	const tcu::UVec2						m_renderSize;
	const VkFormat							m_colorFormat;
	Move<VkPipelineLayout>					m_pipelineLayout;

	Move<VkBuffer>							m_vertexBuffer;
	de::MovePtr<Allocation>					m_vertexBufferMemory;
	std::vector<Vec4>						m_vertices;

	Move<VkRenderPass>						m_renderPass;
	Move<VkCommandPool>						m_cmdPool;
	Move<VkCommandBuffer>					m_cmdBuffer;
	std::vector<Move<VkImage>>				m_colorImages;
	std::vector<Move<VkImageView>>			m_colorAttachmentViews;
	std::vector<de::MovePtr<Allocation>>	m_colorImageAllocs;
	std::vector<VkImageMemoryBarrier>		m_imageLayoutBarriers;
	Move<VkFramebuffer>						m_framebuffer;
	Move<VkPipeline>						m_pipeline;

	Move<VkShaderModule>					m_shaderModules[2];
	deUint32								m_shaderStageCount;
	VkPipelineShaderStageCreateInfo			m_shaderStageInfo[2];
};

void BlendOperationAdvancedTestInstance::bindShaderStage (VkShaderStageFlagBits	stage,
														  const char*			sourceName,
														  const char*			entryName)
{
	const DeviceInterface&	vk			= m_context.getDeviceInterface();
	const VkDevice			vkDevice	= m_context.getDevice();

	// Create shader module
	deUint32*				code		= (deUint32*)m_context.getBinaryCollection().get(sourceName).getBinary();
	deUint32				codeSize	= (deUint32)m_context.getBinaryCollection().get(sourceName).getSize();

	const VkShaderModuleCreateInfo moduleCreateInfo =
	{
		VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,				// VkStructureType				sType;
		DE_NULL,													// const void*					pNext;
		0u,															// VkShaderModuleCreateFlags	flags;
		codeSize,													// deUintptr					codeSize;
		code,														// const deUint32*				pCode;
	};

	m_shaderModules[m_shaderStageCount] = createShaderModule(vk, vkDevice, &moduleCreateInfo);

	// Prepare shader stage info
	m_shaderStageInfo[m_shaderStageCount].sType					= VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
	m_shaderStageInfo[m_shaderStageCount].pNext					= DE_NULL;
	m_shaderStageInfo[m_shaderStageCount].flags					= 0u;
	m_shaderStageInfo[m_shaderStageCount].stage					= stage;
	m_shaderStageInfo[m_shaderStageCount].module				= *m_shaderModules[m_shaderStageCount];
	m_shaderStageInfo[m_shaderStageCount].pName					= entryName;
	m_shaderStageInfo[m_shaderStageCount].pSpecializationInfo	= DE_NULL;

	m_shaderStageCount++;
}

void BlendOperationAdvancedTestInstance::buildPipeline (VkBool32 srcPremultiplied,
													   VkBool32 dstPremultiplied)
{
	const DeviceInterface&		vk					= m_context.getDeviceInterface();
	const VkDevice				vkDevice			= m_context.getDevice();

	// Create pipeline
	const VkVertexInputBindingDescription vertexInputBindingDescription =
	{
		0u,									// deUint32				binding;
		sizeof(Vec4),						// deUint32				strideInBytes;
		VK_VERTEX_INPUT_RATE_VERTEX,		// VkVertexInputRate	inputRate;
	};

	const VkVertexInputAttributeDescription vertexInputAttributeDescription =
	{
		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;
		0u,																// VkPipelineVertexInputStateCreateFlags	flags;
		1u,																// deUint32									vertexBindingDescriptionCount;
		&vertexInputBindingDescription,									// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
		1u,																// deUint32									vertexAttributeDescriptionCount;
		&vertexInputAttributeDescription,								// 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;
		VK_FALSE,														// VkBool32									primitiveRestartEnable;
	};

	const VkRect2D		scissor		= makeRect2D(m_renderSize);
	VkViewport			viewport	= makeViewport(m_renderSize);

	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;
		VK_FALSE,														// VkBool32									depthClampEnable;
		VK_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 VkPipelineColorBlendAdvancedStateCreateInfoEXT blendAdvancedStateParams =
	{
		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT,	// VkStructureType		sType;
		DE_NULL,																// const void*			pNext;
		srcPremultiplied,														// VkBool32				srcPremultiplied;
		dstPremultiplied,														// VkBool32				dstPremultiplied;
		m_param.overlap,														// VkBlendOverlapEXT	blendOverlap;
	};

	std::vector<VkPipelineColorBlendAttachmentState>	colorBlendAttachmentStates;

	for (deUint32 i = 0; i < m_param.colorAttachmentsCount; i++)
	{
		const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
		{
			VK_TRUE,														// VkBool32									blendEnable;
			VK_BLEND_FACTOR_ONE,											// VkBlendFactor							srcColorBlendFactor;
			VK_BLEND_FACTOR_ONE,											// VkBlendFactor							dstColorBlendFactor;
			m_param.blendOps[i],											// VkBlendOp								colorBlendOp;
			VK_BLEND_FACTOR_ONE,											// VkBlendFactor							srcAlphaBlendFactor;
			VK_BLEND_FACTOR_ONE,											// VkBlendFactor							dstAlphaBlendFactor;
			m_param.blendOps[i],											// VkBlendOp								alphaBlendOp;
			VK_COLOR_COMPONENT_R_BIT |
			VK_COLOR_COMPONENT_G_BIT |
			VK_COLOR_COMPONENT_B_BIT |
			VK_COLOR_COMPONENT_A_BIT										// VkColorComponentFlags					colorWriteMask;
		};
		colorBlendAttachmentStates.emplace_back(colorBlendAttachmentState);
	}

	const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
	{
		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
		&blendAdvancedStateParams,									// const void*									pNext;
		0u,															// VkPipelineColorBlendStateCreateFlags			flags;
		VK_FALSE,													// VkBool32										logicOpEnable;
		VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
		(deUint32)colorBlendAttachmentStates.size(),				// deUint32										attachmentCount;
		colorBlendAttachmentStates.data(),							// const VkPipelineColorBlendAttachmentState*	pAttachments;
		{ 0.0f, 0.0f, 0.0f, 0.0f },									// float										blendConst[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;
		VK_FALSE,													// VkBool32										sampleShadingEnable;
		0.0f,														// float										minSampleShading;
		DE_NULL,													// const VkSampleMask*							pSampleMask;
		VK_FALSE,													// VkBool32										alphaToCoverageEnable;
		VK_FALSE,													// VkBool32										alphaToOneEnable;
	};

	VkPipelineDepthStencilStateCreateInfo depthStencilStateParams =
	{
		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType								sType;
		DE_NULL,													// const void*									pNext;
		0u,															// VkPipelineDepthStencilStateCreateFlags		flags;
		VK_FALSE,													// VkBool32										depthTestEnable;
		VK_FALSE,													// VkBool32										depthWriteEnable;
		VK_COMPARE_OP_NEVER,										// VkCompareOp									depthCompareOp;
		VK_FALSE,													// VkBool32										depthBoundsTestEnable;
		VK_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;
		},
		0.0f,														// float										minDepthBounds;
		1.0f,														// float										maxDepthBounds;
	};

	const VkDynamicState dynamicState = VK_DYNAMIC_STATE_SCISSOR;
	const VkPipelineDynamicStateCreateInfo dynamicStateParams =
	{
		VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,	// VkStructureType						sType;
		DE_NULL,												// const void*							pNext;
		0u,														// VkPipelineDynamicStateCreateFlags	flags;
		1u,														// uint32_t								dynamicStateCount;
		&dynamicState											// const VkDynamicState*				pDynamicStates;
	};

	const VkGraphicsPipelineCreateInfo graphicsPipelineParams =
	{
		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,	// VkStructureType										sType;
		DE_NULL,											// const void*											pNext;
		0u,													// VkPipelineCreateFlags								flags;
		m_shaderStageCount,									// deUint32												stageCount;
		m_shaderStageInfo,									// const VkPipelineShaderStageCreateInfo*				pStages;
		&vertexInputStateParams,							// const VkPipelineVertexInputStateCreateInfo*			pVertexInputState;
		&inputAssemblyStateParams,							// const VkPipelineInputAssemblyStateCreateInfo*		pInputAssemblyState;
		DE_NULL,											// const VkPipelineTessellationStateCreateInfo*			pTessellationState;
		&viewportStateParams,								// const VkPipelineViewportStateCreateInfo*				pViewportState;
		&rasterStateParams,									// const VkPipelineRasterizationStateCreateInfo*		pRasterState;
		&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;
		DE_NULL,											// VkPipeline											basePipelineHandle;
		0u,													// deInt32												basePipelineIndex;
	};

	m_pipeline = createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams);
}

void BlendOperationAdvancedTestInstance::prepareRenderPass (VkFramebuffer framebuffer, VkPipeline pipeline) const
{
	const DeviceInterface&	vk				 = m_context.getDeviceInterface();

	std::vector<VkClearValue>	attachmentClearValues;

	for (deUint32 i = 0; i < m_param.colorAttachmentsCount; i++)
		attachmentClearValues.emplace_back(makeClearValueColor(clearColorVec4));

	beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, framebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()),
					m_param.colorAttachmentsCount, attachmentClearValues.data());
	vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
	VkDeviceSize offsets = 0u;
	vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &m_vertexBuffer.get(), &offsets);

	// Draw all colors
	deUint32 skippedColors = 0u;
	for (deUint32 color = 0; color < DE_LENGTH_OF_ARRAY(srcColors); color++)
	{
		// Skip ill-formed colors when we have non-premultiplied destination colors.
		if (m_param.premultipliedDstColor == VK_FALSE)
		{
			deBool skipColor = false;
			for (deUint32 i = 0; i < m_param.colorAttachmentsCount; i++)
			{
				Vec4 calculatedColor = calculateFinalColor(m_param, m_param.blendOps[i], srcColors[color], dstColors[color]);
				if (calculatedColor.w() <= 0.0f && calculatedColor != Vec4(0.0f))
				{
					// Skip ill-formed colors, because the spec says the result is undefined.
					skippedColors++;
					skipColor = true;
					break;
				}
			}
			if (skipColor)
				continue;
		}

		deInt32 x = 0;
		deInt32 y = 0;
		getCoordinates(color, x, y);

		// Set source color as push constant
		vk.cmdPushConstants(*m_cmdBuffer, *m_pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(Vec4), &srcColors[color]);

		VkRect2D scissor = makeRect2D(x, y, 1u, 1u);
		vk.cmdSetScissor(*m_cmdBuffer, 0u, 1u, &scissor);

		// To set destination color, we do clear attachment restricting the area to the respective pixel of each color attachment.
		{
			// Set destination color as push constant.
			std::vector<VkClearAttachment> attachments;
			VkClearValue clearValue = vk::makeClearValueColorVec4(dstColors[color]);

			for (deUint32 i = 0; i < m_param.colorAttachmentsCount; i++)
			{
				VkClearAttachment	attachment	=
				{
					VK_IMAGE_ASPECT_COLOR_BIT,
					i,
					clearValue
				};
				attachments.emplace_back(attachment);
			}

			const VkClearRect rect =
			{
				scissor,
				0u,
				1u
			};
			vk.cmdClearAttachments(*m_cmdBuffer, (deUint32)attachments.size(), attachments.data(), 1u, &rect);
		}

		// Draw
		vk.cmdDraw(*m_cmdBuffer, (deUint32)m_vertices.size(), 1u, 0u, 0u);
	}

	// If we break this assert, then we are not testing anything in this test.
	DE_ASSERT(skippedColors < DE_LENGTH_OF_ARRAY(srcColors));

	// Log number of skipped colors
	if (skippedColors != 0u)
	{
		tcu::TestLog& log = m_context.getTestContext().getLog();
		log << tcu::TestLog::Message << "Skipped " << skippedColors << " out of " << DE_LENGTH_OF_ARRAY(srcColors) << " color cases due to ill-formed colors" << tcu::TestLog::EndMessage;
	}
	endRenderPass(vk, *m_cmdBuffer);
}

void BlendOperationAdvancedTestInstance::prepareCommandBuffer () const
{
	const DeviceInterface&	vk				 = m_context.getDeviceInterface();


	beginCommandBuffer(vk, *m_cmdBuffer, 0u);

	vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, (VkDependencyFlags)0,
						  0u, DE_NULL, 0u, DE_NULL, (deUint32)m_imageLayoutBarriers.size(), m_imageLayoutBarriers.data());

	prepareRenderPass(*m_framebuffer, *m_pipeline);

	endCommandBuffer(vk, *m_cmdBuffer);
}

BlendOperationAdvancedTestInstance::BlendOperationAdvancedTestInstance	(Context&							context,
																		 const BlendOperationAdvancedParam	param)
	: TestInstance			(context)
	, m_param				(param)
	, m_renderSize			(tcu::UVec2(widthArea, heightArea))
	, m_colorFormat			(VK_FORMAT_R16G16B16A16_SFLOAT)
	, m_shaderStageCount	(0)
{
	const DeviceInterface&		vk				 = m_context.getDeviceInterface();
	const VkDevice				vkDevice		 = m_context.getDevice();
	const deUint32				queueFamilyIndex = context.getUniversalQueueFamilyIndex();

	// Create vertex buffer and upload data
	{
		// Load vertices into vertex buffer
		m_vertices		= createPoints();
		DE_ASSERT((deUint32)m_vertices.size() == 6);

		m_vertexBuffer	= createBufferAndBindMemory(m_context, m_vertices.size() * sizeof(Vec4), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, &m_vertexBufferMemory);
		deMemcpy(m_vertexBufferMemory->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vec4));
		flushAlloc(vk, vkDevice, *m_vertexBufferMemory);
	}

	// Create render pass
	m_renderPass = makeTestRenderPass(param, vk, vkDevice, m_colorFormat);

	const VkComponentMapping	componentMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};

	// Create color images
	for (deUint32 i = 0; i < param.colorAttachmentsCount; i++)
	{
		de::MovePtr<Allocation>	colorImageAlloc;
		m_colorImageAllocs.emplace_back(colorImageAlloc);

		Move<VkImage>			colorImage	= createImage2DAndBindMemory(m_context,
																		 m_colorFormat,
																		 m_renderSize.x(),
																		 m_renderSize.y(),
																		 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
																		 VK_SAMPLE_COUNT_1_BIT,
																		 &m_colorImageAllocs.back());
		m_colorImages.emplace_back(colorImage);

		// Set up image layout transition barriers
		{
			VkImageMemoryBarrier colorImageBarrier =
			{
				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,					// VkStructureType			sType;
				DE_NULL,												// const void*				pNext;
				0u,														// VkAccessFlags			srcAccessMask;
				(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
				 VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT),	// VkAccessFlags			dstAccessMask;
				VK_IMAGE_LAYOUT_UNDEFINED,								// VkImageLayout			oldLayout;
				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,				// VkImageLayout			newLayout;
				VK_QUEUE_FAMILY_IGNORED,								// deUint32					srcQueueFamilyIndex;
				VK_QUEUE_FAMILY_IGNORED,								// deUint32					dstQueueFamilyIndex;
				*m_colorImages.back(),									// VkImage					image;
				{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },			// VkImageSubresourceRange	subresourceRange;
			};

			m_imageLayoutBarriers.emplace_back(colorImageBarrier);
		}

		// Create color attachment view
		{
			VkImageViewCreateInfo colorAttachmentViewParams =
			{
				VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType			sType;
				DE_NULL,										// const void*				pNext;
				0u,												// VkImageViewCreateFlags	flags;
				*m_colorImages.back(),							// 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_colorAttachmentViews.emplace_back(createImageView(vk, vkDevice, &colorAttachmentViewParams));
		}
	}

	// Create framebuffer
	{
		std::vector<VkImageView>	imageViews;

		for (auto& movePtr : m_colorAttachmentViews)
			imageViews.push_back(movePtr.get());

		const VkFramebufferCreateInfo framebufferParams =
		{
			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,			// VkStructureType				sType;
			DE_NULL,											// const void*					pNext;
			0u,													// VkFramebufferCreateFlags		flags;
			*m_renderPass,										// VkRenderPass					renderPass;
			(deUint32)imageViews.size(),						// deUint32						attachmentCount;
			imageViews.data(),									// const VkImageView*			pAttachments;
			(deUint32)m_renderSize.x(),							// deUint32						width;
			(deUint32)m_renderSize.y(),							// deUint32						height;
			1u,													// deUint32						layers;
		};

		m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
	}

	// Bind shader stages
	{
		bindShaderStage(VK_SHADER_STAGE_VERTEX_BIT, "vert", "main");
		bindShaderStage(VK_SHADER_STAGE_FRAGMENT_BIT, "frag", "main");
	}


	// Create pipeline layout
	{
		const VkPushConstantRange pushConstantRange =
		{
			VK_SHADER_STAGE_FRAGMENT_BIT,		// VkShaderStageFlags	stageFlags
			0,									// deUint32				offset
			sizeof(Vec4)						// deUint32				size
		};

		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;
			1u,													// deUint32							pushConstantRangeCount;
			&pushConstantRange									// const VkPushConstantRange*		pPushConstantRanges;
		};

		m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
	}

	// Create pipeline
	buildPipeline(m_param.premultipliedSrcColor, m_param.premultipliedDstColor);

	// Create command pool
	m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);

	// Create command buffer
	m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
}

BlendOperationAdvancedTestInstance::~BlendOperationAdvancedTestInstance (void)
{
}

tcu::TestStatus BlendOperationAdvancedTestInstance::iterate (void)
{
	const DeviceInterface&	vk					= m_context.getDeviceInterface();
	const VkDevice			vkDevice			= m_context.getDevice();
	const VkQueue			queue				= m_context.getUniversalQueue();
	tcu::TestLog&			log					= m_context.getTestContext().getLog();

	// Log the blend operations to test
	{
		if (m_param.independentBlend)
		{
			for (deUint32 i = 0; (i < m_param.colorAttachmentsCount); i++)
				log << tcu::TestLog::Message << "Color attachment " << i << " uses depth op: "<< de::toLower(getBlendOpStr(m_param.blendOps[i]).toString().substr(3)) << tcu::TestLog::EndMessage;

		}
		else
		{
			log << tcu::TestLog::Message << "All color attachments use depth op: " << de::toLower(getBlendOpStr(m_param.blendOps[0]).toString().substr(3)) << tcu::TestLog::EndMessage;

		}
	}
	prepareCommandBuffer();
	submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());

	if (verifyTestResult() == DE_FALSE)
		return tcu::TestStatus::fail("Image mismatch");

	return tcu::TestStatus::pass("Result images matches references");
}

deBool BlendOperationAdvancedTestInstance::verifyTestResult ()
{
	deBool							compareOk			= DE_TRUE;
	const DeviceInterface&			vk					= m_context.getDeviceInterface();
	const VkDevice					vkDevice			= m_context.getDevice();
	const VkQueue					queue				= m_context.getUniversalQueue();
	const deUint32					queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
	Allocator&						allocator			= m_context.getDefaultAllocator();
	std::vector<tcu::TextureLevel>	referenceImages;

	for (deUint32 colorAtt = 0; colorAtt < m_param.colorAttachmentsCount; colorAtt++)
	{
		tcu::TextureLevel		refImage			(vk::mapVkFormat(m_colorFormat), 32, 32);
		tcu::clear(refImage.getAccess(), clearColorVec4);
		referenceImages.emplace_back(refImage);
	}

	for (deUint32 color = 0; color < DE_LENGTH_OF_ARRAY(srcColors); color++)
	{
		deBool skipColor = DE_FALSE;

		// Check if any color attachment will generate an ill-formed color. If that's the case, skip that color in the verification.
		for (deUint32 colorAtt = 0; colorAtt < m_param.colorAttachmentsCount; colorAtt++)
		{
			Vec4 rectColor = calculateFinalColor(m_param, m_param.blendOps[colorAtt], srcColors[color], dstColors[color]);
			if (m_param.premultipliedDstColor == VK_FALSE)
			{
				if (rectColor.w() > 0.0f)
				{
					rectColor.x() = rectColor.x() / rectColor.w();
					rectColor.y() = rectColor.y() / rectColor.w();
					rectColor.z() = rectColor.z() / rectColor.w();
				}
				else
				{
					// Skip the color check if it is ill-formed.
					if (rectColor != Vec4(0.0f))
					{
						skipColor = DE_TRUE;
						break;
					}
				}
			}
		}

		// Skip ill-formed colors that appears in any color attachment.
		if (skipColor)
			continue;

		// If we reach this point, the final color for all color attachment is not ill-formed.
		for (deUint32 colorAtt = 0; colorAtt < m_param.colorAttachmentsCount; colorAtt++)
		{
			Vec4 rectColor = calculateFinalColor(m_param, m_param.blendOps[colorAtt], srcColors[color], dstColors[color]);
			if (m_param.premultipliedDstColor == VK_FALSE)
			{
				if (rectColor.w() > 0.0f)
				{
					rectColor.x() = rectColor.x() / rectColor.w();
					rectColor.y() = rectColor.y() / rectColor.w();
					rectColor.z() = rectColor.z() / rectColor.w();
				}
				else
				{
					// Ill-formed colors were already skipped
					DE_ASSERT(rectColor == Vec4(0.0f));
				}
			}
			deInt32 x = 0;
			deInt32 y = 0;
			getCoordinates(color, x, y);
			tcu::clear(tcu::getSubregion(referenceImages[colorAtt].getAccess(), x, y, 1u, 1u), rectColor);
		}
	}

	for (deUint32 colorAtt = 0; colorAtt < m_param.colorAttachmentsCount; colorAtt++)
	{
		// Compare image
		de::MovePtr<tcu::TextureLevel> result = vkt::pipeline::readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImages[colorAtt], m_colorFormat, m_renderSize);
		std::ostringstream name;
		name << "Image comparison. Color attachment: "  << colorAtt << ". Depth op: " << de::toLower(getBlendOpStr(m_param.blendOps[colorAtt]).toString().substr(3));

		compareOk = tcu::floatThresholdCompare(m_context.getTestContext().getLog(),
											   "FloatImageCompare",
											   name.str().c_str(),
											   referenceImages[colorAtt].getAccess(),
											   result->getAccess(),
											   Vec4(0.01f, 0.01f, 0.01f, 0.01f),
											   tcu::COMPARE_LOG_RESULT);
#ifdef CTS_USES_VULKANSC
		if (m_context.getTestContext().getCommandLine().isSubProcess())
#endif // CTS_USES_VULKANSC
		{
			if (!compareOk)
				return DE_FALSE;
		}
	}
	return DE_TRUE;
}

class BlendOperationAdvancedTest : public vkt::TestCase
{
public:
							BlendOperationAdvancedTest	(tcu::TestContext&					testContext,
														 const std::string&					name,
														 const std::string&					description,
														 const BlendOperationAdvancedParam	param)
								: vkt::TestCase (testContext, name, description)
								, m_param		(param)
								{ }
	virtual					~BlendOperationAdvancedTest	(void) { }
	virtual void			initPrograms		(SourceCollections&	programCollection) const;
	virtual TestInstance*	createInstance		(Context&				context) const;
	virtual void			checkSupport		(Context& context) const;

protected:
		const BlendOperationAdvancedParam       m_param;
};

void BlendOperationAdvancedTest::checkSupport(Context& context) const
{
	const InstanceInterface&	vki				 = context.getInstanceInterface();

	context.requireDeviceFunctionality("VK_EXT_blend_operation_advanced");

	VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT blendProperties;
	blendProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT;
	blendProperties.pNext = DE_NULL;

	VkPhysicalDeviceProperties2 properties2;
	properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
	properties2.pNext = &blendProperties;
	vki.getPhysicalDeviceProperties2(context.getPhysicalDevice(), &properties2);

	if (!blendProperties.advancedBlendAllOperations)
	{
		for (deUint32 index = 0u; index < m_param.blendOps.size(); index++)
		{
			switch (m_param.blendOps[index])
			{
			case VK_BLEND_OP_MULTIPLY_EXT:
			case VK_BLEND_OP_SCREEN_EXT:
			case VK_BLEND_OP_OVERLAY_EXT:
			case VK_BLEND_OP_DARKEN_EXT:
			case VK_BLEND_OP_LIGHTEN_EXT:
			case VK_BLEND_OP_COLORDODGE_EXT:
			case VK_BLEND_OP_COLORBURN_EXT:
			case VK_BLEND_OP_HARDLIGHT_EXT:
			case VK_BLEND_OP_SOFTLIGHT_EXT:
			case VK_BLEND_OP_DIFFERENCE_EXT:
			case VK_BLEND_OP_EXCLUSION_EXT:
			case VK_BLEND_OP_HSL_HUE_EXT:
			case VK_BLEND_OP_HSL_SATURATION_EXT:
			case VK_BLEND_OP_HSL_COLOR_EXT:
			case VK_BLEND_OP_HSL_LUMINOSITY_EXT:
				break;
			default:
				throw tcu::NotSupportedError("Unsupported all advanced blend operations and unsupported advanced blend operation");
			}
		}
	}

	if (m_param.colorAttachmentsCount > blendProperties.advancedBlendMaxColorAttachments)
	{
		std::ostringstream error;
		error << "Unsupported number of color attachments (" << blendProperties.advancedBlendMaxColorAttachments << " < " << m_param.colorAttachmentsCount;
		throw tcu::NotSupportedError(error.str().c_str());
	}

	if (m_param.overlap != VK_BLEND_OVERLAP_UNCORRELATED_EXT && !blendProperties.advancedBlendCorrelatedOverlap)
	{
		throw tcu::NotSupportedError("Unsupported blend correlated overlap");
	}

	if (m_param.colorAttachmentsCount > 1 && m_param.independentBlend && !blendProperties.advancedBlendIndependentBlend)
	{
		throw tcu::NotSupportedError("Unsupported independent blend");
	}

	if (!m_param.premultipliedSrcColor && !blendProperties.advancedBlendNonPremultipliedSrcColor)
	{
		throw tcu::NotSupportedError("Unsupported non-premultiplied source color");
	}

	if (!m_param.premultipliedDstColor && !blendProperties.advancedBlendNonPremultipliedDstColor)
	{
		throw tcu::NotSupportedError("Unsupported non-premultiplied destination color");
	}

	const VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT blendFeatures = context.getBlendOperationAdvancedFeaturesEXT();
	if (m_param.coherentOperations && !blendFeatures.advancedBlendCoherentOperations)
	{
		throw tcu::NotSupportedError("Unsupported required coherent operations");
	}
}

void BlendOperationAdvancedTest::initPrograms (SourceCollections& programCollection) const
{
	programCollection.glslSources.add("vert") << glu::VertexSource(
				"#version 310 es\n"
				"layout(location = 0) in vec4 position;\n"
				"void main (void)\n"
				"{\n"
				"  gl_Position = position;\n"
				"}\n");

	std::ostringstream fragmentSource;
	fragmentSource << "#version 310 es\n";
	fragmentSource << "layout(push_constant) uniform Color { highp vec4 color; };\n";
	for (deUint32 i = 0; i < m_param.colorAttachmentsCount; i++)
		fragmentSource << "layout(location = "<< i <<") out highp vec4 fragColor" << i <<";\n";
	fragmentSource << "void main (void)\n";
	fragmentSource << "{\n";
	for (deUint32 i = 0; i < m_param.colorAttachmentsCount; i++)
		fragmentSource << "  fragColor" << i <<" = color;\n";
	fragmentSource << "}\n";
	programCollection.glslSources.add("frag") << glu::FragmentSource(fragmentSource.str().c_str());
}

class BlendOperationAdvancedTestCoherentInstance : public vkt::TestInstance
{
public:
								BlendOperationAdvancedTestCoherentInstance		(Context&				context,
																				 const BlendOperationAdvancedParam	param);
	virtual						~BlendOperationAdvancedTestCoherentInstance		(void);
	virtual tcu::TestStatus		iterate									(void);
protected:
			void				prepareRenderPass						(VkFramebuffer framebuffer, VkPipeline pipeline,
																		 VkRenderPass renderpass, deBool secondDraw);
	virtual	void				prepareCommandBuffer					(void);
	virtual	void				buildPipeline							(void);
	virtual	void				bindShaderStage							(VkShaderStageFlagBits					stage,
																		 const char*							sourceName,
																		 const char*							entryName);
	virtual	tcu::TestStatus		verifyTestResult						(void);

protected:
	const BlendOperationAdvancedParam		m_param;
	const tcu::UVec2						m_renderSize;
	const VkFormat							m_colorFormat;
	Move<VkPipelineLayout>					m_pipelineLayout;

	Move<VkBuffer>							m_vertexBuffer;
	de::MovePtr<Allocation>					m_vertexBufferMemory;
	std::vector<Vec4>						m_vertices;

	std::vector<Move<VkRenderPass>>			m_renderPasses;
	Move<VkCommandPool>						m_cmdPool;
	Move<VkCommandBuffer>					m_cmdBuffer;
	Move<VkImage>							m_colorImage;
	Move<VkImageView>						m_colorAttachmentView;
	de::MovePtr<Allocation>					m_colorImageAlloc;
	std::vector<VkImageMemoryBarrier>		m_imageLayoutBarriers;
	std::vector<Move<VkFramebuffer>>		m_framebuffers;
	std::vector<Move<VkPipeline>>			m_pipelines;

	Move<VkShaderModule>					m_shaderModules[2];
	deUint32								m_shaderStageCount;
	VkPipelineShaderStageCreateInfo			m_shaderStageInfo[2];
};

BlendOperationAdvancedTestCoherentInstance::~BlendOperationAdvancedTestCoherentInstance (void)
{
}

void BlendOperationAdvancedTestCoherentInstance::bindShaderStage (VkShaderStageFlagBits	stage,
																 const char*			sourceName,
																 const char*			entryName)
{
	const DeviceInterface&	vk			= m_context.getDeviceInterface();
	const VkDevice			vkDevice	= m_context.getDevice();

	// Create shader module
	deUint32*				code		= (deUint32*)m_context.getBinaryCollection().get(sourceName).getBinary();
	deUint32				codeSize	= (deUint32)m_context.getBinaryCollection().get(sourceName).getSize();

	const VkShaderModuleCreateInfo moduleCreateInfo =
	{
		VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,				// VkStructureType				sType;
		DE_NULL,													// const void*					pNext;
		0u,															// VkShaderModuleCreateFlags	flags;
		codeSize,													// deUintptr					codeSize;
		code,														// const deUint32*				pCode;
	};

	m_shaderModules[m_shaderStageCount] = createShaderModule(vk, vkDevice, &moduleCreateInfo);

	// Prepare shader stage info
	m_shaderStageInfo[m_shaderStageCount].sType					= VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
	m_shaderStageInfo[m_shaderStageCount].pNext					= DE_NULL;
	m_shaderStageInfo[m_shaderStageCount].flags					= 0u;
	m_shaderStageInfo[m_shaderStageCount].stage					= stage;
	m_shaderStageInfo[m_shaderStageCount].module				= *m_shaderModules[m_shaderStageCount];
	m_shaderStageInfo[m_shaderStageCount].pName					= entryName;
	m_shaderStageInfo[m_shaderStageCount].pSpecializationInfo	= DE_NULL;

	m_shaderStageCount++;
}

void BlendOperationAdvancedTestCoherentInstance::buildPipeline ()
{
	const DeviceInterface&		vk					= m_context.getDeviceInterface();
	const VkDevice				vkDevice			= m_context.getDevice();

	// Create pipeline
	const VkVertexInputBindingDescription vertexInputBindingDescription =
	{
		0u,									// deUint32				binding;
		sizeof(Vec4)		,				// deUint32				strideInBytes;
		VK_VERTEX_INPUT_RATE_VERTEX,		// VkVertexInputRate	inputRate;
	};

	const VkVertexInputAttributeDescription vertexInputAttributeDescription =
	{
		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;
		0u,																// VkPipelineVertexInputStateCreateFlags	flags;
		1u,																// deUint32									vertexBindingDescriptionCount;
		&vertexInputBindingDescription,									// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
		1u,																// deUint32									vertexAttributeDescriptionCount;
		&vertexInputAttributeDescription,								// 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;
		VK_FALSE,														// VkBool32									primitiveRestartEnable;
	};

	const VkRect2D		scissor		= makeRect2D(m_renderSize);
	VkViewport			viewport	= makeViewport(m_renderSize);

	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;
		VK_FALSE,														// VkBool32									depthClampEnable;
		VK_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 VkPipelineColorBlendAdvancedStateCreateInfoEXT blendAdvancedStateParams =
	{
		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT,	// VkStructureType		sType;
		DE_NULL,																// const void*			pNext;
		VK_TRUE,																// VkBool32				srcPremultiplied;
		VK_TRUE,																// VkBool32				dstPremultiplied;
		m_param.overlap,														// VkBlendOverlapEXT	blendOverlap;
	};

	std::vector<VkPipelineColorBlendAttachmentState>	colorBlendAttachmentStates;

	// One VkPipelineColorBlendAttachmentState for each pipeline, we only have one color attachment.
	for (deUint32 i = 0; i < 2; i++)
	{
		const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
		{
			VK_TRUE,														// VkBool32									blendEnable;
			VK_BLEND_FACTOR_ONE,											// VkBlendFactor							srcColorBlendFactor;
			VK_BLEND_FACTOR_ONE,											// VkBlendFactor							dstColorBlendFactor;
			m_param.blendOps[i],											// VkBlendOp								colorBlendOp;
			VK_BLEND_FACTOR_ONE,											// VkBlendFactor							srcAlphaBlendFactor;
			VK_BLEND_FACTOR_ONE,											// VkBlendFactor							dstAlphaBlendFactor;
			m_param.blendOps[i],											// VkBlendOp								alphaBlendOp;
			VK_COLOR_COMPONENT_R_BIT |
			VK_COLOR_COMPONENT_G_BIT |
			VK_COLOR_COMPONENT_B_BIT |
			VK_COLOR_COMPONENT_A_BIT										// VkColorComponentFlags					colorWriteMask;
		};
		colorBlendAttachmentStates.emplace_back(colorBlendAttachmentState);
	}

	std::vector<VkPipelineColorBlendStateCreateInfo> colorBlendStateParams;
	VkPipelineColorBlendStateCreateInfo colorBlendStateParam =
	{
		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
		&blendAdvancedStateParams,									// const void*									pNext;
		0u,															// VkPipelineColorBlendStateCreateFlags			flags;
		VK_FALSE,													// VkBool32										logicOpEnable;
		VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
		1u,															// deUint32										attachmentCount;
		&colorBlendAttachmentStates[0],								// const VkPipelineColorBlendAttachmentState*	pAttachments;
		{ 0.0f, 0.0f, 0.0f, 0.0f },									// float										blendConst[4];
	};
	colorBlendStateParams.emplace_back(colorBlendStateParam);

	// For the second pipeline, the blendOp changed.
	colorBlendStateParam.pAttachments = &colorBlendAttachmentStates[1];
	colorBlendStateParams.emplace_back(colorBlendStateParam);

	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;
		VK_FALSE,													// VkBool32										sampleShadingEnable;
		0.0f,														// float										minSampleShading;
		DE_NULL,													// const VkSampleMask*							pSampleMask;
		VK_FALSE,													// VkBool32										alphaToCoverageEnable;
		VK_FALSE,													// VkBool32										alphaToOneEnable;
	};

	VkPipelineDepthStencilStateCreateInfo depthStencilStateParams =
	{
		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType								sType;
		DE_NULL,													// const void*									pNext;
		0u,															// VkPipelineDepthStencilStateCreateFlags		flags;
		VK_FALSE,													// VkBool32										depthTestEnable;
		VK_FALSE,													// VkBool32										depthWriteEnable;
		VK_COMPARE_OP_NEVER,										// VkCompareOp									depthCompareOp;
		VK_FALSE,													// VkBool32										depthBoundsTestEnable;
		VK_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;
		},
		0.0f,														// float										minDepthBounds;
		1.0f,														// float										maxDepthBounds;
	};

	const VkDynamicState dynamicState = VK_DYNAMIC_STATE_SCISSOR;
	const VkPipelineDynamicStateCreateInfo dynamicStateParams =
	{
		VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,	// VkStructureType						sType;
		DE_NULL,												// const void*							pNext;
		0u,														// VkPipelineDynamicStateCreateFlags	flags;
		1u,														// uint32_t								dynamicStateCount;
		&dynamicState											// const VkDynamicState*				pDynamicStates;
	};

	VkGraphicsPipelineCreateInfo graphicsPipelineParams =
	{
		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,	// VkStructureType										sType;
		DE_NULL,											// const void*											pNext;
		0u,													// VkPipelineCreateFlags								flags;
		m_shaderStageCount,									// deUint32												stageCount;
		m_shaderStageInfo,									// const VkPipelineShaderStageCreateInfo*				pStages;
		&vertexInputStateParams,							// const VkPipelineVertexInputStateCreateInfo*			pVertexInputState;
		&inputAssemblyStateParams,							// const VkPipelineInputAssemblyStateCreateInfo*		pInputAssemblyState;
		DE_NULL,											// const VkPipelineTessellationStateCreateInfo*			pTessellationState;
		&viewportStateParams,								// const VkPipelineViewportStateCreateInfo*				pViewportState;
		&rasterStateParams,									// const VkPipelineRasterizationStateCreateInfo*		pRasterState;
		&multisampleStateParams,							// const VkPipelineMultisampleStateCreateInfo*			pMultisampleState;
		&depthStencilStateParams,							// const VkPipelineDepthStencilStateCreateInfo*			pDepthStencilState;
		&colorBlendStateParams[0],							// const VkPipelineColorBlendStateCreateInfo*			pColorBlendState;
		&dynamicStateParams,								// const VkPipelineDynamicStateCreateInfo*				pDynamicState;
		*m_pipelineLayout,									// VkPipelineLayout										layout;
		m_renderPasses[0].get(),							// VkRenderPass											renderPass;
		0u,													// deUint32												subpass;
		DE_NULL,											// VkPipeline											basePipelineHandle;
		0u,													// deInt32												basePipelineIndex;
	};

	// Create first pipeline
	m_pipelines.emplace_back(createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams));
	// Create second pipeline
	graphicsPipelineParams.pColorBlendState = &colorBlendStateParams[1];
	graphicsPipelineParams.renderPass = m_renderPasses[1].get();
	m_pipelines.emplace_back(createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams));
}

void BlendOperationAdvancedTestCoherentInstance::prepareRenderPass (VkFramebuffer framebuffer, VkPipeline pipeline, VkRenderPass renderpass, deBool secondDraw)
{
	const DeviceInterface&	vk				 = m_context.getDeviceInterface();

	VkClearValue	attachmentClearValue = makeClearValueColor(clearColorVec4);

	beginRenderPass(vk, *m_cmdBuffer, renderpass, framebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()),
					(secondDraw ? 0u : 1u),
					(secondDraw ? DE_NULL : &attachmentClearValue));

	vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
	VkDeviceSize offsets = 0u;
	vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &m_vertexBuffer.get(), &offsets);

	// There are two different renderpasses, each of them draw
	// one half of the colors.
	deBool skippedColors = 0u;
	for (deUint32 color = 0; color < DE_LENGTH_OF_ARRAY(srcColors)/2; color++)
	{
		// Skip ill-formed colors when we have non-premultiplied destination colors.
		if (m_param.premultipliedDstColor == VK_FALSE)
		{
			deBool skipColor = false;
			for (deUint32 i = 0; i < m_param.colorAttachmentsCount; i++)
			{
				Vec4 calculatedColor = calculateFinalColor(m_param, m_param.blendOps[i], srcColors[color], dstColors[color]);
				if (calculatedColor.w() <= 0.0f && calculatedColor != Vec4(0.0f))
				{
					// Skip ill-formed colors, because the spec says the result is undefined.
					skippedColors++;
					skipColor = true;
					break;
				}
			}
			if (skipColor)
				continue;
		}
		deInt32 x = 0;
		deInt32 y = 0;
		getCoordinates(color, x, y);

		deUint32 index = secondDraw ? (color + DE_LENGTH_OF_ARRAY(srcColors) / 2) : color;

		// Set source color as push constant
		vk.cmdPushConstants(*m_cmdBuffer, *m_pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(Vec4), &srcColors[index]);
		VkRect2D scissor = makeRect2D(x, y, 1u, 1u);
		vk.cmdSetScissor(*m_cmdBuffer, 0u, 1u, &scissor);

		// To set destination color, we do clear attachment restricting the area to the respective pixel of each color attachment.
		// Only clear in the first draw, for the second draw the destination color is the result of the first draw's blend.
		if (secondDraw == DE_FALSE)
		{
			std::vector<VkClearAttachment> attachments;
			VkClearValue clearValue = vk::makeClearValueColorVec4(dstColors[index]);

			const VkClearAttachment	attachment	=
			{
				VK_IMAGE_ASPECT_COLOR_BIT,
				0u,
				clearValue
			};

			const VkClearRect rect =
			{
				scissor,
				0u,
				1u
			};
			vk.cmdClearAttachments(*m_cmdBuffer, 1u, &attachment, 1u, &rect);
		}

		// Draw
		vk.cmdDraw(*m_cmdBuffer, (deUint32)m_vertices.size(), 1u, 0u, 0u);
	}

	// If we break this assert, then we are not testing anything in this test.
	DE_ASSERT(skippedColors < (DE_LENGTH_OF_ARRAY(srcColors) / 2));

	// Log number of skipped colors
	if (skippedColors != 0u)
	{
		tcu::TestLog& log = m_context.getTestContext().getLog();
		log << tcu::TestLog::Message << "Skipped " << skippedColors << " out of " << (DE_LENGTH_OF_ARRAY(srcColors) / 2) << " color cases due to ill-formed colors" << tcu::TestLog::EndMessage;
	}
	endRenderPass(vk, *m_cmdBuffer);
}

void BlendOperationAdvancedTestCoherentInstance::prepareCommandBuffer ()
{
	const DeviceInterface&	vk				 = m_context.getDeviceInterface();

	beginCommandBuffer(vk, *m_cmdBuffer, 0u);

	vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, (VkDependencyFlags)0,
						  0u, DE_NULL, 0u, DE_NULL, (deUint32)m_imageLayoutBarriers.size(), m_imageLayoutBarriers.data());

	prepareRenderPass(m_framebuffers[0].get(), m_pipelines[0].get(), m_renderPasses[0].get(), false);

	if (m_param.coherentOperations == DE_FALSE)
	{
		const VkImageMemoryBarrier colorImageBarrier =
		{
			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,					// VkStructureType			sType;
			DE_NULL,												// const void*				pNext;
			(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
			 VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT),	// VkAccessFlags			srcAccessMask;
			(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
			 VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT),	// VkAccessFlags			dstAccessMask;
			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,				// VkImageLayout			oldLayout;
			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,				// VkImageLayout			newLayout;
			VK_QUEUE_FAMILY_IGNORED,								// deUint32					srcQueueFamilyIndex;
			VK_QUEUE_FAMILY_IGNORED,								// deUint32					dstQueueFamilyIndex;
			*m_colorImage,											// VkImage					image;
			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },			// VkImageSubresourceRange	subresourceRange;
		};
		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
							  VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, (VkDependencyFlags)0,
							  0u, DE_NULL, 0u, DE_NULL, 1u, &colorImageBarrier);
	}

	prepareRenderPass(m_framebuffers[1].get(), m_pipelines[1].get(), m_renderPasses[1].get(), true);

	endCommandBuffer(vk, *m_cmdBuffer);
}

BlendOperationAdvancedTestCoherentInstance::BlendOperationAdvancedTestCoherentInstance	(Context&							context,
																						 const BlendOperationAdvancedParam	param)
	: TestInstance			(context)
	, m_param				(param)
	, m_renderSize			(tcu::UVec2(widthArea, heightArea))
	, m_colorFormat			(VK_FORMAT_R16G16B16A16_SFLOAT)
	, m_shaderStageCount	(0)
{
	const DeviceInterface&		vk				 = m_context.getDeviceInterface();
	const VkDevice				vkDevice		 = m_context.getDevice();
	const deUint32				queueFamilyIndex = context.getUniversalQueueFamilyIndex();

	// Create vertex buffer
	{
		m_vertices		= createPoints();
		DE_ASSERT((deUint32)m_vertices.size() == 6);

		m_vertexBuffer	= createBufferAndBindMemory(m_context, m_vertices.size() * sizeof(Vec4), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, &m_vertexBufferMemory);
		// Load vertices into vertex buffer
		deMemcpy(m_vertexBufferMemory->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vec4));
		flushAlloc(vk, vkDevice, *m_vertexBufferMemory);
	}

	// Create render passes
	m_renderPasses.emplace_back(makeTestRenderPass(param, vk, vkDevice, m_colorFormat, VK_ATTACHMENT_LOAD_OP_CLEAR));
	m_renderPasses.emplace_back(makeTestRenderPass(param, vk, vkDevice, m_colorFormat, VK_ATTACHMENT_LOAD_OP_LOAD));

	const VkComponentMapping	componentMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};

	// Create color image
	m_colorImage	= createImage2DAndBindMemory(m_context,
												 m_colorFormat,
												 m_renderSize.x(),
												 m_renderSize.y(),
												 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
												 VK_SAMPLE_COUNT_1_BIT,
												 &m_colorImageAlloc);
	// Set up image layout transition barriers
	{
		VkImageMemoryBarrier colorImageBarrier =
		{
			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,					// VkStructureType			sType;
			DE_NULL,												// const void*				pNext;
			0u,														// VkAccessFlags			srcAccessMask;
			(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
			 VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT),	// VkAccessFlags			dstAccessMask;
			VK_IMAGE_LAYOUT_UNDEFINED,								// VkImageLayout			oldLayout;
			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,				// VkImageLayout			newLayout;
			VK_QUEUE_FAMILY_IGNORED,								// deUint32					srcQueueFamilyIndex;
			VK_QUEUE_FAMILY_IGNORED,								// deUint32					dstQueueFamilyIndex;
			*m_colorImage,											// VkImage					image;
			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },			// VkImageSubresourceRange	subresourceRange;
		};

		m_imageLayoutBarriers.emplace_back(colorImageBarrier);
	}

	// Create color attachment view
	{
		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 framebuffers
	{
		VkFramebufferCreateInfo framebufferParams =
		{
			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,			// VkStructureType				sType;
			DE_NULL,											// const void*					pNext;
			0u,													// VkFramebufferCreateFlags		flags;
			m_renderPasses[0].get(),							// 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_framebuffers.emplace_back(createFramebuffer(vk, vkDevice, &framebufferParams));
		framebufferParams.renderPass = m_renderPasses[1].get();
		m_framebuffers.emplace_back(createFramebuffer(vk, vkDevice, &framebufferParams));
	}

	// Bind shader stages
	{
		bindShaderStage(VK_SHADER_STAGE_VERTEX_BIT, "vert", "main");
		bindShaderStage(VK_SHADER_STAGE_FRAGMENT_BIT, "frag", "main");
	}


	// Create pipeline layout
	{
		const VkPushConstantRange pushConstantRange =
		{
			VK_SHADER_STAGE_FRAGMENT_BIT,		// VkShaderStageFlags	stageFlags
			0,									// deUint32				offset
			sizeof(Vec4)						// deUint32				size
		};

		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;
			1u,													// deUint32							pushConstantRangeCount;
			&pushConstantRange									// const VkPushConstantRange*		pPushConstantRanges;
		};

		m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
	}

	// Create pipeline
	buildPipeline();

	// Create command pool
	m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);

	// Create command buffer
	m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
}

tcu::TestStatus BlendOperationAdvancedTestCoherentInstance::iterate (void)
{
	const DeviceInterface&	vk					= m_context.getDeviceInterface();
	const VkDevice			vkDevice			= m_context.getDevice();
	const VkQueue			queue				= m_context.getUniversalQueue();
	tcu::TestLog&			log					= m_context.getTestContext().getLog();

	// Log the blend operations to test
	{
		DE_ASSERT(m_param.blendOps.size() == 2u);
		log << tcu::TestLog::Message << "First depth op: " << de::toLower(getBlendOpStr(m_param.blendOps[0]).toString().substr(3)) << tcu::TestLog::EndMessage;
		log << tcu::TestLog::Message << "Second depth op: " << de::toLower(getBlendOpStr(m_param.blendOps[1]).toString().substr(3)) << tcu::TestLog::EndMessage;

	}

	prepareCommandBuffer();

	submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
	return verifyTestResult();
}

tcu::TestStatus BlendOperationAdvancedTestCoherentInstance::verifyTestResult (void)
{
	deBool					compareOk			= DE_TRUE;
	const DeviceInterface&	vk					= m_context.getDeviceInterface();
	const VkDevice			vkDevice			= m_context.getDevice();
	const VkQueue			queue				= m_context.getUniversalQueue();
	const deUint32			queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
	Allocator&				allocator			= m_context.getDefaultAllocator();
	tcu::TextureLevel		refImage			(vk::mapVkFormat(m_colorFormat), 32, 32);

	tcu::clear(refImage.getAccess(), clearColorVec4);

	// Generate reference image
	for (deUint32 color = 0; color < DE_LENGTH_OF_ARRAY(srcColors)/2; color++)
	{
		deUint32 secondDrawColorIndex = color + DE_LENGTH_OF_ARRAY(srcColors)/2;
		// Calculate first draw final color
		Vec4 rectColorTmp = calculateFinalColor(m_param, m_param.blendOps[0], srcColors[color], dstColors[color]);

		if (m_param.premultipliedDstColor == VK_FALSE)
		{
			if (rectColorTmp.w() > 0.0f)
			{
				rectColorTmp.x() = rectColorTmp.x() / rectColorTmp.w();
				rectColorTmp.y() = rectColorTmp.y() / rectColorTmp.w();
				rectColorTmp.z() = rectColorTmp.z() / rectColorTmp.w();
			}
			else
			{
				// Skip the color check if it is ill-formed.
				if (rectColorTmp != Vec4(0.0f))
					continue;
			}
		}
		// Calculate second draw final color
		Vec4 rectColor = calculateFinalColor(m_param, m_param.blendOps[1], srcColors[secondDrawColorIndex], rectColorTmp);
		if (m_param.premultipliedDstColor == VK_FALSE)
		{
			if (rectColor.w() > 0.0f)
			{
				rectColor.x() = rectColor.x() / rectColor.w();
				rectColor.y() = rectColor.y() / rectColor.w();
				rectColor.z() = rectColor.z() / rectColor.w();
			}
			else
			{
				// Skip the color check if it is ill-formed.
				if (rectColor != Vec4(0.0f))
					continue;
			}
		}

		deInt32 x = 0;
		deInt32 y = 0;
		getCoordinates(color, x, y);
		tcu::clear(tcu::getSubregion(refImage.getAccess(), x, y, 1u, 1u), rectColor);
	}

	de::MovePtr<tcu::TextureLevel> result = vkt::pipeline::readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize);
	std::ostringstream name;
	name << "Image comparison. Depth ops: " << de::toLower(getBlendOpStr(m_param.blendOps[0]).toString().substr(3)) << " and " << de::toLower(getBlendOpStr(m_param.blendOps[1]).toString().substr(3));
	compareOk = tcu::floatThresholdCompare(m_context.getTestContext().getLog(),
										   "FloatImageCompare",
										   name.str().c_str(),
										   refImage.getAccess(),
										   result->getAccess(),
										   Vec4(0.01f, 0.01f, 0.01f, 0.01f),
										   tcu::COMPARE_LOG_RESULT);
	if (!compareOk)
		return tcu::TestStatus::fail("Image mismatch");

	return tcu::TestStatus::pass("Result images matches references");
}

TestInstance* BlendOperationAdvancedTest::createInstance (Context& context) const
{
	if (m_param.testMode == TEST_MODE_GENERIC)
		return new BlendOperationAdvancedTestInstance(context, m_param);
	else
		return new BlendOperationAdvancedTestCoherentInstance(context, m_param);
}

} // anonymous

tcu::TestCaseGroup* createBlendOperationAdvancedTests (tcu::TestContext& testCtx)
{
	enum nonpremultiplyEnum
	{
		PREMULTIPLY_SRC = 1u,
		PREMULTIPLY_DST = 2u
	};
	deUint32	premultiplyModes[] = { 0u, PREMULTIPLY_SRC, PREMULTIPLY_DST, PREMULTIPLY_SRC | PREMULTIPLY_DST };
	deUint32	colorAttachmentCounts[] = { 1u, 2u, 4u, 8u, 16u };
	deBool		coherentOps[] = { DE_FALSE, DE_TRUE };
	VkBlendOp	blendOps[] =
	{
		VK_BLEND_OP_ZERO_EXT, VK_BLEND_OP_SRC_EXT, VK_BLEND_OP_DST_EXT,	VK_BLEND_OP_SRC_OVER_EXT, VK_BLEND_OP_DST_OVER_EXT,
		VK_BLEND_OP_SRC_IN_EXT, VK_BLEND_OP_DST_IN_EXT, VK_BLEND_OP_SRC_OUT_EXT, VK_BLEND_OP_DST_OUT_EXT, VK_BLEND_OP_SRC_ATOP_EXT,
		VK_BLEND_OP_DST_ATOP_EXT, VK_BLEND_OP_XOR_EXT, VK_BLEND_OP_MULTIPLY_EXT, VK_BLEND_OP_SCREEN_EXT, VK_BLEND_OP_OVERLAY_EXT,
		VK_BLEND_OP_DARKEN_EXT, VK_BLEND_OP_LIGHTEN_EXT, VK_BLEND_OP_COLORDODGE_EXT, VK_BLEND_OP_COLORBURN_EXT, VK_BLEND_OP_HARDLIGHT_EXT,
		VK_BLEND_OP_SOFTLIGHT_EXT, VK_BLEND_OP_DIFFERENCE_EXT, VK_BLEND_OP_EXCLUSION_EXT, VK_BLEND_OP_INVERT_EXT, VK_BLEND_OP_INVERT_RGB_EXT,
		VK_BLEND_OP_LINEARDODGE_EXT, VK_BLEND_OP_LINEARBURN_EXT, VK_BLEND_OP_VIVIDLIGHT_EXT, VK_BLEND_OP_LINEARLIGHT_EXT, VK_BLEND_OP_PINLIGHT_EXT,
		VK_BLEND_OP_HARDMIX_EXT, VK_BLEND_OP_HSL_HUE_EXT, VK_BLEND_OP_HSL_SATURATION_EXT, VK_BLEND_OP_HSL_COLOR_EXT, VK_BLEND_OP_HSL_LUMINOSITY_EXT,
		VK_BLEND_OP_PLUS_EXT, VK_BLEND_OP_PLUS_CLAMPED_EXT, VK_BLEND_OP_PLUS_CLAMPED_ALPHA_EXT, VK_BLEND_OP_PLUS_DARKER_EXT, VK_BLEND_OP_MINUS_EXT,
		VK_BLEND_OP_MINUS_CLAMPED_EXT, VK_BLEND_OP_CONTRAST_EXT, VK_BLEND_OP_INVERT_OVG_EXT, VK_BLEND_OP_RED_EXT, VK_BLEND_OP_GREEN_EXT, VK_BLEND_OP_BLUE_EXT,
	};

	de::MovePtr<tcu::TestCaseGroup> tests (new tcu::TestCaseGroup(testCtx, "blend_operation_advanced", "VK_EXT_blend_operation_advanced tests"));
	de::Random						rnd				(deStringHash(tests->getName()));

	de::MovePtr<tcu::TestCaseGroup> opsTests (new tcu::TestCaseGroup(testCtx, "ops", "Test each blend operation advance op"));


	for (deUint32 colorAttachmentCount = 0u; colorAttachmentCount < DE_LENGTH_OF_ARRAY(colorAttachmentCounts); colorAttachmentCount++)
	{
		for (deUint32 overlap = 0; overlap <= VK_BLEND_OVERLAP_CONJOINT_EXT; overlap++)
		{
			for (deUint32 premultiply = 0u; premultiply < DE_LENGTH_OF_ARRAY(premultiplyModes); premultiply++)
			{
				deUint32 testNumber = 0u;
				for (deUint64 blendOp = 0u; blendOp < DE_LENGTH_OF_ARRAY(blendOps); blendOp++)
				{
					deBool isAdditionalRGBBlendOp = blendOps[blendOp] >= VK_BLEND_OP_PLUS_EXT && blendOps[blendOp] < VK_BLEND_OP_MAX_ENUM;

					// Additional RGB Blend operations are not affected by the blend overlap modes
					if (isAdditionalRGBBlendOp && overlap != VK_BLEND_OVERLAP_UNCORRELATED_EXT)
						continue;

					BlendOperationAdvancedParam testParams;
					testParams.testMode					= TEST_MODE_GENERIC;
					testParams.overlap					= (VkBlendOverlapEXT) overlap;
					testParams.coherentOperations		= DE_FALSE;
					testParams.colorAttachmentsCount	= colorAttachmentCounts[colorAttachmentCount];
					testParams.independentBlend			= DE_FALSE;
					testParams.premultipliedSrcColor	= (premultiplyModes[premultiply] & PREMULTIPLY_SRC) ? VK_TRUE : VK_FALSE;
					testParams.premultipliedDstColor	= (premultiplyModes[premultiply] & PREMULTIPLY_DST) ? VK_TRUE : VK_FALSE;
					testParams.testNumber				= testNumber++;

					for (deUint32 numColorAtt = 0; numColorAtt < colorAttachmentCounts[colorAttachmentCount]; numColorAtt++)
						testParams.blendOps.push_back(blendOps[blendOp]);
					opsTests->addChild(newTestCase<BlendOperationAdvancedTest>(testCtx, testParams));
				}
			}
		}
	}
	tests->addChild(opsTests.release());

	// Independent Blend Tests: test more than one color attachment.
	de::MovePtr<tcu::TestCaseGroup> independentTests (new tcu::TestCaseGroup(testCtx, "independent", "Test independent blend feature"));
	deUint32 testNumber = 0u;

	for (deUint32 colorAttachmentCount = 1u; colorAttachmentCount < DE_LENGTH_OF_ARRAY(colorAttachmentCounts); colorAttachmentCount++)
	{
		BlendOperationAdvancedParam testParams;
		testParams.testMode					= TEST_MODE_GENERIC;
		testParams.overlap					= VK_BLEND_OVERLAP_UNCORRELATED_EXT;
		testParams.coherentOperations		= DE_FALSE;
		testParams.colorAttachmentsCount	= colorAttachmentCounts[colorAttachmentCount];
		testParams.independentBlend			= DE_TRUE;
		testParams.premultipliedSrcColor	= VK_TRUE;
		testParams.premultipliedDstColor	= VK_TRUE;
		testParams.testNumber				= testNumber++;

		for (deUint32 numColorAtt = 0; numColorAtt < colorAttachmentCounts[colorAttachmentCount]; numColorAtt++)
		{
			deUint32 i = de::randomScalar<deUint32>(rnd, 0, DE_LENGTH_OF_ARRAY(blendOps) - 1);
			testParams.blendOps.push_back(blendOps[i]);
		}
		independentTests->addChild(newTestCase<BlendOperationAdvancedTest>(testCtx, testParams));
	}

	tests->addChild(independentTests.release());

	// Coherent tests, do two consecutive advanced blending operations on the same color attachment.
	de::MovePtr<tcu::TestCaseGroup> coherentTests (new tcu::TestCaseGroup(testCtx, "coherent", "Test coherent memory"));
	testNumber = 0u;

	for (deUint32 coherent = 0u; coherent < DE_LENGTH_OF_ARRAY(coherentOps); coherent++)
	{
		BlendOperationAdvancedParam testParams;
		testParams.testMode					= TEST_MODE_COHERENT;
		testParams.overlap					= VK_BLEND_OVERLAP_UNCORRELATED_EXT;
		testParams.coherentOperations		= coherentOps[coherent];
		testParams.colorAttachmentsCount	= 1u;
		testParams.independentBlend			= DE_FALSE;
		testParams.premultipliedSrcColor	= VK_TRUE;
		testParams.premultipliedDstColor	= VK_TRUE;
		testParams.testNumber				= testNumber++;

		// We do two consecutive advanced blending operations
		deUint32 i = de::randomScalar<deUint32>(rnd, 0, DE_LENGTH_OF_ARRAY(blendOps) - 1);
		testParams.blendOps.push_back(blendOps[i]);
		i = de::randomScalar<deUint32>(rnd, 0, DE_LENGTH_OF_ARRAY(blendOps) - 1);
		testParams.blendOps.push_back(blendOps[i]);

		coherentTests->addChild(newTestCase<BlendOperationAdvancedTest>(testCtx, testParams));
	}
	tests->addChild(coherentTests.release());


	return tests.release();
}

} // pipeline

} // vkt
