| 3467 | } |
| 3468 | |
| 3469 | void vulkan_context::create_fixed_sampler_set() const { |
| 3470 | union vulkan_fixed_sampler { |
| 3471 | struct { |
| 3472 | //! nearest or linear, includes mip-map filtering |
| 3473 | uint32_t filter : 1; |
| 3474 | //! -> sampler.hpp: never, less, equal, less or equal, greater, not equal, greater or equal, always |
| 3475 | // TODO: get rid of always, b/c the compiler takes care of these (never as well, but we need a way to signal "no depth compare") |
| 3476 | uint32_t compare_mode : 3; |
| 3477 | //! 0 = clamp to edge, 1 = repeat, 2 = repeat-mirrored |
| 3478 | uint32_t address_mode : 2; |
| 3479 | //! unused |
| 3480 | uint32_t _unused : 26; |
| 3481 | }; |
| 3482 | uint32_t value; |
| 3483 | }; |
| 3484 | static_assert(sizeof(vulkan_fixed_sampler) == 4, "invalid sampler size"); |
| 3485 | static_assert(uint32_t(VK_COMPARE_OP_NEVER) == uint32_t(COMPARE_FUNCTION::NEVER) && |
| 3486 | uint32_t(VK_COMPARE_OP_LESS) == uint32_t(COMPARE_FUNCTION::LESS) && |
| 3487 | uint32_t(VK_COMPARE_OP_EQUAL) == uint32_t(COMPARE_FUNCTION::EQUAL) && |
| 3488 | uint32_t(VK_COMPARE_OP_LESS_OR_EQUAL) == uint32_t(COMPARE_FUNCTION::LESS_OR_EQUAL) && |
| 3489 | uint32_t(VK_COMPARE_OP_GREATER) == uint32_t(COMPARE_FUNCTION::GREATER) && |
| 3490 | uint32_t(VK_COMPARE_OP_NOT_EQUAL) == uint32_t(COMPARE_FUNCTION::NOT_EQUAL) && |
| 3491 | uint32_t(VK_COMPARE_OP_GREATER_OR_EQUAL) == uint32_t(COMPARE_FUNCTION::GREATER_OR_EQUAL) && |
| 3492 | uint32_t(VK_COMPARE_OP_ALWAYS) == uint32_t(COMPARE_FUNCTION::ALWAYS), |
| 3493 | "failed depth compare function sanity check"); |
| 3494 | |
| 3495 | for (auto& dev : devices) { |
| 3496 | auto& vk_dev = (vulkan_device&)*dev; |
| 3497 | vk_dev.fixed_sampler_set.resize(max_sampler_combinations, nullptr); |
| 3498 | } |
| 3499 | |
| 3500 | // create the samplers for all devices |
| 3501 | for (uint32_t combination = 0; combination < max_sampler_combinations; ++combination) { |
| 3502 | const vulkan_fixed_sampler smplr { .value = combination }; |
| 3503 | const VkFilter filter = (smplr.filter == 0 ? VK_FILTER_NEAREST : VK_FILTER_LINEAR); |
| 3504 | const VkSamplerMipmapMode mipmap_filter = (smplr.filter == 0 ? |
| 3505 | VK_SAMPLER_MIPMAP_MODE_NEAREST : VK_SAMPLER_MIPMAP_MODE_LINEAR); |
| 3506 | const VkSamplerAddressMode address_mode = (smplr.address_mode == 0 ? VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE : |
| 3507 | (smplr.address_mode == 1 ? VK_SAMPLER_ADDRESS_MODE_REPEAT : |
| 3508 | VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT)); |
| 3509 | VkSamplerCreateInfo sampler_create_info { |
| 3510 | .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, |
| 3511 | .pNext = nullptr, |
| 3512 | .flags = 0, |
| 3513 | .magFilter = filter, |
| 3514 | .minFilter = filter, |
| 3515 | .mipmapMode = mipmap_filter, |
| 3516 | .addressModeU = address_mode, |
| 3517 | .addressModeV = address_mode, |
| 3518 | .addressModeW = address_mode, |
| 3519 | .mipLodBias = 0.0f, |
| 3520 | // always enable anisotropic filtering when using linear filtering |
| 3521 | .anisotropyEnable = (smplr.filter != 0), |
| 3522 | .maxAnisotropy = 0.0f, |
| 3523 | .compareEnable = (smplr.compare_mode != 0), |
| 3524 | // NOTE: this matches 1:1, we will filter out NEVER/NONE and ALWAYS read ops in the compiler |
| 3525 | .compareOp = (VkCompareOp)smplr.compare_mode, |
| 3526 | .minLod = 0.0f, |
nothing calls this directly
no test coverage detected