Home | History | Annotate | Download | only in vk
      1 /*
      2 * Copyright 2016 Google Inc.
      3 *
      4 * Use of this source code is governed by a BSD-style license that can be
      5 * found in the LICENSE file.
      6 */
      7 
      8 #include "GrVkSampler.h"
      9 
     10 #include "GrVkGpu.h"
     11 
     12 static inline VkSamplerAddressMode tile_to_vk_sampler_address(SkShader::TileMode tm) {
     13     static const VkSamplerAddressMode gWrapModes[] = {
     14         VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
     15         VK_SAMPLER_ADDRESS_MODE_REPEAT,
     16         VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT
     17     };
     18     GR_STATIC_ASSERT(SkShader::kTileModeCount == SK_ARRAY_COUNT(gWrapModes));
     19     GR_STATIC_ASSERT(0 == SkShader::kClamp_TileMode);
     20     GR_STATIC_ASSERT(1 == SkShader::kRepeat_TileMode);
     21     GR_STATIC_ASSERT(2 == SkShader::kMirror_TileMode);
     22     return gWrapModes[tm];
     23 }
     24 
     25 GrVkSampler* GrVkSampler::Create(const GrVkGpu* gpu, const GrSamplerParams& params,
     26                                  uint32_t mipLevels) {
     27     static VkFilter vkMinFilterModes[] = {
     28         VK_FILTER_NEAREST,
     29         VK_FILTER_LINEAR,
     30         VK_FILTER_LINEAR
     31     };
     32     static VkFilter vkMagFilterModes[] = {
     33         VK_FILTER_NEAREST,
     34         VK_FILTER_LINEAR,
     35         VK_FILTER_LINEAR
     36     };
     37 
     38     VkSamplerCreateInfo createInfo;
     39     memset(&createInfo, 0, sizeof(VkSamplerCreateInfo));
     40     createInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
     41     createInfo.pNext = 0;
     42     createInfo.flags = 0;
     43     createInfo.magFilter = vkMagFilterModes[params.filterMode()];
     44     createInfo.minFilter = vkMinFilterModes[params.filterMode()];
     45     createInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
     46     createInfo.addressModeU = tile_to_vk_sampler_address(params.getTileModeX());
     47     createInfo.addressModeV = tile_to_vk_sampler_address(params.getTileModeY());
     48     createInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; // Shouldn't matter
     49     createInfo.mipLodBias = 0.0f;
     50     createInfo.anisotropyEnable = VK_FALSE;
     51     createInfo.maxAnisotropy = 1.0f;
     52     createInfo.compareEnable = VK_FALSE;
     53     createInfo.compareOp = VK_COMPARE_OP_NEVER;
     54     // Vulkan doesn't have a direct mapping of GL's nearest or linear filters for minFilter since
     55     // there is always a mipmapMode. To get the same effect as GL we can set minLod = maxLod = 0.0.
     56     // This works since our min and mag filters are the same (this forces us to use mag on the 0
     57     // level mip). If the filters weren't the same we could set min = 0 and max = 0.25 to force
     58     // the minFilter on mip level 0.
     59     createInfo.minLod = 0.0f;
     60     bool useMipMaps = GrSamplerParams::kMipMap_FilterMode == params.filterMode() && mipLevels > 1;
     61     createInfo.maxLod = !useMipMaps ? 0.0f : (float)(mipLevels);
     62     createInfo.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
     63     createInfo.unnormalizedCoordinates = VK_FALSE;
     64 
     65     VkSampler sampler;
     66     GR_VK_CALL_ERRCHECK(gpu->vkInterface(), CreateSampler(gpu->device(),
     67                                                           &createInfo,
     68                                                           nullptr,
     69                                                           &sampler));
     70 
     71     return new GrVkSampler(sampler, GenerateKey(params, mipLevels));
     72 }
     73 
     74 void GrVkSampler::freeGPUData(const GrVkGpu* gpu) const {
     75     SkASSERT(fSampler);
     76     GR_VK_CALL(gpu->vkInterface(), DestroySampler(gpu->device(), fSampler, nullptr));
     77 }
     78 
     79 uint16_t GrVkSampler::GenerateKey(const GrSamplerParams& params, uint32_t mipLevels) {
     80     const int kTileModeXShift = 2;
     81     const int kTileModeYShift = 4;
     82     const int kMipLevelShift = 6;
     83 
     84     uint16_t key = params.filterMode();
     85 
     86     SkASSERT(params.filterMode() <= 3);
     87     key |= (params.getTileModeX() << kTileModeXShift);
     88 
     89     GR_STATIC_ASSERT(SkShader::kTileModeCount <= 4);
     90     key |= (params.getTileModeY() << kTileModeYShift);
     91 
     92     SkASSERT(mipLevels < 1024);
     93     key |= (mipLevels << kMipLevelShift);
     94 
     95     return key;
     96 }
     97