Implement multisample "disable" in Vulkan

Emulates multisample disable by colocating all samples at pixel
center. Multisample disable will be required in order for us to
integrate mixed samples.

Change-Id: I52b67e22c979584b5d001e737a08eef07bd7ffe2
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/253282
Commit-Queue: Chris Dalton <csmartdalton@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
This commit is contained in:
Chris Dalton 2019-11-07 12:43:13 -07:00 committed by Skia Commit-Bot
parent 52591f6880
commit b204e4c3d3
7 changed files with 56 additions and 44 deletions

View File

@ -99,7 +99,15 @@ GrPipeline::GrPipeline(GrScissorTest scissorTest, sk_sp<const GrXferProcessor> x
}
}
uint32_t GrPipeline::getBlendInfoKey() const {
void GrPipeline::genKey(GrProcessorKeyBuilder* b, const GrCaps& caps) const {
// kSnapVerticesToPixelCenters is implemented in a shader.
InputFlags ignoredFlags = InputFlags::kSnapVerticesToPixelCenters;
if (!caps.multisampleDisableSupport()) {
// Ganesh will omit kHWAntialias regardless multisampleDisableSupport.
ignoredFlags |= InputFlags::kHWAntialias;
}
b->add32((uint32_t)fFlags & ~(uint32_t)ignoredFlags);
const GrXferProcessor::BlendInfo& blendInfo = this->getXferProcessor().getBlendInfo();
static const uint32_t kBlendWriteShift = 1;
@ -107,10 +115,10 @@ uint32_t GrPipeline::getBlendInfoKey() const {
GR_STATIC_ASSERT(kLast_GrBlendCoeff < (1 << kBlendCoeffShift));
GR_STATIC_ASSERT(kFirstAdvancedGrBlendEquation - 1 < 4);
uint32_t key = blendInfo.fWriteColor;
key |= (blendInfo.fSrcBlend << kBlendWriteShift);
key |= (blendInfo.fDstBlend << (kBlendWriteShift + kBlendCoeffShift));
key |= (blendInfo.fEquation << (kBlendWriteShift + 2 * kBlendCoeffShift));
uint32_t blendKey = blendInfo.fWriteColor;
blendKey |= (blendInfo.fSrcBlend << kBlendWriteShift);
blendKey |= (blendInfo.fDstBlend << (kBlendWriteShift + kBlendCoeffShift));
blendKey |= (blendInfo.fEquation << (kBlendWriteShift + 2 * kBlendCoeffShift));
return key;
b->add32(blendKey);
}

View File

@ -197,7 +197,7 @@ public:
GrXferBarrierType xferBarrierType(GrTexture*, const GrCaps&) const;
// Used by Vulkan and Metal to cache their respective pipeline objects
uint32_t getBlendInfoKey() const;
void genKey(GrProcessorKeyBuilder*, const GrCaps&) const;
const GrSwizzle& outputSwizzle() const { return fOutputSwizzle; }

View File

@ -468,7 +468,7 @@ bool GrMtlPipelineStateBuilder::Desc::Build(Desc* desc,
b.add32((uint32_t)programInfo.pipeline().isStencilEnabled());
// Stencil samples don't seem to be tracked in the MTLRenderPipeline
b.add32(programInfo.pipeline().getBlendInfoKey());
programInfo.pipeline().genKey(&b, *gpu->caps());
b.add32((uint32_t)programInfo.primitiveType());

View File

@ -461,29 +461,6 @@ void GrVkCaps::applyDriverCorrectnessWorkarounds(const VkPhysicalDevicePropertie
}
}
int get_max_sample_count(VkSampleCountFlags flags) {
SkASSERT(flags & VK_SAMPLE_COUNT_1_BIT);
if (!(flags & VK_SAMPLE_COUNT_2_BIT)) {
return 0;
}
if (!(flags & VK_SAMPLE_COUNT_4_BIT)) {
return 2;
}
if (!(flags & VK_SAMPLE_COUNT_8_BIT)) {
return 4;
}
if (!(flags & VK_SAMPLE_COUNT_16_BIT)) {
return 8;
}
if (!(flags & VK_SAMPLE_COUNT_32_BIT)) {
return 16;
}
if (!(flags & VK_SAMPLE_COUNT_64_BIT)) {
return 32;
}
return 64;
}
void GrVkCaps::initGrCaps(const GrVkInterface* vkInterface,
VkPhysicalDevice physDev,
const VkPhysicalDeviceProperties& properties,
@ -497,6 +474,11 @@ void GrVkCaps::initGrCaps(const GrVkInterface* vkInterface,
static const uint32_t kMaxVertexAttributes = 64;
fMaxVertexAttributes = SkTMin(properties.limits.maxVertexInputAttributes, kMaxVertexAttributes);
if (extensions.hasExtension(VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME, 1)) {
// We "disable" multisample by colocating all samples at pixel center.
fMultisampleDisableSupport = true;
}
// We could actually query and get a max size for each config, however maxImageDimension2D will
// give the minimum max size across all configs. So for simplicity we will use that for now.
fMaxRenderTargetSize = SkTMin(properties.limits.maxImageDimension2D, (uint32_t)INT_MAX);
@ -1187,12 +1169,8 @@ void GrVkCaps::FormatInfo::initSampleCounts(const GrVkInterface* interface,
if (flags & VK_SAMPLE_COUNT_16_BIT) {
fColorSampleCounts.push_back(16);
}
if (flags & VK_SAMPLE_COUNT_32_BIT) {
fColorSampleCounts.push_back(32);
}
if (flags & VK_SAMPLE_COUNT_64_BIT) {
fColorSampleCounts.push_back(64);
}
// Standard sample locations are not defined for more than 16 samples, and we don't need more
// than 16. Omit 32 and 64.
}
void GrVkCaps::FormatInfo::init(const GrVkInterface* interface,

View File

@ -294,6 +294,29 @@ static void setup_multisample_state(const GrProgramInfo& programInfo,
multisampleInfo->alphaToOneEnable = VK_FALSE;
}
static void setup_all_sample_locations_at_pixel_center(
const GrProgramInfo& programInfo,
VkPipelineSampleLocationsStateCreateInfoEXT* sampleLocations) {
constexpr static VkSampleLocationEXT kCenteredSampleLocations[16] = {
{.5f,.5f}, {.5f,.5f}, {.5f,.5f}, {.5f,.5f}, {.5f,.5f}, {.5f,.5f}, {.5f,.5f}, {.5f,.5f},
{.5f,.5f}, {.5f,.5f}, {.5f,.5f}, {.5f,.5f}, {.5f,.5f}, {.5f,.5f}, {.5f,.5f}, {.5f,.5f}};
memset(sampleLocations, 0, sizeof(VkPipelineSampleLocationsStateCreateInfoEXT));
sampleLocations->sType = VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT;
sampleLocations->pNext = nullptr;
sampleLocations->sampleLocationsEnable = VK_TRUE;
sampleLocations->sampleLocationsInfo.sType = VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT;
sampleLocations->sampleLocationsInfo.pNext = nullptr;
SkAssertResult(GrSampleCountToVkSampleCount(
programInfo.numSamples(),
&sampleLocations->sampleLocationsInfo.sampleLocationsPerPixel));
sampleLocations->sampleLocationsInfo.sampleLocationGridSize.width = 1;
sampleLocations->sampleLocationsInfo.sampleLocationGridSize.height = 1;
SkASSERT(programInfo.numSamples() < (int)SK_ARRAY_COUNT(kCenteredSampleLocations));
sampleLocations->sampleLocationsInfo.sampleLocationsCount = std::min(
programInfo.numSamples(), (int)SK_ARRAY_COUNT(kCenteredSampleLocations));
sampleLocations->sampleLocationsInfo.pSampleLocations = kCenteredSampleLocations;
}
static VkBlendFactor blend_coeff_to_vk_blend(GrBlendCoeff coeff) {
static const VkBlendFactor gTable[] = {
VK_BLEND_FACTOR_ZERO, // kZero_GrBlendCoeff
@ -523,6 +546,15 @@ GrVkPipeline* GrVkPipeline::Create(
VkPipelineMultisampleStateCreateInfo multisampleInfo;
setup_multisample_state(programInfo, gpu->caps(), &multisampleInfo);
VkPipelineSampleLocationsStateCreateInfoEXT sampleLocations;
if (gpu->caps()->multisampleDisableSupport()) {
if (programInfo.numSamples() > 1 && !programInfo.pipeline().isHWAntialiasState()) {
setup_all_sample_locations_at_pixel_center(programInfo, &sampleLocations);
sampleLocations.pNext = multisampleInfo.pNext;
multisampleInfo.pNext = &sampleLocations;
}
}
// We will only have one color attachment per pipeline.
VkPipelineColorBlendAttachmentState attachmentStates[1];
VkPipelineColorBlendStateCreateInfo colorBlendInfo;

View File

@ -346,7 +346,7 @@ bool GrVkPipelineStateBuilder::Desc::Build(Desc* desc,
stencil.genKey(&b);
b.add32(programInfo.pipeline().getBlendInfoKey());
programInfo.pipeline().genKey(&b, *gpu->caps());
// Vulkan requires the full primitive type as part of its key
b.add32((uint32_t)programInfo.primitiveType());

View File

@ -96,12 +96,6 @@ bool GrSampleCountToVkSampleCount(uint32_t samples, VkSampleCountFlagBits* vkSam
case 16:
*vkSamples = VK_SAMPLE_COUNT_16_BIT;
return true;
case 32:
*vkSamples = VK_SAMPLE_COUNT_32_BIT;
return true;
case 64:
*vkSamples = VK_SAMPLE_COUNT_64_BIT;
return true;
default:
return false;
}