.has_robust_buffer_access = true,
.has_slc_cache_line_size_bits = true,
.has_slc_mcu_cache_controls = true,
+ .has_tf_bicubic_filter = true,
.has_tile_size_x = true,
.has_tile_size_y = true,
.has_tpu_array_textures = true,
.has_brn48492 = true,
.has_brn48545 = true,
.has_brn49032 = true,
+ .has_brn51025 = true,
.has_brn51210 = true,
.has_brn51764 = true,
.has_brn52354 = true,
.has_simple_internal_parameter_format_v2 = true,
.has_simple_parameter_format_version = true,
.has_slc_cache_line_size_bits = true,
+ .has_tile_size_16x16 = true,
.has_tile_size_x = true,
.has_tile_size_y = true,
- .has_tile_size_16x16 = true,
.has_tpu_extended_integer_lookup = true,
.has_tpu_image_state_v2 = true,
.has_usc_f16sop_u8 = true,
.has_simple_internal_parameter_format_v2 = true,
.has_simple_parameter_format_version = true,
.has_slc_cache_line_size_bits = true,
+ .has_tile_size_16x16 = true,
.has_tile_size_x = true,
.has_tile_size_y = true,
- .has_tile_size_16x16 = true,
.has_tpu_extended_integer_lookup = true,
.has_tpu_image_state_v2 = true,
.has_usc_f16sop_u8 = true,
#include "util/u_math.h"
#include "vk_alloc.h"
#include "vk_log.h"
+#include "vk_object.h"
#include "vk_util.h"
#define PVR_GLOBAL_FREE_LIST_INITIAL_SIZE (2U * 1024U * 1024U)
.maxDrawIndexedIndexValue = UINT32_MAX,
.maxDrawIndirectCount = 2U * 1024U * 1024U * 1024U,
- .maxSamplerLodBias = 15.0f,
- .maxSamplerAnisotropy = 16.0f,
+ .maxSamplerLodBias = 16.0f,
+ .maxSamplerAnisotropy = 1.0f,
.maxViewports = PVR_MAX_VIEWPORTS,
.maxViewportDimensions[0] = max_render_size,
vk_object_free(&device->vk, pAllocator, buffer);
}
-void pvr_DestroySampler(VkDevice _device,
- VkSampler _sampler,
- const VkAllocationCallbacks *pAllocator)
-{
- assert(!"Unimplemented");
-}
-
VkResult pvr_gpu_upload(struct pvr_device *device,
struct pvr_winsys_heap *heap,
const void *data,
return VK_SUCCESS;
}
+static uint32_t
+pvr_sampler_get_hw_filter_from_vk(const struct pvr_device_info *dev_info,
+ VkFilter filter)
+{
+ switch (filter) {
+ case VK_FILTER_NEAREST:
+ return PVRX(TEXSTATE_FILTER_POINT);
+ case VK_FILTER_LINEAR:
+ return PVRX(TEXSTATE_FILTER_LINEAR);
+ default:
+ unreachable("Unknown filter type.");
+ }
+}
+
+static uint32_t
+pvr_sampler_get_hw_addr_mode_from_vk(VkSamplerAddressMode addr_mode)
+{
+ switch (addr_mode) {
+ case VK_SAMPLER_ADDRESS_MODE_REPEAT:
+ return PVRX(TEXSTATE_ADDRMODE_REPEAT);
+ case VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT:
+ return PVRX(TEXSTATE_ADDRMODE_FLIP);
+ case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE:
+ return PVRX(TEXSTATE_ADDRMODE_CLAMP_TO_EDGE);
+ case VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE:
+ return PVRX(TEXSTATE_ADDRMODE_FLIP_ONCE_THEN_CLAMP);
+ case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER:
+ return PVRX(TEXSTATE_ADDRMODE_CLAMP_TO_BORDER);
+ default:
+ unreachable("Invalid sampler address mode.");
+ }
+}
+
VkResult pvr_CreateSampler(VkDevice _device,
const VkSamplerCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkSampler *pSampler)
{
- assert(!"Unimplemented");
+ PVR_FROM_HANDLE(pvr_device, device, _device);
+ struct pvr_sampler *sampler;
+ float lod_rounding_bias;
+ VkFilter min_filter;
+ VkFilter mag_filter;
+ float min_lod;
+ float max_lod;
+
+ sampler = vk_object_alloc(&device->vk,
+ pAllocator,
+ sizeof(*sampler),
+ VK_OBJECT_TYPE_SAMPLER);
+ if (!sampler)
+ return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ mag_filter = pCreateInfo->magFilter;
+ min_filter = pCreateInfo->minFilter;
+
+ if (PVR_HAS_QUIRK(&device->pdevice->dev_info, 51025)) {
+ /* The min/mag filters may need adjustment here, the GPU should decide
+ * which of the two filters to use based on the clamped LOD value: LOD
+ * <= 0 implies magnification, while LOD > 0 implies minification.
+ *
+ * As a workaround, we override magFilter with minFilter if we know that
+ * the magnification filter will never be used due to clamping anyway
+ * (i.e. minLod > 0). Conversely, we override minFilter with magFilter
+ * if maxLod <= 0.
+ */
+ if (pCreateInfo->minLod > 0.0f) {
+ /* The clamped LOD will always be positive => always minify. */
+ mag_filter = pCreateInfo->minFilter;
+ }
+
+ if (pCreateInfo->maxLod <= 0.0f) {
+ /* The clamped LOD will always be negative or zero => always
+ * magnify.
+ */
+ min_filter = pCreateInfo->magFilter;
+ }
+ }
+
+ pvr_csb_pack (&sampler->sampler_word, TEXSTATE_SAMPLER, word) {
+ const struct pvr_device_info *dev_info = &device->pdevice->dev_info;
+ const float lod_clamp_max = (float)PVRX(TEXSTATE_CLAMP_MAX) /
+ (1 << PVRX(TEXSTATE_CLAMP_FRACTIONAL_BITS));
+ const float max_dadjust = ((float)(PVRX(TEXSTATE_DADJUST_MAX_UINT) -
+ PVRX(TEXSTATE_DADJUST_ZERO_UINT))) /
+ (1 << PVRX(TEXSTATE_DADJUST_FRACTIONAL_BITS));
+ const float min_dadjust = ((float)(PVRX(TEXSTATE_DADJUST_MIN_UINT) -
+ PVRX(TEXSTATE_DADJUST_ZERO_UINT))) /
+ (1 << PVRX(TEXSTATE_DADJUST_FRACTIONAL_BITS));
+
+ word.magfilter = pvr_sampler_get_hw_filter_from_vk(dev_info, mag_filter);
+ word.minfilter = pvr_sampler_get_hw_filter_from_vk(dev_info, min_filter);
+
+ if (pCreateInfo->mipmapMode == VK_SAMPLER_MIPMAP_MODE_LINEAR)
+ word.mipfilter = true;
+
+ word.addrmode_u =
+ pvr_sampler_get_hw_addr_mode_from_vk(pCreateInfo->addressModeU);
+ word.addrmode_v =
+ pvr_sampler_get_hw_addr_mode_from_vk(pCreateInfo->addressModeV);
+ word.addrmode_w =
+ pvr_sampler_get_hw_addr_mode_from_vk(pCreateInfo->addressModeW);
+
+ /* The Vulkan 1.0.205 spec says:
+ *
+ * The absolute value of mipLodBias must be less than or equal to
+ * VkPhysicalDeviceLimits::maxSamplerLodBias.
+ */
+ word.dadjust =
+ PVRX(TEXSTATE_DADJUST_ZERO_UINT) +
+ util_signed_fixed(
+ CLAMP(pCreateInfo->mipLodBias, min_dadjust, max_dadjust),
+ PVRX(TEXSTATE_DADJUST_FRACTIONAL_BITS));
+
+ /* Anisotropy is not supported for now. */
+ word.anisoctl = PVRX(TEXSTATE_ANISOCTL_DISABLED);
+
+ if (PVR_HAS_QUIRK(&device->pdevice->dev_info, 51025) &&
+ pCreateInfo->mipmapMode == VK_SAMPLER_MIPMAP_MODE_NEAREST) {
+ /* When MIPMAP_MODE_NEAREST is enabled, the LOD level should be
+ * selected by adding 0.5 and then truncating the input LOD value.
+ * This hardware adds the 0.5 bias before clamping against
+ * lodmin/lodmax, while Vulkan specifies the bias to be added after
+ * clamping. We compensate for this difference by adding the 0.5
+ * bias to the LOD bounds, too.
+ */
+ lod_rounding_bias = 0.5f;
+ } else {
+ lod_rounding_bias = 0.0f;
+ }
+
+ min_lod = pCreateInfo->minLod + lod_rounding_bias;
+ word.minlod = util_unsigned_fixed(CLAMP(min_lod, 0.0f, lod_clamp_max),
+ PVRX(TEXSTATE_CLAMP_FRACTIONAL_BITS));
+
+ max_lod = pCreateInfo->maxLod + lod_rounding_bias;
+ word.maxlod = util_unsigned_fixed(CLAMP(max_lod, 0.0f, lod_clamp_max),
+ PVRX(TEXSTATE_CLAMP_FRACTIONAL_BITS));
+
+ word.bordercolor_index = pCreateInfo->borderColor;
+
+ if (pCreateInfo->unnormalizedCoordinates)
+ word.non_normalized_coords = true;
+ }
+
+ *pSampler = pvr_sampler_to_handle(sampler);
+
return VK_SUCCESS;
}
+void pvr_DestroySampler(VkDevice _device,
+ VkSampler _sampler,
+ const VkAllocationCallbacks *pAllocator)
+{
+ PVR_FROM_HANDLE(pvr_device, device, _device);
+ PVR_FROM_HANDLE(pvr_sampler, sampler, _sampler);
+
+ if (!sampler)
+ return;
+
+ vk_object_free(&device->vk, pAllocator, sampler);
+}
+
void pvr_GetBufferMemoryRequirements2(
VkDevice _device,
const VkBufferMemoryRequirementsInfo2 *pInfo,