Add support for Advanced blend extension to vulkan.
Currently we only support coherent advanced blends
Bug: skia:
Change-Id: I3d0d7d19313dc55aed57c79585c0ee870f6981a7
Reviewed-on: https://skia-review.googlesource.com/145888
Commit-Queue: Greg Daniel <egdaniel@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/vk/GrVkCaps.cpp b/src/gpu/vk/GrVkCaps.cpp
index 7f67f7c..28440b1 100644
--- a/src/gpu/vk/GrVkCaps.cpp
+++ b/src/gpu/vk/GrVkCaps.cpp
@@ -239,7 +239,7 @@
fSupportsMaintenance3 = true;
}
- this->initGrCaps(properties, memoryProperties, features);
+ this->initGrCaps(vkInterface, physDev, properties, memoryProperties, features, extensions);
this->initShaderCaps(properties, features);
if (!contextOptions.fDisableDriverCorrectnessWorkarounds) {
@@ -344,9 +344,33 @@
return 64;
}
-void GrVkCaps::initGrCaps(const VkPhysicalDeviceProperties& properties,
+template<typename T> T* get_extension_feature_struct(const VkPhysicalDeviceFeatures2& features,
+ VkStructureType type) {
+ // All Vulkan structs that could be part of the features chain will start with the
+ // structure type followed by the pNext pointer. We cast to the CommonVulkanHeader
+ // so we can get access to the pNext for the next struct.
+ struct CommonVulkanHeader {
+ VkStructureType sType;
+ void* pNext;
+ };
+
+ void* pNext = features.pNext;
+ while (pNext) {
+ CommonVulkanHeader* header = static_cast<CommonVulkanHeader*>(pNext);
+ if (header->sType == type) {
+ return static_cast<T*>(pNext);
+ }
+ pNext = header->pNext;
+ }
+ return nullptr;
+}
+
+void GrVkCaps::initGrCaps(const GrVkInterface* vkInterface,
+ VkPhysicalDevice physDev,
+ const VkPhysicalDeviceProperties& properties,
const VkPhysicalDeviceMemoryProperties& memoryProperties,
- const VkPhysicalDeviceFeatures2& features) {
+ const VkPhysicalDeviceFeatures2& features,
+ const GrVkExtensions& extensions) {
// So GPUs, like AMD, are reporting MAX_INT support vertex attributes. In general, there is no
// need for us ever to support that amount, and it makes tests which tests all the vertex
// attribs timeout looping over that many. For now, we'll cap this at 64 max and can raise it if
@@ -376,6 +400,37 @@
fOversizedStencilSupport = true;
fSampleShadingSupport = features.features.sampleRateShading;
+
+ if (extensions.hasExtension(VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME, 2) &&
+ this->supportsPhysicalDeviceProperties2()) {
+
+ VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT blendProps;
+ blendProps.sType =
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT;
+ blendProps.pNext = nullptr;
+
+ VkPhysicalDeviceProperties2 props;
+ props.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
+ props.pNext = &blendProps;
+
+ GR_VK_CALL(vkInterface, GetPhysicalDeviceProperties2(physDev, &props));
+
+ if (blendProps.advancedBlendAllOperations == VK_TRUE) {
+ fShaderCaps->fAdvBlendEqInteraction = GrShaderCaps::kAutomatic_AdvBlendEqInteraction;
+
+ auto blendFeatures =
+ get_extension_feature_struct<VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT>(
+ features,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT);
+ if (blendFeatures && blendFeatures->advancedBlendCoherentOperations == VK_TRUE) {
+ fBlendEquationSupport = kAdvancedCoherent_BlendEquationSupport;
+ } else {
+ // TODO: Currently non coherent blends are not supported in our vulkan backend. They
+ // require us to support self dependencies in our render passes.
+ // fBlendEquationSupport = kAdvanced_BlendEquationSupport;
+ }
+ }
+ }
}
void GrVkCaps::initShaderCaps(const VkPhysicalDeviceProperties& properties,
diff --git a/src/gpu/vk/GrVkCaps.h b/src/gpu/vk/GrVkCaps.h
index d780adb..b3037bc 100644
--- a/src/gpu/vk/GrVkCaps.h
+++ b/src/gpu/vk/GrVkCaps.h
@@ -159,9 +159,12 @@
void init(const GrContextOptions& contextOptions, const GrVkInterface* vkInterface,
VkPhysicalDevice device, const VkPhysicalDeviceFeatures2&, const GrVkExtensions&);
- void initGrCaps(const VkPhysicalDeviceProperties&,
+ void initGrCaps(const GrVkInterface* vkInterface,
+ VkPhysicalDevice physDev,
+ const VkPhysicalDeviceProperties&,
const VkPhysicalDeviceMemoryProperties&,
- const VkPhysicalDeviceFeatures2&);
+ const VkPhysicalDeviceFeatures2&,
+ const GrVkExtensions&);
void initShaderCaps(const VkPhysicalDeviceProperties&, const VkPhysicalDeviceFeatures2&);
#ifdef GR_TEST_UTILS
diff --git a/src/gpu/vk/GrVkPipeline.cpp b/src/gpu/vk/GrVkPipeline.cpp
index 60e7f43..c85dcd7 100644
--- a/src/gpu/vk/GrVkPipeline.cpp
+++ b/src/gpu/vk/GrVkPipeline.cpp
@@ -343,14 +343,47 @@
static VkBlendOp blend_equation_to_vk_blend_op(GrBlendEquation equation) {
static const VkBlendOp gTable[] = {
- VK_BLEND_OP_ADD, // kAdd_GrBlendEquation
- VK_BLEND_OP_SUBTRACT, // kSubtract_GrBlendEquation
- VK_BLEND_OP_REVERSE_SUBTRACT, // kReverseSubtract_GrBlendEquation
+ // Basic blend ops
+ VK_BLEND_OP_ADD,
+ VK_BLEND_OP_SUBTRACT,
+ VK_BLEND_OP_REVERSE_SUBTRACT,
+
+ // Advanced blend ops
+ 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_MULTIPLY_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
};
- GR_STATIC_ASSERT(SK_ARRAY_COUNT(gTable) == kFirstAdvancedGrBlendEquation);
GR_STATIC_ASSERT(0 == kAdd_GrBlendEquation);
GR_STATIC_ASSERT(1 == kSubtract_GrBlendEquation);
GR_STATIC_ASSERT(2 == kReverseSubtract_GrBlendEquation);
+ GR_STATIC_ASSERT(3 == kScreen_GrBlendEquation);
+ GR_STATIC_ASSERT(4 == kOverlay_GrBlendEquation);
+ GR_STATIC_ASSERT(5 == kDarken_GrBlendEquation);
+ GR_STATIC_ASSERT(6 == kLighten_GrBlendEquation);
+ GR_STATIC_ASSERT(7 == kColorDodge_GrBlendEquation);
+ GR_STATIC_ASSERT(8 == kColorBurn_GrBlendEquation);
+ GR_STATIC_ASSERT(9 == kHardLight_GrBlendEquation);
+ GR_STATIC_ASSERT(10 == kSoftLight_GrBlendEquation);
+ GR_STATIC_ASSERT(11 == kDifference_GrBlendEquation);
+ GR_STATIC_ASSERT(12 == kExclusion_GrBlendEquation);
+ GR_STATIC_ASSERT(13 == kMultiply_GrBlendEquation);
+ GR_STATIC_ASSERT(14 == kHSLHue_GrBlendEquation);
+ GR_STATIC_ASSERT(15 == kHSLSaturation_GrBlendEquation);
+ GR_STATIC_ASSERT(16 == kHSLColor_GrBlendEquation);
+ GR_STATIC_ASSERT(17 == kHSLLuminosity_GrBlendEquation);
+ GR_STATIC_ASSERT(SK_ARRAY_COUNT(gTable) == kGrBlendEquationCnt);
SkASSERT((unsigned)equation < kGrBlendCoeffCnt);
return gTable[equation];