blob: 61044f9b39c0b3af5be989ce0ab377113c5e4369 [file] [log] [blame]
/*
*
* Copyright (C) 2015-2016 Valve Corporation
* Copyright (C) 2015-2016 LunarG, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Author: Chia-I Wu <olv@lunarg.com>
* Author: Chris Forbes <chrisf@ijw.co.nz>
*
*/
#include "buf.h"
#include "img.h"
#include "mem.h"
#include "state.h"
#include "cmd_priv.h"
#include "fb.h"
static VkResult cmd_meta_create_buf_view(struct intel_cmd *cmd,
VkBuffer buf,
VkDeviceSize range,
VkFormat format,
struct intel_buf_view **view)
{
VkBufferViewCreateInfo info;
VkDeviceSize stride;
memset(&info, 0, sizeof(info));
info.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO;
info.buffer = buf;
info.format = format;
info.range = range;
/*
* We do not rely on the hardware to avoid out-of-bound access. But we do
* not want the hardware to ignore the last element either.
*/
stride = icd_format_get_size(format);
if (info.range % stride)
info.range += stride - (info.range % stride);
return intel_buf_view_create(cmd->dev, &info, view);
}
static void cmd_meta_set_src_for_buf(struct intel_cmd *cmd,
const struct intel_buf *buf,
VkFormat format,
struct intel_cmd_meta *meta)
{
struct intel_buf_view *view;
VkResult res;
VkBuffer localbuf = (VkBuffer) buf;
res = cmd_meta_create_buf_view(cmd, localbuf,
buf->size, format, &view);
if (res != VK_SUCCESS) {
cmd_fail(cmd, res);
return;
}
meta->src.valid = true;
memcpy(meta->src.surface, view->cmd,
sizeof(view->cmd[0]) * view->cmd_len);
meta->src.surface_len = view->cmd_len;
intel_buf_view_destroy(view);
meta->src.reloc_target = (intptr_t) buf->obj.mem->bo;
meta->src.reloc_offset = 0;
meta->src.reloc_flags = 0;
}
static void cmd_meta_set_dst_for_buf(struct intel_cmd *cmd,
const struct intel_buf *buf,
VkFormat format,
struct intel_cmd_meta *meta)
{
struct intel_buf_view *view;
VkResult res;
VkBuffer localbuf = (VkBuffer) buf;
res = cmd_meta_create_buf_view(cmd, localbuf,
buf->size, format, &view);
if (res != VK_SUCCESS) {
cmd_fail(cmd, res);
return;
}
meta->dst.valid = true;
memcpy(meta->dst.surface, view->cmd,
sizeof(view->cmd[0]) * view->cmd_len);
meta->dst.surface_len = view->cmd_len;
intel_buf_view_destroy(view);
meta->dst.reloc_target = (intptr_t) buf->obj.mem->bo;
meta->dst.reloc_offset = 0;
meta->dst.reloc_flags = INTEL_RELOC_WRITE;
}
static void cmd_meta_set_src_for_img(struct intel_cmd *cmd,
const struct intel_img *img,
VkFormat format,
VkImageAspectFlagBits aspect,
struct intel_cmd_meta *meta)
{
VkImageViewCreateInfo info;
struct intel_img_view tmp_view;
struct intel_img_view *view = &tmp_view;
memset(&tmp_view, 0, sizeof(tmp_view));
memset(&info, 0, sizeof(info));
info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
info.image = (VkImage) img;
if (img->array_size == 1) {
switch (img->type) {
case VK_IMAGE_TYPE_1D:
info.viewType = VK_IMAGE_VIEW_TYPE_1D;
break;
case VK_IMAGE_TYPE_2D:
info.viewType = VK_IMAGE_VIEW_TYPE_2D;
break;
default:
break;
}
} else {
switch (img->type) {
case VK_IMAGE_TYPE_1D:
info.viewType = VK_IMAGE_VIEW_TYPE_1D_ARRAY;
break;
case VK_IMAGE_TYPE_2D:
info.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
break;
case VK_IMAGE_TYPE_3D:
info.viewType = VK_IMAGE_VIEW_TYPE_3D;
break;
default:
break;
}
}
info.format = format;
info.components.r = VK_COMPONENT_SWIZZLE_R;
info.components.g = VK_COMPONENT_SWIZZLE_G;
info.components.b = VK_COMPONENT_SWIZZLE_B;
info.components.a = VK_COMPONENT_SWIZZLE_A;
info.subresourceRange.aspectMask = aspect;
info.subresourceRange.baseMipLevel = 0;
info.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
info.subresourceRange.baseArrayLayer = 0;
info.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
intel_img_view_init(cmd->dev, &info, view);
meta->src.valid = true;
memcpy(meta->src.surface, view->cmd,
sizeof(view->cmd[0]) * view->cmd_len);
meta->src.surface_len = view->cmd_len;
meta->src.reloc_target = (intptr_t) img->obj.mem->bo;
meta->src.reloc_offset = 0;
meta->src.reloc_flags = 0;
/* Don't need tmp_view anymore */
}
static void cmd_meta_adjust_compressed_dst(struct intel_cmd *cmd,
const struct intel_img *img,
struct intel_cmd_meta *meta)
{
int32_t w, h, layer;
unsigned x_offset, y_offset;
if (cmd_gen(cmd) >= INTEL_GEN(7)) {
w = GEN_EXTRACT(meta->dst.surface[2], GEN7_SURFACE_DW2_WIDTH);
h = GEN_EXTRACT(meta->dst.surface[2], GEN7_SURFACE_DW2_HEIGHT);
layer = GEN_EXTRACT(meta->dst.surface[4],
GEN7_SURFACE_DW4_MIN_ARRAY_ELEMENT);
} else {
w = GEN_EXTRACT(meta->dst.surface[2], GEN6_SURFACE_DW2_WIDTH);
h = GEN_EXTRACT(meta->dst.surface[2], GEN6_SURFACE_DW2_HEIGHT);
layer = GEN_EXTRACT(meta->dst.surface[4],
GEN6_SURFACE_DW4_MIN_ARRAY_ELEMENT);
}
/* note that the width/height fields have the real values minus 1 */
w = (w + img->layout.block_width) / img->layout.block_width - 1;
h = (h + img->layout.block_height) / img->layout.block_height - 1;
/* adjust width and height */
if (cmd_gen(cmd) >= INTEL_GEN(7)) {
meta->dst.surface[2] &= ~(GEN7_SURFACE_DW2_WIDTH__MASK |
GEN7_SURFACE_DW2_HEIGHT__MASK);
meta->dst.surface[2] |= GEN_SHIFT32(w, GEN7_SURFACE_DW2_WIDTH) |
GEN_SHIFT32(h, GEN7_SURFACE_DW2_HEIGHT);
} else {
meta->dst.surface[2] &= ~(GEN6_SURFACE_DW2_WIDTH__MASK |
GEN6_SURFACE_DW2_HEIGHT__MASK);
meta->dst.surface[2] |= GEN_SHIFT32(w, GEN6_SURFACE_DW2_WIDTH) |
GEN_SHIFT32(h, GEN6_SURFACE_DW2_HEIGHT);
}
if (!layer)
return;
meta->dst.reloc_offset = intel_layout_get_slice_tile_offset(&img->layout,
0, layer, &x_offset, &y_offset);
/*
* The lower 2 bits (or 1 bit for Y) are missing. This may be a problem
* for small images (16x16 or smaller). We will need to adjust the
* drawing rectangle instead.
*/
x_offset = (x_offset / img->layout.block_width) >> 2;
y_offset = (y_offset / img->layout.block_height) >> 1;
/* adjust min array element and X/Y offsets */
if (cmd_gen(cmd) >= INTEL_GEN(7)) {
meta->dst.surface[4] &= ~GEN7_SURFACE_DW4_MIN_ARRAY_ELEMENT__MASK;
meta->dst.surface[5] |= GEN_SHIFT32(x_offset, GEN7_SURFACE_DW5_X_OFFSET) |
GEN_SHIFT32(y_offset, GEN7_SURFACE_DW5_Y_OFFSET);
} else {
meta->dst.surface[4] &= ~GEN6_SURFACE_DW4_MIN_ARRAY_ELEMENT__MASK;
meta->dst.surface[5] |= GEN_SHIFT32(x_offset, GEN6_SURFACE_DW5_X_OFFSET) |
GEN_SHIFT32(y_offset, GEN6_SURFACE_DW5_Y_OFFSET);
}
}
static void cmd_meta_set_dst_for_img(struct intel_cmd *cmd,
const struct intel_img *img,
VkFormat format,
uint32_t lod, uint32_t layer,
struct intel_cmd_meta *meta)
{
struct intel_att_view tmp_view;
struct intel_att_view *view = &tmp_view;
VkImageViewCreateInfo info;
memset(&info, 0, sizeof(info));
info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
info.image = (VkImage) img;
info.format = format;
info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
info.subresourceRange.baseMipLevel = lod;
info.subresourceRange.levelCount = 1;
info.subresourceRange.baseArrayLayer = layer;
info.subresourceRange.layerCount = 1;
intel_att_view_init(cmd->dev, &info, view);
meta->dst.valid = true;
memcpy(meta->dst.surface, view->att_cmd,
sizeof(view->att_cmd[0]) * view->cmd_len);
meta->dst.surface_len = view->cmd_len;
meta->dst.reloc_target = (intptr_t) img->obj.mem->bo;
meta->dst.reloc_offset = 0;
meta->dst.reloc_flags = INTEL_RELOC_WRITE;
if (icd_format_is_compressed(img->layout.format))
cmd_meta_adjust_compressed_dst(cmd, img, meta);
}
static void cmd_meta_set_src_for_writer(struct intel_cmd *cmd,
enum intel_cmd_writer_type writer,
VkDeviceSize size,
VkFormat format,
struct intel_cmd_meta *meta)
{
struct intel_buf_view *view;
VkResult res;
VkBuffer localbuf = VK_NULL_HANDLE;
res = cmd_meta_create_buf_view(cmd, localbuf,
size, format, &view);
if (res != VK_SUCCESS) {
cmd_fail(cmd, res);
return;
}
meta->src.valid = true;
memcpy(meta->src.surface, view->cmd,
sizeof(view->cmd[0]) * view->cmd_len);
meta->src.surface_len = view->cmd_len;
intel_buf_view_destroy(view);
meta->src.reloc_target = (intptr_t) writer;
meta->src.reloc_offset = 0;
meta->src.reloc_flags = INTEL_CMD_RELOC_TARGET_IS_WRITER;
}
static void cmd_meta_set_ds_view(struct intel_cmd *cmd,
const struct intel_img *img,
uint32_t lod, uint32_t layer,
struct intel_cmd_meta *meta)
{
VkImageViewCreateInfo info;
memset(&info, 0, sizeof(info));
info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
info.image = (VkImage) img;
info.subresourceRange.baseMipLevel = lod;
info.subresourceRange.levelCount = 1;
info.subresourceRange.baseArrayLayer = layer;
info.subresourceRange.layerCount = 1;
intel_att_view_init(cmd->dev, &info, &meta->ds.view);
}
static void cmd_meta_set_ds_state(struct intel_cmd *cmd,
VkImageAspectFlagBits aspect,
uint32_t stencil_ref,
struct intel_cmd_meta *meta)
{
meta->ds.stencil_ref = stencil_ref;
meta->ds.aspect = aspect;
}
static enum intel_dev_meta_shader get_shader_id(const struct intel_dev *dev,
const struct intel_img *img,
bool copy_array)
{
enum intel_dev_meta_shader shader_id;
switch (img->type) {
case VK_IMAGE_TYPE_1D:
shader_id = (copy_array) ?
INTEL_DEV_META_FS_COPY_1D_ARRAY : INTEL_DEV_META_FS_COPY_1D;
break;
case VK_IMAGE_TYPE_2D:
shader_id = (img->sample_count > 1) ? INTEL_DEV_META_FS_COPY_2D_MS :
(copy_array) ? INTEL_DEV_META_FS_COPY_2D_ARRAY :
INTEL_DEV_META_FS_COPY_2D;
break;
case VK_IMAGE_TYPE_3D:
default:
shader_id = INTEL_DEV_META_FS_COPY_2D_ARRAY;
break;
}
return shader_id;
}
static bool cmd_meta_mem_dword_aligned(const struct intel_cmd *cmd,
VkDeviceSize src_offset,
VkDeviceSize dst_offset,
VkDeviceSize size)
{
return !((src_offset | dst_offset | size) & 0x3);
}
static VkFormat cmd_meta_img_raw_format(const struct intel_cmd *cmd,
VkFormat format)
{
switch (icd_format_get_size(format)) {
case 1:
format = VK_FORMAT_R8_UINT;
break;
case 2:
format = VK_FORMAT_R16_UINT;
break;
case 4:
format = VK_FORMAT_R32_UINT;
break;
case 8:
format = VK_FORMAT_R32G32_UINT;
break;
case 16:
format = VK_FORMAT_R32G32B32A32_UINT;
break;
default:
assert(!"unsupported image format for raw blit op");
format = VK_FORMAT_UNDEFINED;
break;
}
return format;
}
VKAPI_ATTR void VKAPI_CALL vkCmdCopyBuffer(
VkCommandBuffer commandBuffer,
VkBuffer srcBuffer,
VkBuffer dstBuffer,
uint32_t regionCount,
const VkBufferCopy* pRegions)
{
struct intel_cmd *cmd = intel_cmd(commandBuffer);
struct intel_buf *src = intel_buf(srcBuffer);
struct intel_buf *dst = intel_buf(dstBuffer);
struct intel_cmd_meta meta;
VkFormat format;
uint32_t i;
memset(&meta, 0, sizeof(meta));
meta.mode = INTEL_CMD_META_VS_POINTS;
meta.height = 1;
meta.sample_count = 1;
format = VK_FORMAT_UNDEFINED;
for (i = 0; i < regionCount; i++) {
const VkBufferCopy *region = &pRegions[i];
VkFormat fmt;
meta.src.x = region->srcOffset;
meta.dst.x = region->dstOffset;
meta.width = region->size;
if (cmd_meta_mem_dword_aligned(cmd, region->srcOffset,
region->dstOffset, region->size)) {
meta.shader_id = INTEL_DEV_META_VS_COPY_MEM;
meta.src.x /= 4;
meta.dst.x /= 4;
meta.width /= 4;
/*
* INTEL_DEV_META_VS_COPY_MEM is untyped but expects the stride to
* be 16
*/
fmt = VK_FORMAT_R32G32B32A32_UINT;
} else {
if (cmd_gen(cmd) == INTEL_GEN(6)) {
intel_dev_log(cmd->dev, VK_DEBUG_REPORT_ERROR_BIT_EXT,
&cmd->obj.base, 0, 0,
"unaligned vkCmdCopyBuffer unsupported");
cmd_fail(cmd, VK_ERROR_VALIDATION_FAILED_EXT);
continue;
}
meta.shader_id = INTEL_DEV_META_VS_COPY_MEM_UNALIGNED;
/*
* INTEL_DEV_META_VS_COPY_MEM_UNALIGNED is untyped but expects the
* stride to be 4
*/
fmt = VK_FORMAT_R8G8B8A8_UINT;
}
if (format != fmt) {
format = fmt;
cmd_meta_set_src_for_buf(cmd, src, format, &meta);
cmd_meta_set_dst_for_buf(cmd, dst, format, &meta);
}
cmd_draw_meta(cmd, &meta);
}
}
VKAPI_ATTR void VKAPI_CALL vkCmdCopyImage(
VkCommandBuffer commandBuffer,
VkImage srcImage,
VkImageLayout srcImageLayout,
VkImage dstImage,
VkImageLayout dstImageLayout,
uint32_t regionCount,
const VkImageCopy* pRegions)
{
struct intel_cmd *cmd = intel_cmd(commandBuffer);
struct intel_img *src = intel_img(srcImage);
struct intel_img *dst = intel_img(dstImage);
struct intel_cmd_meta meta;
VkFormat raw_format;
bool raw_copy = false;
uint32_t i;
if (src->layout.format == dst->layout.format) {
raw_copy = true;
raw_format = cmd_meta_img_raw_format(cmd, src->layout.format);
} else {
assert(!(icd_format_is_compressed(src->layout.format) ||
icd_format_is_compressed(dst->layout.format)) && "Compressed formats not supported");
}
memset(&meta, 0, sizeof(meta));
meta.mode = INTEL_CMD_META_FS_RECT;
cmd_meta_set_src_for_img(cmd, src,
(raw_copy) ? raw_format : src->layout.format,
VK_IMAGE_ASPECT_COLOR_BIT, &meta);
meta.sample_count = dst->sample_count;
for (i = 0; i < regionCount; i++) {
const VkImageCopy *region = &pRegions[i];
uint32_t j;
meta.shader_id = get_shader_id(cmd->dev, src,
(region->extent.depth > 1));
meta.src.lod = region->srcSubresource.mipLevel;
meta.src.layer = region->srcSubresource.baseArrayLayer +
region->srcOffset.z;
meta.src.x = region->srcOffset.x;
meta.src.y = region->srcOffset.y;
meta.dst.lod = region->dstSubresource.mipLevel;
meta.dst.layer = region->dstSubresource.baseArrayLayer +
region->dstOffset.z;
meta.dst.x = region->dstOffset.x;
meta.dst.y = region->dstOffset.y;
meta.width = region->extent.width;
meta.height = region->extent.height;
if (raw_copy) {
const uint32_t block_width =
icd_format_get_block_width(raw_format);
meta.src.x /= block_width;
meta.src.y /= block_width;
meta.dst.x /= block_width;
meta.dst.y /= block_width;
meta.width /= block_width;
meta.height /= block_width;
}
for (j = 0; j < region->extent.depth; j++) {
cmd_meta_set_dst_for_img(cmd, dst,
(raw_copy) ? raw_format : dst->layout.format,
meta.dst.lod, meta.dst.layer, &meta);
cmd_draw_meta(cmd, &meta);
meta.src.layer++;
meta.dst.layer++;
}
}
}
VKAPI_ATTR void VKAPI_CALL vkCmdBlitImage(
VkCommandBuffer commandBuffer,
VkImage srcImage,
VkImageLayout srcImageLayout,
VkImage dstImage,
VkImageLayout dstImageLayout,
uint32_t regionCount,
const VkImageBlit* pRegions,
VkFilter filter)
{
/*
* TODO: Implement actual blit function.
*/
assert(0 && "vkCmdBlitImage not implemented");
}
VKAPI_ATTR void VKAPI_CALL vkCmdCopyBufferToImage(
VkCommandBuffer commandBuffer,
VkBuffer srcBuffer,
VkImage dstImage,
VkImageLayout dstImageLayout,
uint32_t regionCount,
const VkBufferImageCopy* pRegions)
{
struct intel_cmd *cmd = intel_cmd(commandBuffer);
struct intel_buf *buf = intel_buf(srcBuffer);
struct intel_img *img = intel_img(dstImage);
struct intel_cmd_meta meta;
VkFormat format;
uint32_t block_width, i;
memset(&meta, 0, sizeof(meta));
meta.mode = INTEL_CMD_META_FS_RECT;
meta.shader_id = INTEL_DEV_META_FS_COPY_MEM_TO_IMG;
meta.sample_count = img->sample_count;
format = cmd_meta_img_raw_format(cmd, img->layout.format);
block_width = icd_format_get_block_width(img->layout.format);
cmd_meta_set_src_for_buf(cmd, buf, format, &meta);
for (i = 0; i < regionCount; i++) {
const VkBufferImageCopy *region = &pRegions[i];
uint32_t j;
meta.src.x = region->bufferOffset / icd_format_get_size(format);
meta.dst.lod = region->imageSubresource.mipLevel;
meta.dst.layer = region->imageSubresource.baseArrayLayer +
region->imageOffset.z;
meta.dst.x = region->imageOffset.x / block_width;
meta.dst.y = region->imageOffset.y / block_width;
meta.width = region->imageExtent.width / block_width;
meta.height = region->imageExtent.height / block_width;
for (j = 0; j < region->imageExtent.depth; j++) {
cmd_meta_set_dst_for_img(cmd, img, format,
meta.dst.lod, meta.dst.layer, &meta);
cmd_draw_meta(cmd, &meta);
meta.src.x += meta.width * meta.height;
meta.dst.layer++;
}
}
}
VKAPI_ATTR void VKAPI_CALL vkCmdCopyImageToBuffer(
VkCommandBuffer commandBuffer,
VkImage srcImage,
VkImageLayout srcImageLayout,
VkBuffer dstBuffer,
uint32_t regionCount,
const VkBufferImageCopy* pRegions)
{
struct intel_cmd *cmd = intel_cmd(commandBuffer);
struct intel_img *img = intel_img(srcImage);
struct intel_buf *buf = intel_buf(dstBuffer);
struct intel_cmd_meta meta;
VkFormat img_format, buf_format;
uint32_t block_width, i;
memset(&meta, 0, sizeof(meta));
meta.mode = INTEL_CMD_META_VS_POINTS;
img_format = cmd_meta_img_raw_format(cmd, img->layout.format);
block_width = icd_format_get_block_width(img_format);
/* buf_format is ignored by hw, but we derive stride from it */
switch (img_format) {
case VK_FORMAT_R8_UINT:
meta.shader_id = INTEL_DEV_META_VS_COPY_R8_TO_MEM;
buf_format = VK_FORMAT_R8G8B8A8_UINT;
break;
case VK_FORMAT_R16_UINT:
meta.shader_id = INTEL_DEV_META_VS_COPY_R16_TO_MEM;
buf_format = VK_FORMAT_R8G8B8A8_UINT;
break;
case VK_FORMAT_R32_UINT:
meta.shader_id = INTEL_DEV_META_VS_COPY_R32_TO_MEM;
buf_format = VK_FORMAT_R32G32B32A32_UINT;
break;
case VK_FORMAT_R32G32_UINT:
meta.shader_id = INTEL_DEV_META_VS_COPY_R32G32_TO_MEM;
buf_format = VK_FORMAT_R32G32B32A32_UINT;
break;
case VK_FORMAT_R32G32B32A32_UINT:
meta.shader_id = INTEL_DEV_META_VS_COPY_R32G32B32A32_TO_MEM;
buf_format = VK_FORMAT_R32G32B32A32_UINT;
break;
default:
img_format = VK_FORMAT_UNDEFINED;
buf_format = VK_FORMAT_UNDEFINED;
break;
}
if (img_format == VK_FORMAT_UNDEFINED ||
(cmd_gen(cmd) == INTEL_GEN(6) &&
icd_format_get_size(img_format) < 4)) {
intel_dev_log(cmd->dev, VK_DEBUG_REPORT_ERROR_BIT_EXT,
&cmd->obj.base, 0, 0,
"vkCmdCopyImageToBuffer with bpp %d unsupported",
icd_format_get_size(img->layout.format));
return;
}
cmd_meta_set_src_for_img(cmd, img, img_format,
VK_IMAGE_ASPECT_COLOR_BIT, &meta);
cmd_meta_set_dst_for_buf(cmd, buf, buf_format, &meta);
meta.sample_count = 1;
for (i = 0; i < regionCount; i++) {
const VkBufferImageCopy *region = &pRegions[i];
uint32_t j;
meta.src.lod = region->imageSubresource.mipLevel;
meta.src.layer = region->imageSubresource.baseArrayLayer +
region->imageOffset.z;
meta.src.x = region->imageOffset.x / block_width;
meta.src.y = region->imageOffset.y / block_width;
meta.dst.x = region->bufferOffset / icd_format_get_size(img_format);
meta.width = region->imageExtent.width / block_width;
meta.height = region->imageExtent.height / block_width;
for (j = 0; j < region->imageExtent.depth; j++) {
cmd_draw_meta(cmd, &meta);
meta.src.layer++;
meta.dst.x += meta.width * meta.height;
}
}
}
VKAPI_ATTR void VKAPI_CALL vkCmdUpdateBuffer(
VkCommandBuffer commandBuffer,
VkBuffer dstBuffer,
VkDeviceSize dstOffset,
VkDeviceSize dataSize,
const void* pData)
{
struct intel_cmd *cmd = intel_cmd(commandBuffer);
struct intel_buf *dst = intel_buf(dstBuffer);
struct intel_cmd_meta meta;
VkFormat format;
uint32_t *ptr;
uint32_t offset;
/* write to dynamic state writer first */
offset = cmd_state_pointer(cmd, INTEL_CMD_ITEM_BLOB, 32,
(dataSize + 3) / 4, &ptr);
memcpy(ptr, pData, dataSize);
memset(&meta, 0, sizeof(meta));
meta.mode = INTEL_CMD_META_VS_POINTS;
meta.shader_id = INTEL_DEV_META_VS_COPY_MEM;
meta.src.x = offset / 4;
meta.dst.x = dstOffset / 4;
meta.width = dataSize / 4;
meta.height = 1;
meta.sample_count = 1;
/*
* INTEL_DEV_META_VS_COPY_MEM is untyped but expects the stride to be 16
*/
format = VK_FORMAT_R32G32B32A32_UINT;
cmd_meta_set_src_for_writer(cmd, INTEL_CMD_WRITER_STATE,
offset + dataSize, format, &meta);
cmd_meta_set_dst_for_buf(cmd, dst, format, &meta);
cmd_draw_meta(cmd, &meta);
}
VKAPI_ATTR void VKAPI_CALL vkCmdFillBuffer(
VkCommandBuffer commandBuffer,
VkBuffer dstBuffer,
VkDeviceSize dstOffset,
VkDeviceSize size,
uint32_t data)
{
struct intel_cmd *cmd = intel_cmd(commandBuffer);
struct intel_buf *dst = intel_buf(dstBuffer);
struct intel_cmd_meta meta;
VkFormat format;
memset(&meta, 0, sizeof(meta));
meta.mode = INTEL_CMD_META_VS_POINTS;
meta.shader_id = INTEL_DEV_META_VS_FILL_MEM;
meta.clear_val[0] = data;
meta.dst.x = dstOffset / 4;
meta.width = size / 4;
meta.height = 1;
meta.sample_count = 1;
/*
* INTEL_DEV_META_VS_FILL_MEM is untyped but expects the stride to be 16
*/
format = VK_FORMAT_R32G32B32A32_UINT;
cmd_meta_set_dst_for_buf(cmd, dst, format, &meta);
cmd_draw_meta(cmd, &meta);
}
static void cmd_meta_clear_image(struct intel_cmd *cmd,
struct intel_img *img,
VkFormat format,
struct intel_cmd_meta *meta,
const VkImageSubresourceRange *range)
{
uint32_t mip_levels, array_size;
uint32_t i, j;
if (range->baseMipLevel >= img->mip_levels ||
range->baseArrayLayer >= img->array_size)
return;
mip_levels = img->mip_levels - range->baseMipLevel;
if (mip_levels > range->levelCount)
mip_levels = range->levelCount;
array_size = img->array_size - range->baseArrayLayer;
if (array_size > range->layerCount)
array_size = range->layerCount;
for (i = 0; i < mip_levels; i++) {
meta->dst.lod = range->baseMipLevel + i;
meta->dst.layer = range->baseArrayLayer;
/* TODO INTEL_CMD_META_DS_HIZ_CLEAR requires 8x4 aligned rectangle */
meta->width = u_minify(img->layout.width0, meta->dst.lod);
meta->height = u_minify(img->layout.height0, meta->dst.lod);
if (meta->ds.op != INTEL_CMD_META_DS_NOP &&
!intel_img_can_enable_hiz(img, meta->dst.lod))
continue;
for (j = 0; j < array_size; j++) {
if (range->aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) {
cmd_meta_set_dst_for_img(cmd, img, format,
meta->dst.lod, meta->dst.layer, meta);
cmd_draw_meta(cmd, meta);
} else {
cmd_meta_set_ds_view(cmd, img, meta->dst.lod,
meta->dst.layer, meta);
if (range->aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) {
cmd_meta_set_ds_state(cmd, VK_IMAGE_ASPECT_DEPTH_BIT,
meta->clear_val[1], meta);
cmd_draw_meta(cmd, meta);
}
if (range->aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) {
cmd_meta_set_ds_state(cmd, VK_IMAGE_ASPECT_STENCIL_BIT,
meta->clear_val[1], meta);
cmd_draw_meta(cmd, meta);
}
}
meta->dst.layer++;
}
}
}
void cmd_meta_ds_op(struct intel_cmd *cmd,
enum intel_cmd_meta_ds_op op,
struct intel_img *img,
const VkImageSubresourceRange *range)
{
struct intel_cmd_meta meta;
if (img->layout.aux != INTEL_LAYOUT_AUX_HIZ)
return;
if (!(range->aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)))
return;
memset(&meta, 0, sizeof(meta));
meta.mode = INTEL_CMD_META_DEPTH_STENCIL_RECT;
meta.sample_count = img->sample_count;
meta.ds.op = op;
meta.ds.optimal = true;
cmd_meta_clear_image(cmd, img, img->layout.format, &meta, range);
}
void cmd_meta_clear_color_image(
VkCommandBuffer commandBuffer,
struct intel_img *img,
VkImageLayout imageLayout,
const VkClearColorValue *pClearColor,
uint32_t rangeCount,
const VkImageSubresourceRange *pRanges)
{
struct intel_cmd *cmd = intel_cmd(commandBuffer);
struct intel_cmd_meta meta;
VkFormat format;
uint32_t i;
memset(&meta, 0, sizeof(meta));
meta.mode = INTEL_CMD_META_FS_RECT;
meta.shader_id = INTEL_DEV_META_FS_CLEAR_COLOR;
meta.sample_count = img->sample_count;
meta.clear_val[0] = pClearColor->uint32[0];
meta.clear_val[1] = pClearColor->uint32[1];
meta.clear_val[2] = pClearColor->uint32[2];
meta.clear_val[3] = pClearColor->uint32[3];
format = img->layout.format;
for (i = 0; i < rangeCount; i++) {
cmd_meta_clear_image(cmd, img, format, &meta, &pRanges[i]);
}
}
VKAPI_ATTR void VKAPI_CALL vkCmdClearColorImage(
VkCommandBuffer commandBuffer,
VkImage image,
VkImageLayout imageLayout,
const VkClearColorValue *pClearColor,
uint32_t rangeCount,
const VkImageSubresourceRange *pRanges)
{
struct intel_img *img = intel_img(image);
cmd_meta_clear_color_image(commandBuffer, img, imageLayout, pClearColor, rangeCount, pRanges);
}
void cmd_meta_clear_depth_stencil_image(
VkCommandBuffer commandBuffer,
struct intel_img* img,
VkImageLayout imageLayout,
float depth,
uint32_t stencil,
uint32_t rangeCount,
const VkImageSubresourceRange* pRanges)
{
struct intel_cmd *cmd = intel_cmd(commandBuffer);
struct intel_cmd_meta meta;
uint32_t i;
memset(&meta, 0, sizeof(meta));
meta.mode = INTEL_CMD_META_DEPTH_STENCIL_RECT;
meta.shader_id = INTEL_DEV_META_FS_CLEAR_DEPTH;
meta.sample_count = img->sample_count;
meta.clear_val[0] = u_fui(depth);
meta.clear_val[1] = stencil;
if (imageLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ||
imageLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL) {
meta.ds.optimal = true;
}
for (i = 0; i < rangeCount; i++) {
const VkImageSubresourceRange *range = &pRanges[i];
cmd_meta_clear_image(cmd, img, img->layout.format,
&meta, range);
}
}
VKAPI_ATTR void VKAPI_CALL vkCmdClearDepthStencilImage(
VkCommandBuffer commandBuffer,
VkImage image,
VkImageLayout imageLayout,
const VkClearDepthStencilValue* pDepthStencil,
uint32_t rangeCount,
const VkImageSubresourceRange* pRanges)
{
struct intel_img *img = intel_img(image);
cmd_meta_clear_depth_stencil_image(commandBuffer, img, imageLayout, pDepthStencil->depth, pDepthStencil->stencil, rangeCount, pRanges);
}
static void cmd_clear_color_attachment(
VkCommandBuffer commandBuffer,
uint32_t colorAttachment,
VkImageLayout imageLayout,
const VkClearColorValue *pColor,
uint32_t rectCount,
const VkClearRect *pRects)
{
struct intel_cmd *cmd = intel_cmd(commandBuffer);
const struct intel_render_pass_subpass *subpass =
cmd->bind.render_pass_subpass;
const struct intel_fb *fb = cmd->bind.fb;
const struct intel_att_view *view =
fb->views[subpass->color_indices[colorAttachment]];
/* Convert each rect3d to clear into a subresource clear.
* TODO: this currently only supports full layer clears --
* cmd_meta_clear_color_image does not provide a means to
* specify the xy bounds.
*/
for (uint32_t i = 0; i < rectCount; i++) {
VkImageSubresourceRange range = {
VK_IMAGE_ASPECT_COLOR_BIT,
view->mipLevel,
1,
0,
1
};
cmd_meta_clear_color_image(commandBuffer, view->img,
imageLayout,
pColor,
1,
&range);
}
}
static void cmd_clear_depth_stencil_attachment(
VkCommandBuffer commandBuffer,
VkImageAspectFlags aspectMask,
VkImageLayout imageLayout,
const VkClearDepthStencilValue* pDepthStencil,
uint32_t rectCount,
const VkClearRect *pRects)
{
struct intel_cmd *cmd = intel_cmd(commandBuffer);
const struct intel_render_pass_subpass *subpass =
cmd->bind.render_pass_subpass;
const struct intel_fb *fb = cmd->bind.fb;
const struct intel_att_view *view = fb->views[subpass->ds_index];
/* Convert each rect3d to clear into a subresource clear.
* TODO: this currently only supports full layer clears --
* cmd_meta_clear_depth_stencil_image does not provide a means to
* specify the xy bounds.
*/
for (uint32_t i = 0; i < rectCount; i++) {
VkImageSubresourceRange range = {
aspectMask,
view->mipLevel,
1,
0,
1
};
cmd_meta_clear_depth_stencil_image(commandBuffer,
view->img, imageLayout,
pDepthStencil->depth, pDepthStencil->stencil, 1, &range);
}
}
VKAPI_ATTR void VKAPI_CALL vkCmdClearAttachments(
VkCommandBuffer commandBuffer,
uint32_t attachmentCount,
const VkClearAttachment* pAttachments,
uint32_t rectCount,
const VkClearRect* pRects)
{
struct intel_cmd *cmd = intel_cmd(commandBuffer);
for (uint32_t i = 0; i < attachmentCount; i++) {
if (pAttachments[i].aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) {
cmd_clear_color_attachment(
commandBuffer,
pAttachments[i].colorAttachment,
cmd->bind.render_pass->attachments[i].final_layout,
&pAttachments[i].clearValue.color,
rectCount,
pRects);
} else {
cmd_clear_depth_stencil_attachment(
commandBuffer,
pAttachments[i].aspectMask,
cmd->bind.render_pass_subpass->ds_layout,
&pAttachments[i].clearValue.depthStencil,
rectCount,
pRects);
}
}
}
VKAPI_ATTR void VKAPI_CALL vkCmdResolveImage(
VkCommandBuffer commandBuffer,
VkImage srcImage,
VkImageLayout srcImageLayout,
VkImage dstImage,
VkImageLayout dstImageLayout,
uint32_t regionCount,
const VkImageResolve* pRegions)
{
struct intel_cmd *cmd = intel_cmd(commandBuffer);
struct intel_img *src = intel_img(srcImage);
struct intel_img *dst = intel_img(dstImage);
struct intel_cmd_meta meta;
VkFormat format;
uint32_t i;
memset(&meta, 0, sizeof(meta));
meta.mode = INTEL_CMD_META_FS_RECT;
switch (src->sample_count) {
case 2:
default:
meta.shader_id = INTEL_DEV_META_FS_RESOLVE_2X;
break;
case 4:
meta.shader_id = INTEL_DEV_META_FS_RESOLVE_4X;
break;
case 8:
meta.shader_id = INTEL_DEV_META_FS_RESOLVE_8X;
break;
case 16:
meta.shader_id = INTEL_DEV_META_FS_RESOLVE_16X;
break;
}
meta.sample_count = 1;
format = cmd_meta_img_raw_format(cmd, src->layout.format);
cmd_meta_set_src_for_img(cmd, src, format, VK_IMAGE_ASPECT_COLOR_BIT, &meta);
for (i = 0; i < regionCount; i++) {
const VkImageResolve *region = &pRegions[i];
int arrayLayer;
for(arrayLayer = 0; arrayLayer < region->extent.depth; arrayLayer++) {
meta.src.lod = region->srcSubresource.mipLevel;
meta.src.layer = region->srcSubresource.baseArrayLayer + arrayLayer;
meta.src.x = region->srcOffset.x;
meta.src.y = region->srcOffset.y;
meta.dst.lod = region->dstSubresource.mipLevel;
meta.dst.layer = region->dstSubresource.baseArrayLayer + arrayLayer;
meta.dst.x = region->dstOffset.x;
meta.dst.y = region->dstOffset.y;
meta.width = region->extent.width;
meta.height = region->extent.height;
cmd_meta_set_dst_for_img(cmd, dst, format,
meta.dst.lod, meta.dst.layer, &meta);
cmd_draw_meta(cmd, &meta);
}
}
}