anv/state: Factor out surface state calculation from genX_image_view_init.

Some fields of the surface state template were dependent on the
surface type, which is dependent on the usage of the image view, which
wasn't known until the bottom of the function after the template had
been constructed.  This caused failures in all image load/store CTS
tests using cubemaps.  Refactor the surface state calculation into a
function that is called once for each required usage.
This commit is contained in:
Francisco Jerez
2016-01-21 19:21:34 -08:00
committed by Jason Ekstrand
parent 16780632c2
commit d533c3796d
2 changed files with 109 additions and 81 deletions
+56 -44
View File
@@ -148,22 +148,22 @@ static const uint8_t anv_valign[] = {
[4] = VALIGN_4,
};
GENX_FUNC(GEN7, GEN75) void
genX(image_view_init)(struct anv_image_view *iview,
struct anv_device *device,
const VkImageViewCreateInfo* pCreateInfo,
struct anv_cmd_buffer *cmd_buffer)
static struct GENX(RENDER_SURFACE_STATE)
surface_state_for_image_view(struct anv_image_view *iview,
struct anv_device *device,
const VkImageViewCreateInfo *pCreateInfo,
VkImageUsageFlagBits usage)
{
assert(usage & (VK_IMAGE_USAGE_SAMPLED_BIT |
VK_IMAGE_USAGE_STORAGE_BIT |
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT));
assert(util_is_power_of_two(usage));
ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
const VkImageSubresourceRange *range = &pCreateInfo->subresourceRange;
struct anv_surface *surface =
anv_image_get_surface_for_aspect_mask(image, range->aspectMask);
if (pCreateInfo->viewType != VK_IMAGE_VIEW_TYPE_2D)
anv_finishme("non-2D image views");
uint32_t depth = 1;
if (range->layerCount > 1) {
depth = range->layerCount;
@@ -174,10 +174,13 @@ genX(image_view_init)(struct anv_image_view *iview,
const struct isl_extent3d image_align_sa =
isl_surf_get_image_alignment_sa(&surface->isl);
const struct GENX(RENDER_SURFACE_STATE) template = {
.SurfaceType = anv_surftype(image, pCreateInfo->viewType, false),
struct GENX(RENDER_SURFACE_STATE) template = {
.SurfaceType = anv_surftype(image, pCreateInfo->viewType,
usage == VK_IMAGE_USAGE_STORAGE_BIT),
.SurfaceArray = image->array_size > 1,
.SurfaceFormat = iview->format,
.SurfaceFormat = (usage != VK_IMAGE_USAGE_STORAGE_BIT ? iview->format :
isl_lower_storage_image_format(
&device->isl_dev, iview->format)),
.SurfaceVerticalAlignment = anv_valign[image_align_sa.height],
.SurfaceHorizontalAlignment = anv_halign[image_align_sa.width],
@@ -227,19 +230,44 @@ genX(image_view_init)(struct anv_image_view *iview,
.SurfaceBaseAddress = { NULL, iview->offset },
};
if (image->needs_nonrt_surface_state) {
struct GENX(RENDER_SURFACE_STATE) surface_state = template;
iview->nonrt_surface_state = alloc_surface_state(device, cmd_buffer);
surface_state.RenderCacheReadWriteMode = false;
if (usage == VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
/* For render target surfaces, the hardware interprets field
* MIPCount/LOD as LOD. The Broadwell PRM says:
*
* MIPCountLOD defines the LOD that will be rendered into.
* SurfaceMinLOD is ignored.
*/
template.MIPCountLOD = range->baseMipLevel;
template.SurfaceMinLOD = 0;
} else {
/* For non render target surfaces, the hardware interprets field
* MIPCount/LOD as MIPCount. The range of levels accessible by the
* sampler engine is [SurfaceMinLOD, SurfaceMinLOD + MIPCountLOD].
*/
surface_state.SurfaceMinLOD = range->baseMipLevel;
surface_state.MIPCountLOD = MAX2(range->levelCount, 1) - 1;
template.SurfaceMinLOD = range->baseMipLevel;
template.MIPCountLOD = MAX2(range->levelCount, 1) - 1;
}
return template;
}
GENX_FUNC(GEN7, GEN75) void
genX(image_view_init)(struct anv_image_view *iview,
struct anv_device *device,
const VkImageViewCreateInfo* pCreateInfo,
struct anv_cmd_buffer *cmd_buffer)
{
ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
if (pCreateInfo->viewType != VK_IMAGE_VIEW_TYPE_2D)
anv_finishme("non-2D image views");
if (image->needs_nonrt_surface_state) {
struct GENX(RENDER_SURFACE_STATE) surface_state =
surface_state_for_image_view(iview, device, pCreateInfo,
VK_IMAGE_USAGE_SAMPLED_BIT);
iview->nonrt_surface_state = alloc_surface_state(device, cmd_buffer);
GENX(RENDER_SURFACE_STATE_pack)(NULL, iview->nonrt_surface_state.map,
&surface_state);
@@ -251,21 +279,12 @@ genX(image_view_init)(struct anv_image_view *iview,
}
if (image->needs_color_rt_surface_state) {
struct GENX(RENDER_SURFACE_STATE) surface_state = template;
struct GENX(RENDER_SURFACE_STATE) surface_state =
surface_state_for_image_view(iview, device, pCreateInfo,
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
iview->color_rt_surface_state = alloc_surface_state(device, cmd_buffer);
surface_state.RenderCacheReadWriteMode = 0; /* Write only */
/* For render target surfaces, the hardware interprets field MIPCount/LOD as
* LOD. The Broadwell PRM says:
*
* MIPCountLOD defines the LOD that will be rendered into.
* SurfaceMinLOD is ignored.
*/
surface_state.MIPCountLOD = range->baseMipLevel;
surface_state.SurfaceMinLOD = 0;
GENX(RENDER_SURFACE_STATE_pack)(NULL, iview->color_rt_surface_state.map,
&surface_state);
if (!device->info.has_llc)
@@ -275,19 +294,12 @@ genX(image_view_init)(struct anv_image_view *iview,
}
if (image->needs_storage_surface_state) {
struct GENX(RENDER_SURFACE_STATE) surface_state = template;
struct GENX(RENDER_SURFACE_STATE) surface_state =
surface_state_for_image_view(iview, device, pCreateInfo,
VK_IMAGE_USAGE_STORAGE_BIT);
iview->storage_surface_state = alloc_surface_state(device, cmd_buffer);
surface_state.SurfaceType =
anv_surftype(image, pCreateInfo->viewType, true),
surface_state.SurfaceFormat =
isl_lower_storage_image_format(&device->isl_dev, iview->format);
surface_state.SurfaceMinLOD = range->baseMipLevel;
surface_state.MIPCountLOD = MAX2(range->levelCount, 1) - 1;
GENX(RENDER_SURFACE_STATE_pack)(NULL, iview->storage_surface_state.map,
&surface_state);
} else {
+53 -37
View File
@@ -162,16 +162,19 @@ get_qpitch(const struct isl_surf *surf)
}
}
void
genX(image_view_init)(struct anv_image_view *iview,
struct anv_device *device,
const VkImageViewCreateInfo* pCreateInfo,
struct anv_cmd_buffer *cmd_buffer)
static struct GENX(RENDER_SURFACE_STATE)
surface_state_for_image_view(struct anv_image_view *iview,
struct anv_device *device,
const VkImageViewCreateInfo *pCreateInfo,
VkImageUsageFlagBits usage)
{
assert(usage & (VK_IMAGE_USAGE_SAMPLED_BIT |
VK_IMAGE_USAGE_STORAGE_BIT |
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT));
assert(util_is_power_of_two(usage));
ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
const VkImageSubresourceRange *range = &pCreateInfo->subresourceRange;
struct anv_surface *surface =
anv_image_get_surface_for_aspect_mask(image, range->aspectMask);
@@ -188,9 +191,12 @@ genX(image_view_init)(struct anv_image_view *iview,
get_halign_valign(&surface->isl, &halign, &valign);
struct GENX(RENDER_SURFACE_STATE) template = {
.SurfaceType = anv_surftype(image, pCreateInfo->viewType, false),
.SurfaceType = anv_surftype(image, pCreateInfo->viewType,
usage == VK_IMAGE_USAGE_STORAGE_BIT),
.SurfaceArray = image->array_size > 1,
.SurfaceFormat = iview->format,
.SurfaceFormat = (usage != VK_IMAGE_USAGE_STORAGE_BIT ? iview->format :
isl_lower_storage_image_format(
&device->isl_dev, iview->format)),
.SurfaceVerticalAlignment = valign,
.SurfaceHorizontalAlignment = halign,
.TileMode = isl_to_gen_tiling[surface->isl.tiling],
@@ -295,18 +301,42 @@ genX(image_view_init)(struct anv_image_view *iview,
unreachable(!"bad SurfaceType");
}
if (image->needs_nonrt_surface_state) {
struct GENX(RENDER_SURFACE_STATE) surface_state = template;
iview->nonrt_surface_state =
alloc_surface_state(device, cmd_buffer);
if (usage == VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
/* For render target surfaces, the hardware interprets field
* MIPCount/LOD as LOD. The Broadwell PRM says:
*
* MIPCountLOD defines the LOD that will be rendered into.
* SurfaceMinLOD is ignored.
*/
template.MIPCountLOD = range->baseMipLevel;
template.SurfaceMinLOD = 0;
} else {
/* For non render target surfaces, the hardware interprets field
* MIPCount/LOD as MIPCount. The range of levels accessible by the
* sampler engine is [SurfaceMinLOD, SurfaceMinLOD + MIPCountLOD].
*/
surface_state.SurfaceMinLOD = range->baseMipLevel;
surface_state.MIPCountLOD = MAX2(range->levelCount, 1) - 1;
template.SurfaceMinLOD = range->baseMipLevel;
template.MIPCountLOD = MAX2(range->levelCount, 1) - 1;
}
return template;
}
void
genX(image_view_init)(struct anv_image_view *iview,
struct anv_device *device,
const VkImageViewCreateInfo* pCreateInfo,
struct anv_cmd_buffer *cmd_buffer)
{
ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
if (image->needs_nonrt_surface_state) {
const struct GENX(RENDER_SURFACE_STATE) surface_state =
surface_state_for_image_view(iview, device, pCreateInfo,
VK_IMAGE_USAGE_SAMPLED_BIT);
iview->nonrt_surface_state =
alloc_surface_state(device, cmd_buffer);
GENX(RENDER_SURFACE_STATE_pack)(NULL, iview->nonrt_surface_state.map,
&surface_state);
@@ -317,20 +347,13 @@ genX(image_view_init)(struct anv_image_view *iview,
}
if (image->needs_color_rt_surface_state) {
struct GENX(RENDER_SURFACE_STATE) surface_state = template;
const struct GENX(RENDER_SURFACE_STATE) surface_state =
surface_state_for_image_view(iview, device, pCreateInfo,
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
iview->color_rt_surface_state =
alloc_surface_state(device, cmd_buffer);
/* For render target surfaces, the hardware interprets field
* MIPCount/LOD as LOD. The Broadwell PRM says:
*
* MIPCountLOD defines the LOD that will be rendered into.
* SurfaceMinLOD is ignored.
*/
surface_state.MIPCountLOD = range->baseMipLevel;
surface_state.SurfaceMinLOD = 0;
GENX(RENDER_SURFACE_STATE_pack)(NULL, iview->color_rt_surface_state.map,
&surface_state);
if (!device->info.has_llc)
@@ -340,20 +363,13 @@ genX(image_view_init)(struct anv_image_view *iview,
}
if (image->needs_storage_surface_state) {
struct GENX(RENDER_SURFACE_STATE) surface_state = template;
struct GENX(RENDER_SURFACE_STATE) surface_state =
surface_state_for_image_view(iview, device, pCreateInfo,
VK_IMAGE_USAGE_STORAGE_BIT);
iview->storage_surface_state =
alloc_surface_state(device, cmd_buffer);
surface_state.SurfaceType =
anv_surftype(image, pCreateInfo->viewType, true),
surface_state.SurfaceFormat =
isl_lower_storage_image_format(&device->isl_dev, iview->format);
surface_state.SurfaceMinLOD = range->baseMipLevel;
surface_state.MIPCountLOD = MAX2(range->levelCount, 1) - 1;
GENX(RENDER_SURFACE_STATE_pack)(NULL, iview->storage_surface_state.map,
&surface_state);
} else {