panvk: Move the VkDeviceMemory logic to panvk_device_memory.{c,h}

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Acked-by: Erik Faye-Lund <erik.faye-lund@collabora.com>
Reviewed-by: Mary Guillemard <mary.guillemard@collabora.com>
Reviewed-by: Rebecca Mckeever <rebecca.mckeever@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/28170>
This commit is contained in:
Boris Brezillon
2023-12-15 12:45:48 +01:00
committed by Marge Bot
parent 09d3411ad8
commit 5a817bd62b
7 changed files with 314 additions and 283 deletions
+1
View File
@@ -39,6 +39,7 @@ libpanvk_files = files(
'panvk_cmd_buffer.c',
'panvk_cs.c',
'panvk_device.c',
'panvk_device_memory.c',
'panvk_descriptor_set.c',
'panvk_formats.c',
'panvk_image.c',
+1
View File
@@ -4,6 +4,7 @@
*/
#include "panvk_buffer.h"
#include "panvk_device_memory.h"
#include "panvk_private.h"
VKAPI_ATTR VkDeviceAddress VKAPI_CALL
+1 -272
View File
@@ -26,6 +26,7 @@
* DEALINGS IN THE SOFTWARE.
*/
#include "panvk_device_memory.h"
#include "panvk_image.h"
#include "panvk_private.h"
@@ -1318,245 +1319,6 @@ vk_icdGetInstanceProcAddr(VkInstance instance, const char *pName)
return panvk_GetInstanceProcAddr(instance, pName);
}
VKAPI_ATTR VkResult VKAPI_CALL
panvk_AllocateMemory(VkDevice _device,
const VkMemoryAllocateInfo *pAllocateInfo,
const VkAllocationCallbacks *pAllocator,
VkDeviceMemory *pMem)
{
VK_FROM_HANDLE(panvk_device, device, _device);
struct panvk_device_memory *mem;
bool can_be_exported = false;
VkResult result;
assert(pAllocateInfo->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO);
if (pAllocateInfo->allocationSize == 0) {
/* Apparently, this is allowed */
*pMem = VK_NULL_HANDLE;
return VK_SUCCESS;
}
const VkExportMemoryAllocateInfo *export_info =
vk_find_struct_const(pAllocateInfo->pNext, EXPORT_MEMORY_ALLOCATE_INFO);
if (export_info) {
if (export_info->handleTypes &
~(VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT |
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT))
return vk_error(device, VK_ERROR_INVALID_EXTERNAL_HANDLE);
else if (export_info->handleTypes)
can_be_exported = true;
}
mem = vk_device_memory_create(&device->vk, pAllocateInfo, pAllocator,
sizeof(*mem));
if (mem == NULL)
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
const VkImportMemoryFdInfoKHR *fd_info =
vk_find_struct_const(pAllocateInfo->pNext, IMPORT_MEMORY_FD_INFO_KHR);
if (fd_info && !fd_info->handleType)
fd_info = NULL;
if (fd_info) {
assert(
fd_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
fd_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
/*
* TODO Importing the same fd twice gives us the same handle without
* reference counting. We need to maintain a per-instance handle-to-bo
* table and add reference count to panvk_bo.
*/
mem->bo = pan_kmod_bo_import(device->kmod.dev, fd_info->fd, 0);
if (!mem->bo) {
result = vk_error(device, VK_ERROR_INVALID_EXTERNAL_HANDLE);
goto err_destroy_mem;
}
} else {
mem->bo = pan_kmod_bo_alloc(device->kmod.dev,
can_be_exported ? NULL : device->kmod.vm,
pAllocateInfo->allocationSize, 0);
if (!mem->bo) {
result = vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
goto err_destroy_mem;
}
}
/* Always GPU-map at creation time. */
struct pan_kmod_vm_op op = {
.type = PAN_KMOD_VM_OP_TYPE_MAP,
.va = {
.start = PAN_KMOD_VM_MAP_AUTO_VA,
.size = pan_kmod_bo_size(mem->bo),
},
.map = {
.bo = mem->bo,
.bo_offset = 0,
},
};
int ret =
pan_kmod_vm_bind(device->kmod.vm, PAN_KMOD_VM_OP_MODE_IMMEDIATE, &op, 1);
if (ret) {
result = vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
goto err_put_bo;
}
mem->addr.dev = op.va.start;
if (fd_info) {
/* From the Vulkan spec:
*
* "Importing memory from a file descriptor transfers ownership of
* the file descriptor from the application to the Vulkan
* implementation. The application must not perform any operations on
* the file descriptor after a successful import."
*
* If the import fails, we leave the file descriptor open.
*/
close(fd_info->fd);
}
if (device->debug.decode_ctx) {
pandecode_inject_mmap(device->debug.decode_ctx, mem->addr.dev, NULL,
pan_kmod_bo_size(mem->bo), NULL);
}
*pMem = panvk_device_memory_to_handle(mem);
return VK_SUCCESS;
err_put_bo:
pan_kmod_bo_put(mem->bo);
err_destroy_mem:
vk_device_memory_destroy(&device->vk, pAllocator, &mem->vk);
return result;
}
VKAPI_ATTR void VKAPI_CALL
panvk_FreeMemory(VkDevice _device, VkDeviceMemory _mem,
const VkAllocationCallbacks *pAllocator)
{
VK_FROM_HANDLE(panvk_device, device, _device);
VK_FROM_HANDLE(panvk_device_memory, mem, _mem);
if (mem == NULL)
return;
if (device->debug.decode_ctx) {
pandecode_inject_free(device->debug.decode_ctx, mem->addr.dev,
pan_kmod_bo_size(mem->bo));
}
struct pan_kmod_vm_op op = {
.type = PAN_KMOD_VM_OP_TYPE_UNMAP,
.va = {
.start = mem->addr.dev,
.size = pan_kmod_bo_size(mem->bo),
},
};
ASSERTED int ret =
pan_kmod_vm_bind(device->kmod.vm, PAN_KMOD_VM_OP_MODE_IMMEDIATE, &op, 1);
assert(!ret);
pan_kmod_bo_put(mem->bo);
vk_device_memory_destroy(&device->vk, pAllocator, &mem->vk);
}
VKAPI_ATTR VkResult VKAPI_CALL
panvk_MapMemory2KHR(VkDevice _device, const VkMemoryMapInfoKHR *pMemoryMapInfo,
void **ppData)
{
VK_FROM_HANDLE(panvk_device, device, _device);
VK_FROM_HANDLE(panvk_device_memory, mem, pMemoryMapInfo->memory);
if (mem == NULL) {
*ppData = NULL;
return VK_SUCCESS;
}
const VkDeviceSize offset = pMemoryMapInfo->offset;
const VkDeviceSize size = vk_device_memory_range(
&mem->vk, pMemoryMapInfo->offset, pMemoryMapInfo->size);
/* From the Vulkan spec version 1.0.32 docs for MapMemory:
*
* * If size is not equal to VK_WHOLE_SIZE, size must be greater than 0
* assert(size != 0);
* * If size is not equal to VK_WHOLE_SIZE, size must be less than or
* equal to the size of the memory minus offset
*/
assert(size > 0);
assert(offset + size <= mem->bo->size);
if (size != (size_t)size) {
return vk_errorf(device, VK_ERROR_MEMORY_MAP_FAILED,
"requested size 0x%" PRIx64 " does not fit in %u bits",
size, (unsigned)(sizeof(size_t) * 8));
}
/* From the Vulkan 1.2.194 spec:
*
* "memory must not be currently host mapped"
*/
if (mem->addr.host)
return vk_errorf(device, VK_ERROR_MEMORY_MAP_FAILED,
"Memory object already mapped.");
void *addr = pan_kmod_bo_mmap(mem->bo, 0, pan_kmod_bo_size(mem->bo),
PROT_READ | PROT_WRITE, MAP_SHARED, NULL);
if (addr == MAP_FAILED)
return vk_errorf(device, VK_ERROR_MEMORY_MAP_FAILED,
"Memory object couldn't be mapped.");
mem->addr.host = addr;
*ppData = mem->addr.host + offset;
return VK_SUCCESS;
}
VKAPI_ATTR VkResult VKAPI_CALL
panvk_UnmapMemory2KHR(VkDevice _device,
const VkMemoryUnmapInfoKHR *pMemoryUnmapInfo)
{
VK_FROM_HANDLE(panvk_device_memory, mem, pMemoryUnmapInfo->memory);
if (mem->addr.host) {
ASSERTED int ret =
os_munmap((void *)mem->addr.host, pan_kmod_bo_size(mem->bo));
assert(!ret);
mem->addr.host = NULL;
}
return VK_SUCCESS;
}
VKAPI_ATTR VkResult VKAPI_CALL
panvk_FlushMappedMemoryRanges(VkDevice _device, uint32_t memoryRangeCount,
const VkMappedMemoryRange *pMemoryRanges)
{
return VK_SUCCESS;
}
VKAPI_ATTR VkResult VKAPI_CALL
panvk_InvalidateMappedMemoryRanges(VkDevice _device, uint32_t memoryRangeCount,
const VkMappedMemoryRange *pMemoryRanges)
{
return VK_SUCCESS;
}
VKAPI_ATTR void VKAPI_CALL
panvk_GetDeviceMemoryCommitment(VkDevice device, VkDeviceMemory memory,
VkDeviceSize *pCommittedMemoryInBytes)
{
*pCommittedMemoryInBytes = 0;
}
VKAPI_ATTR VkResult VKAPI_CALL
panvk_CreateEvent(VkDevice _device, const VkEventCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkEvent *pEvent)
@@ -1676,39 +1438,6 @@ panvk_DestroySampler(VkDevice _device, VkSampler _sampler,
vk_sampler_destroy(&device->vk, pAllocator, &sampler->vk);
}
VKAPI_ATTR VkResult VKAPI_CALL
panvk_GetMemoryFdKHR(VkDevice _device, const VkMemoryGetFdInfoKHR *pGetFdInfo,
int *pFd)
{
VK_FROM_HANDLE(panvk_device, device, _device);
VK_FROM_HANDLE(panvk_device_memory, memory, pGetFdInfo->memory);
assert(pGetFdInfo->sType == VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR);
/* At the moment, we support only the below handle types. */
assert(
pGetFdInfo->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
pGetFdInfo->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
int prime_fd = pan_kmod_bo_export(memory->bo);
if (prime_fd < 0)
return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
*pFd = prime_fd;
return VK_SUCCESS;
}
VKAPI_ATTR VkResult VKAPI_CALL
panvk_GetMemoryFdPropertiesKHR(VkDevice _device,
VkExternalMemoryHandleTypeFlagBits handleType,
int fd,
VkMemoryFdPropertiesKHR *pMemoryFdProperties)
{
assert(handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
pMemoryFdProperties->memoryTypeBits = 1;
return VK_SUCCESS;
}
VKAPI_ATTR void VKAPI_CALL
panvk_GetPhysicalDeviceExternalSemaphoreProperties(
VkPhysicalDevice physicalDevice,
+283
View File
@@ -0,0 +1,283 @@
/*
* Copyright © 2021 Collabora Ltd.
* SPDX-License-Identifier: MIT
*/
#include "genxml/decode.h"
#include "vulkan/util/vk_util.h"
#include "panvk_device_memory.h"
#include "panvk_private.h"
VKAPI_ATTR VkResult VKAPI_CALL
panvk_AllocateMemory(VkDevice _device,
const VkMemoryAllocateInfo *pAllocateInfo,
const VkAllocationCallbacks *pAllocator,
VkDeviceMemory *pMem)
{
VK_FROM_HANDLE(panvk_device, device, _device);
struct panvk_device_memory *mem;
bool can_be_exported = false;
VkResult result;
assert(pAllocateInfo->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO);
if (pAllocateInfo->allocationSize == 0) {
/* Apparently, this is allowed */
*pMem = VK_NULL_HANDLE;
return VK_SUCCESS;
}
const VkExportMemoryAllocateInfo *export_info =
vk_find_struct_const(pAllocateInfo->pNext, EXPORT_MEMORY_ALLOCATE_INFO);
if (export_info) {
if (export_info->handleTypes &
~(VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT |
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT))
return vk_error(device, VK_ERROR_INVALID_EXTERNAL_HANDLE);
else if (export_info->handleTypes)
can_be_exported = true;
}
mem = vk_device_memory_create(&device->vk, pAllocateInfo, pAllocator,
sizeof(*mem));
if (mem == NULL)
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
const VkImportMemoryFdInfoKHR *fd_info =
vk_find_struct_const(pAllocateInfo->pNext, IMPORT_MEMORY_FD_INFO_KHR);
if (fd_info && !fd_info->handleType)
fd_info = NULL;
if (fd_info) {
assert(
fd_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
fd_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
/*
* TODO Importing the same fd twice gives us the same handle without
* reference counting. We need to maintain a per-instance handle-to-bo
* table and add reference count to panvk_bo.
*/
mem->bo = pan_kmod_bo_import(device->kmod.dev, fd_info->fd, 0);
if (!mem->bo) {
result = vk_error(device, VK_ERROR_INVALID_EXTERNAL_HANDLE);
goto err_destroy_mem;
}
} else {
mem->bo = pan_kmod_bo_alloc(device->kmod.dev,
can_be_exported ? NULL : device->kmod.vm,
pAllocateInfo->allocationSize, 0);
if (!mem->bo) {
result = vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
goto err_destroy_mem;
}
}
/* Always GPU-map at creation time. */
struct pan_kmod_vm_op op = {
.type = PAN_KMOD_VM_OP_TYPE_MAP,
.va = {
.start = PAN_KMOD_VM_MAP_AUTO_VA,
.size = pan_kmod_bo_size(mem->bo),
},
.map = {
.bo = mem->bo,
.bo_offset = 0,
},
};
int ret =
pan_kmod_vm_bind(device->kmod.vm, PAN_KMOD_VM_OP_MODE_IMMEDIATE, &op, 1);
if (ret) {
result = vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
goto err_put_bo;
}
mem->addr.dev = op.va.start;
if (fd_info) {
/* From the Vulkan spec:
*
* "Importing memory from a file descriptor transfers ownership of
* the file descriptor from the application to the Vulkan
* implementation. The application must not perform any operations on
* the file descriptor after a successful import."
*
* If the import fails, we leave the file descriptor open.
*/
close(fd_info->fd);
}
if (device->debug.decode_ctx) {
pandecode_inject_mmap(device->debug.decode_ctx, mem->addr.dev, NULL,
pan_kmod_bo_size(mem->bo), NULL);
}
*pMem = panvk_device_memory_to_handle(mem);
return VK_SUCCESS;
err_put_bo:
pan_kmod_bo_put(mem->bo);
err_destroy_mem:
vk_device_memory_destroy(&device->vk, pAllocator, &mem->vk);
return result;
}
VKAPI_ATTR void VKAPI_CALL
panvk_FreeMemory(VkDevice _device, VkDeviceMemory _mem,
const VkAllocationCallbacks *pAllocator)
{
VK_FROM_HANDLE(panvk_device, device, _device);
VK_FROM_HANDLE(panvk_device_memory, mem, _mem);
if (mem == NULL)
return;
if (device->debug.decode_ctx) {
pandecode_inject_free(device->debug.decode_ctx, mem->addr.dev,
pan_kmod_bo_size(mem->bo));
}
struct pan_kmod_vm_op op = {
.type = PAN_KMOD_VM_OP_TYPE_UNMAP,
.va = {
.start = mem->addr.dev,
.size = pan_kmod_bo_size(mem->bo),
},
};
ASSERTED int ret =
pan_kmod_vm_bind(device->kmod.vm, PAN_KMOD_VM_OP_MODE_IMMEDIATE, &op, 1);
assert(!ret);
pan_kmod_bo_put(mem->bo);
vk_device_memory_destroy(&device->vk, pAllocator, &mem->vk);
}
VKAPI_ATTR VkResult VKAPI_CALL
panvk_MapMemory2KHR(VkDevice _device, const VkMemoryMapInfoKHR *pMemoryMapInfo,
void **ppData)
{
VK_FROM_HANDLE(panvk_device, device, _device);
VK_FROM_HANDLE(panvk_device_memory, mem, pMemoryMapInfo->memory);
if (mem == NULL) {
*ppData = NULL;
return VK_SUCCESS;
}
const VkDeviceSize offset = pMemoryMapInfo->offset;
const VkDeviceSize size = vk_device_memory_range(
&mem->vk, pMemoryMapInfo->offset, pMemoryMapInfo->size);
/* From the Vulkan spec version 1.0.32 docs for MapMemory:
*
* * If size is not equal to VK_WHOLE_SIZE, size must be greater than 0
* assert(size != 0);
* * If size is not equal to VK_WHOLE_SIZE, size must be less than or
* equal to the size of the memory minus offset
*/
assert(size > 0);
assert(offset + size <= mem->bo->size);
if (size != (size_t)size) {
return vk_errorf(device, VK_ERROR_MEMORY_MAP_FAILED,
"requested size 0x%" PRIx64 " does not fit in %u bits",
size, (unsigned)(sizeof(size_t) * 8));
}
/* From the Vulkan 1.2.194 spec:
*
* "memory must not be currently host mapped"
*/
if (mem->addr.host)
return vk_errorf(device, VK_ERROR_MEMORY_MAP_FAILED,
"Memory object already mapped.");
void *addr = pan_kmod_bo_mmap(mem->bo, 0, pan_kmod_bo_size(mem->bo),
PROT_READ | PROT_WRITE, MAP_SHARED, NULL);
if (addr == MAP_FAILED)
return vk_errorf(device, VK_ERROR_MEMORY_MAP_FAILED,
"Memory object couldn't be mapped.");
mem->addr.host = addr;
*ppData = mem->addr.host + offset;
return VK_SUCCESS;
}
VKAPI_ATTR VkResult VKAPI_CALL
panvk_UnmapMemory2KHR(VkDevice _device,
const VkMemoryUnmapInfoKHR *pMemoryUnmapInfo)
{
VK_FROM_HANDLE(panvk_device_memory, mem, pMemoryUnmapInfo->memory);
if (mem->addr.host) {
ASSERTED int ret =
os_munmap((void *)mem->addr.host, pan_kmod_bo_size(mem->bo));
assert(!ret);
mem->addr.host = NULL;
}
return VK_SUCCESS;
}
VKAPI_ATTR VkResult VKAPI_CALL
panvk_FlushMappedMemoryRanges(VkDevice _device, uint32_t memoryRangeCount,
const VkMappedMemoryRange *pMemoryRanges)
{
return VK_SUCCESS;
}
VKAPI_ATTR VkResult VKAPI_CALL
panvk_InvalidateMappedMemoryRanges(VkDevice _device, uint32_t memoryRangeCount,
const VkMappedMemoryRange *pMemoryRanges)
{
return VK_SUCCESS;
}
VKAPI_ATTR VkResult VKAPI_CALL
panvk_GetMemoryFdKHR(VkDevice _device, const VkMemoryGetFdInfoKHR *pGetFdInfo,
int *pFd)
{
VK_FROM_HANDLE(panvk_device, device, _device);
VK_FROM_HANDLE(panvk_device_memory, memory, pGetFdInfo->memory);
assert(pGetFdInfo->sType == VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR);
/* At the moment, we support only the below handle types. */
assert(
pGetFdInfo->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
pGetFdInfo->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
int prime_fd = pan_kmod_bo_export(memory->bo);
if (prime_fd < 0)
return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
*pFd = prime_fd;
return VK_SUCCESS;
}
VKAPI_ATTR VkResult VKAPI_CALL
panvk_GetMemoryFdPropertiesKHR(VkDevice _device,
VkExternalMemoryHandleTypeFlagBits handleType,
int fd,
VkMemoryFdPropertiesKHR *pMemoryFdProperties)
{
assert(handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
pMemoryFdProperties->memoryTypeBits = 1;
return VK_SUCCESS;
}
VKAPI_ATTR void VKAPI_CALL
panvk_GetDeviceMemoryCommitment(VkDevice device, VkDeviceMemory memory,
VkDeviceSize *pCommittedMemoryInBytes)
{
*pCommittedMemoryInBytes = 0;
}
+27
View File
@@ -0,0 +1,27 @@
/*
* Copyright © 2021 Collabora Ltd.
* SPDX-License-Identifier: MIT
*/
#ifndef PANVK_DEVICE_MEMORY_H
#define PANVK_DEVICE_MEMORY_H
#include <stdint.h>
#include "vk_device_memory.h"
struct panvk_priv_bo;
struct panvk_device_memory {
struct vk_device_memory vk;
struct pan_kmod_bo *bo;
struct {
uint64_t dev;
void *host;
} addr;
};
VK_DEFINE_NONDISP_HANDLE_CASTS(panvk_device_memory, vk.base, VkDeviceMemory,
VK_OBJECT_TYPE_DEVICE_MEMORY)
#endif
+1
View File
@@ -28,6 +28,7 @@
#include "pan_props.h"
#include "panvk_device_memory.h"
#include "panvk_image.h"
#include "panvk_private.h"
-11
View File
@@ -336,15 +336,6 @@ struct panvk_cmd_event_op {
struct panvk_event *event;
};
struct panvk_device_memory {
struct vk_device_memory vk;
struct pan_kmod_bo *bo;
struct {
mali_ptr dev;
void *host;
} addr;
};
struct panvk_buffer_desc {
struct panvk_buffer *buffer;
VkDeviceSize offset;
@@ -933,8 +924,6 @@ VK_DEFINE_NONDISP_HANDLE_CASTS(panvk_descriptor_set, base, VkDescriptorSet,
VK_DEFINE_NONDISP_HANDLE_CASTS(panvk_descriptor_set_layout, vk.base,
VkDescriptorSetLayout,
VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT)
VK_DEFINE_NONDISP_HANDLE_CASTS(panvk_device_memory, vk.base, VkDeviceMemory,
VK_OBJECT_TYPE_DEVICE_MEMORY)
VK_DEFINE_NONDISP_HANDLE_CASTS(panvk_event, base, VkEvent, VK_OBJECT_TYPE_EVENT)
VK_DEFINE_NONDISP_HANDLE_CASTS(panvk_image_view, vk.base, VkImageView,
VK_OBJECT_TYPE_IMAGE_VIEW);