Vulkan CP: Use the color blitter

This commit is contained in:
Dr. Chat
2017-05-13 10:15:56 -05:00
parent a41cf1a9ba
commit 84758a3a3f
7 changed files with 267 additions and 68 deletions

View File

@@ -311,7 +311,7 @@ void TextureCache::DestroyEmptySet() {
}
TextureCache::Texture* TextureCache::AllocateTexture(
const TextureInfo& texture_info) {
const TextureInfo& texture_info, VkFormatFeatureFlags required_flags) {
// Create an image first.
VkImageCreateInfo image_info = {};
image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
@@ -341,18 +341,24 @@ TextureCache::Texture* TextureCache::AllocateTexture(
: VK_FORMAT_R8G8B8A8_UNORM;
image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
image_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT |
VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
VK_IMAGE_USAGE_TRANSFER_DST_BIT;
image_info.usage =
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
// Check the device limits for the format before we create it.
VkFormatProperties props;
vkGetPhysicalDeviceFormatProperties(*device_, format, &props);
uint32_t required_flags =
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT;
if ((props.optimalTilingFeatures & required_flags) != required_flags) {
// Texture needs conversion on upload to a native format.
// assert_always();
assert_always();
}
if (props.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) {
// Add color attachment usage if it's supported.
image_info.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
}
if (props.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_DST_BIT) {
image_info.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
}
VkImageFormatProperties image_props;
@@ -413,6 +419,10 @@ bool TextureCache::FreeTexture(Texture* texture) {
return false;
}
if (texture->framebuffer) {
vkDestroyFramebuffer(*device_, texture->framebuffer, nullptr);
}
for (auto it = texture->views.begin(); it != texture->views.end();) {
vkDestroyImageView(*device_, (*it)->view, nullptr);
it = texture->views.erase(it);
@@ -449,7 +459,9 @@ TextureCache::Texture* TextureCache::DemandResolveTexture(
}
// No texture at this location. Make a new one.
auto texture = AllocateTexture(texture_info);
auto texture =
AllocateTexture(texture_info, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT);
// Setup a debug name for the texture.
device_->DbgSetObjectName(
@@ -965,23 +977,30 @@ void TextureCache::ConvertTexture2D(uint8_t* dest, const TextureInfo& src) {
uint32_t offset_x;
uint32_t offset_y;
TextureInfo::GetPackedTileOffset(src, &offset_x, &offset_y);
auto bpp = (bytes_per_block >> 2) +
((bytes_per_block >> 1) >> (bytes_per_block >> 2));
for (uint32_t y = 0, output_base_offset = 0;
y < std::min(src.size_2d.block_height, src.size_2d.logical_height);
y++, output_base_offset += src.size_2d.output_pitch) {
auto input_base_offset = TextureInfo::TiledOffset2DOuter(
offset_y + y,
(src.size_2d.input_width / src.format_info()->block_width), bpp);
for (uint32_t x = 0, output_offset = output_base_offset;
x < src.size_2d.block_width; x++, output_offset += bytes_per_block) {
auto log2_bpp = (bytes_per_block >> 2) +
((bytes_per_block >> 1) >> (bytes_per_block >> 2));
// Offset to the current row, in bytes.
uint32_t output_row_offset = 0;
for (uint32_t y = 0; y < src.size_2d.block_height; y++) {
auto input_row_offset = TextureInfo::TiledOffset2DOuter(
offset_y + y, src.size_2d.block_width, log2_bpp);
// Go block-by-block on this row.
uint32_t output_offset = output_row_offset;
for (uint32_t x = 0; x < src.size_2d.block_width; x++) {
auto input_offset =
TextureInfo::TiledOffset2DInner(offset_x + x, offset_y + y, bpp,
input_base_offset) >>
bpp;
TextureInfo::TiledOffset2DInner(offset_x + x, offset_y + y,
log2_bpp, input_row_offset) >>
log2_bpp;
TextureSwap(src.endianness, dest + output_offset,
src_mem + input_offset * bytes_per_block, bytes_per_block);
output_offset += bytes_per_block;
}
output_row_offset += src.size_2d.output_pitch;
}
}
}
@@ -1174,6 +1193,13 @@ bool TextureCache::UploadTexture2D(VkCommandBuffer command_buffer,
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.image = dest->image;
barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
if (dest->format == VK_FORMAT_D16_UNORM_S8_UINT ||
dest->format == VK_FORMAT_D24_UNORM_S8_UINT ||
dest->format == VK_FORMAT_D32_SFLOAT_S8_UINT) {
barrier.subresourceRange.aspectMask =
VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
}
vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, nullptr, 0,
nullptr, 1, &barrier);