mirror of
https://github.com/EduApps-CDG/OpenDX
synced 2024-12-30 09:45:37 +01:00
[dxvk] Added proper support for block-compressed image formats
This commit is contained in:
parent
cd4f21a0c3
commit
c0f5b46f81
@ -421,6 +421,56 @@ namespace dxvk {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Upload data through a staging buffer. Special care needs to
|
||||||
|
// be taken when dealing with compressed image formats: Rather
|
||||||
|
// than copying pixels, we'll be copying blocks of pixels.
|
||||||
|
const DxvkFormatInfo* formatInfo
|
||||||
|
= imageFormatInfo(image->info().format);
|
||||||
|
|
||||||
|
VkExtent3D elementCount = imageExtent;
|
||||||
|
elementCount.depth *= subresources.layerCount;
|
||||||
|
|
||||||
|
elementCount.width /= formatInfo->blockSize.width;
|
||||||
|
elementCount.height /= formatInfo->blockSize.height;
|
||||||
|
elementCount.depth /= formatInfo->blockSize.depth;
|
||||||
|
|
||||||
|
VkDeviceSize bytesPerRow = elementCount.width * formatInfo->elementSize;
|
||||||
|
VkDeviceSize bytesPerLayer = elementCount.height * bytesPerRow;
|
||||||
|
VkDeviceSize bytesTotal = elementCount.depth * bytesPerLayer;
|
||||||
|
|
||||||
|
// Allocate staging buffer memory for the image data. The
|
||||||
|
// pixels or blocks will be tightly packed within the buffer.
|
||||||
|
DxvkStagingBufferSlice slice = m_cmd->stagedAlloc(bytesTotal);
|
||||||
|
|
||||||
|
auto dstData = reinterpret_cast<char*>(slice.mapPtr);
|
||||||
|
auto srcData = reinterpret_cast<const char*>(data);
|
||||||
|
|
||||||
|
// If the application provides tightly packed data as well,
|
||||||
|
// we can minimize the number of memcpy calls in order to
|
||||||
|
// improve performance.
|
||||||
|
bool useDirectCopy = true;
|
||||||
|
|
||||||
|
useDirectCopy &= (pitchPerLayer == bytesPerLayer) || (elementCount.depth == 1);
|
||||||
|
useDirectCopy &= (pitchPerRow == bytesPerRow) || (elementCount.height == 1);
|
||||||
|
|
||||||
|
if (useDirectCopy) {
|
||||||
|
std::memcpy(dstData, srcData, bytesTotal);
|
||||||
|
} else {
|
||||||
|
for (uint32_t i = 0; i < elementCount.depth; i++) {
|
||||||
|
for (uint32_t j = 0; j < elementCount.height; j++) {
|
||||||
|
std::memcpy(dstData, srcData, bytesPerRow);
|
||||||
|
|
||||||
|
dstData += bytesPerRow;
|
||||||
|
srcData += pitchPerRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
dstData += bytesPerLayer;
|
||||||
|
srcData += pitchPerLayer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare the image layout. If the given extent covers
|
||||||
|
// the entire image, we may discard its previous contents.
|
||||||
VkImageSubresourceRange subresourceRange;
|
VkImageSubresourceRange subresourceRange;
|
||||||
subresourceRange.aspectMask = subresources.aspectMask;
|
subresourceRange.aspectMask = subresources.aspectMask;
|
||||||
subresourceRange.baseMipLevel = subresources.mipLevel;
|
subresourceRange.baseMipLevel = subresources.mipLevel;
|
||||||
@ -440,39 +490,9 @@ namespace dxvk {
|
|||||||
VK_ACCESS_TRANSFER_WRITE_BIT);
|
VK_ACCESS_TRANSFER_WRITE_BIT);
|
||||||
m_barriers.recordCommands(m_cmd);
|
m_barriers.recordCommands(m_cmd);
|
||||||
|
|
||||||
// TODO support block formats properly
|
// Copy contents of the staging buffer into the image.
|
||||||
const DxvkFormatInfo* formatInfo
|
// Since our source data is tightly packed, we do not
|
||||||
= imageFormatInfo(image->info().format);
|
// need to specify any strides.
|
||||||
|
|
||||||
const VkDeviceSize layerCount = imageExtent.depth * subresources.layerCount;
|
|
||||||
VkDeviceSize bytesPerRow = imageExtent.width * formatInfo->elementSize;
|
|
||||||
VkDeviceSize bytesPerLayer = imageExtent.height * bytesPerRow;
|
|
||||||
VkDeviceSize bytesTotal = layerCount * bytesPerLayer;
|
|
||||||
|
|
||||||
auto slice = m_cmd->stagedAlloc(bytesTotal);
|
|
||||||
auto dstData = reinterpret_cast<char*>(slice.mapPtr);
|
|
||||||
auto srcData = reinterpret_cast<const char*>(data);
|
|
||||||
|
|
||||||
bool useDirectCopy = true;
|
|
||||||
useDirectCopy &= (pitchPerLayer == bytesPerLayer) || layerCount == 1;
|
|
||||||
useDirectCopy &= (pitchPerRow == bytesPerRow) || imageExtent.height == 1;
|
|
||||||
|
|
||||||
if (useDirectCopy) {
|
|
||||||
std::memcpy(dstData, srcData, bytesTotal);
|
|
||||||
} else {
|
|
||||||
for (uint32_t i = 0; i < layerCount; i++) {
|
|
||||||
for (uint32_t j = 0; j < imageExtent.height; j++) {
|
|
||||||
std::memcpy(dstData, srcData, bytesPerRow);
|
|
||||||
|
|
||||||
dstData += bytesPerRow;
|
|
||||||
srcData += pitchPerRow;
|
|
||||||
}
|
|
||||||
|
|
||||||
dstData += bytesPerLayer;
|
|
||||||
srcData += pitchPerLayer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
VkBufferImageCopy region;
|
VkBufferImageCopy region;
|
||||||
region.bufferOffset = slice.offset;
|
region.bufferOffset = slice.offset;
|
||||||
region.bufferRowLength = 0;
|
region.bufferRowLength = 0;
|
||||||
@ -485,6 +505,7 @@ namespace dxvk {
|
|||||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
region, slice);
|
region, slice);
|
||||||
|
|
||||||
|
// Transition image back into its optimal layout
|
||||||
m_barriers.accessImage(
|
m_barriers.accessImage(
|
||||||
image, subresourceRange,
|
image, subresourceRange,
|
||||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
|
@ -4,7 +4,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
const std::array<DxvkFormatInfo, 147> g_formatInfos = {{
|
const std::array<DxvkFormatInfo, 147> g_formatInfos = {{
|
||||||
// VK_FORMAT_UNDEFINED
|
// VK_FORMAT_UNDEFINED
|
||||||
{ 0, 0 },
|
{ },
|
||||||
|
|
||||||
// VK_FORMAT_R4G4_UNORM_PACK8
|
// VK_FORMAT_R4G4_UNORM_PACK8
|
||||||
{ 1, VK_IMAGE_ASPECT_COLOR_BIT },
|
{ 1, VK_IMAGE_ASPECT_COLOR_BIT },
|
||||||
@ -397,52 +397,84 @@ namespace dxvk {
|
|||||||
{ 0, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT },
|
{ 0, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT },
|
||||||
|
|
||||||
// VK_FORMAT_BC1_RGB_UNORM_BLOCK
|
// VK_FORMAT_BC1_RGB_UNORM_BLOCK
|
||||||
{ 0, VK_IMAGE_ASPECT_COLOR_BIT },
|
{ 8, VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
DxvkFormatFlag::BlockCompressed,
|
||||||
|
VkExtent3D { 4, 4, 1 } },
|
||||||
|
|
||||||
// VK_FORMAT_BC1_RGB_SRGB_BLOCK
|
// VK_FORMAT_BC1_RGB_SRGB_BLOCK
|
||||||
{ 0, VK_IMAGE_ASPECT_COLOR_BIT },
|
{ 8, VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
DxvkFormatFlag::BlockCompressed,
|
||||||
|
VkExtent3D { 4, 4, 1 } },
|
||||||
|
|
||||||
// VK_FORMAT_BC1_RGBA_UNORM_BLOCK
|
// VK_FORMAT_BC1_RGBA_UNORM_BLOCK
|
||||||
{ 0, VK_IMAGE_ASPECT_COLOR_BIT },
|
{ 8, VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
DxvkFormatFlag::BlockCompressed,
|
||||||
|
VkExtent3D { 4, 4, 1 } },
|
||||||
|
|
||||||
// VK_FORMAT_BC1_RGBA_SRGB_BLOCK
|
// VK_FORMAT_BC1_RGBA_SRGB_BLOCK
|
||||||
{ 0, VK_IMAGE_ASPECT_COLOR_BIT },
|
{ 8, VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
DxvkFormatFlag::BlockCompressed,
|
||||||
|
VkExtent3D { 4, 4, 1 } },
|
||||||
|
|
||||||
// VK_FORMAT_BC2_UNORM_BLOCK
|
// VK_FORMAT_BC2_UNORM_BLOCK
|
||||||
{ 0, VK_IMAGE_ASPECT_COLOR_BIT },
|
{ 16, VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
DxvkFormatFlag::BlockCompressed,
|
||||||
|
VkExtent3D { 4, 4, 1 } },
|
||||||
|
|
||||||
// VK_FORMAT_BC2_SRGB_BLOCK
|
// VK_FORMAT_BC2_SRGB_BLOCK
|
||||||
{ 0, VK_IMAGE_ASPECT_COLOR_BIT },
|
{ 16, VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
DxvkFormatFlag::BlockCompressed,
|
||||||
|
VkExtent3D { 4, 4, 1 } },
|
||||||
|
|
||||||
// VK_FORMAT_BC3_UNORM_BLOCK
|
// VK_FORMAT_BC3_UNORM_BLOCK
|
||||||
{ 0, VK_IMAGE_ASPECT_COLOR_BIT },
|
{ 16, VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
DxvkFormatFlag::BlockCompressed,
|
||||||
|
VkExtent3D { 4, 4, 1 } },
|
||||||
|
|
||||||
// VK_FORMAT_BC3_SRGB_BLOCK
|
// VK_FORMAT_BC3_SRGB_BLOCK
|
||||||
{ 0, VK_IMAGE_ASPECT_COLOR_BIT },
|
{ 16, VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
DxvkFormatFlag::BlockCompressed,
|
||||||
|
VkExtent3D { 4, 4, 1 } },
|
||||||
|
|
||||||
// VK_FORMAT_BC4_UNORM_BLOCK
|
// VK_FORMAT_BC4_UNORM_BLOCK
|
||||||
{ 0, VK_IMAGE_ASPECT_COLOR_BIT },
|
{ 8, VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
DxvkFormatFlag::BlockCompressed,
|
||||||
|
VkExtent3D { 4, 4, 1 } },
|
||||||
|
|
||||||
// VK_FORMAT_BC4_SNORM_BLOCK
|
// VK_FORMAT_BC4_SNORM_BLOCK
|
||||||
{ 0, VK_IMAGE_ASPECT_COLOR_BIT },
|
{ 8, VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
DxvkFormatFlag::BlockCompressed,
|
||||||
|
VkExtent3D { 4, 4, 1 } },
|
||||||
|
|
||||||
// VK_FORMAT_BC5_UNORM_BLOCK
|
// VK_FORMAT_BC5_UNORM_BLOCK
|
||||||
{ 0, VK_IMAGE_ASPECT_COLOR_BIT },
|
{ 16, VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
DxvkFormatFlag::BlockCompressed,
|
||||||
|
VkExtent3D { 4, 4, 1 } },
|
||||||
|
|
||||||
// VK_FORMAT_BC5_SNORM_BLOCK
|
// VK_FORMAT_BC5_SNORM_BLOCK
|
||||||
{ 0, VK_IMAGE_ASPECT_COLOR_BIT },
|
{ 16, VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
DxvkFormatFlag::BlockCompressed,
|
||||||
|
VkExtent3D { 4, 4, 1 } },
|
||||||
|
|
||||||
// VK_FORMAT_BC6H_UFLOAT_BLOCK
|
// VK_FORMAT_BC6H_UFLOAT_BLOCK
|
||||||
{ 0, VK_IMAGE_ASPECT_COLOR_BIT },
|
{ 16, VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
DxvkFormatFlag::BlockCompressed,
|
||||||
|
VkExtent3D { 4, 4, 1 } },
|
||||||
|
|
||||||
// VK_FORMAT_BC6H_SFLOAT_BLOCK
|
// VK_FORMAT_BC6H_SFLOAT_BLOCK
|
||||||
{ 0, VK_IMAGE_ASPECT_COLOR_BIT },
|
{ 16, VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
DxvkFormatFlag::BlockCompressed,
|
||||||
|
VkExtent3D { 4, 4, 1 } },
|
||||||
|
|
||||||
// VK_FORMAT_BC7_UNORM_BLOCK
|
// VK_FORMAT_BC7_UNORM_BLOCK
|
||||||
{ 0, VK_IMAGE_ASPECT_COLOR_BIT },
|
{ 16, VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
DxvkFormatFlag::BlockCompressed,
|
||||||
|
VkExtent3D { 4, 4, 1 } },
|
||||||
|
|
||||||
// VK_FORMAT_BC7_SRGB_BLOCK
|
// VK_FORMAT_BC7_SRGB_BLOCK
|
||||||
{ 0, VK_IMAGE_ASPECT_COLOR_BIT },
|
{ 16, VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
DxvkFormatFlag::BlockCompressed,
|
||||||
|
VkExtent3D { 4, 4, 1 } },
|
||||||
}};
|
}};
|
||||||
|
|
||||||
const DxvkFormatInfo* imageFormatInfo(VkFormat format) {
|
const DxvkFormatInfo* imageFormatInfo(VkFormat format) {
|
||||||
|
@ -4,6 +4,12 @@
|
|||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
|
enum class DxvkFormatFlag {
|
||||||
|
BlockCompressed,
|
||||||
|
};
|
||||||
|
|
||||||
|
using DxvkFormatFlags = Flags<DxvkFormatFlag>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Format info structure
|
* \brief Format info structure
|
||||||
*
|
*
|
||||||
@ -11,14 +17,23 @@ namespace dxvk {
|
|||||||
* about a Vulkan image format.
|
* about a Vulkan image format.
|
||||||
*/
|
*/
|
||||||
struct DxvkFormatInfo {
|
struct DxvkFormatInfo {
|
||||||
/// Size of an element in this format
|
/// Size of an element in this format. For compressed
|
||||||
VkDeviceSize elementSize;
|
/// formats, this is the size of a block, in bytes.
|
||||||
|
VkDeviceSize elementSize = 0;
|
||||||
|
|
||||||
/// Available image aspect flags
|
/// Available image aspect flags
|
||||||
VkImageAspectFlags aspectMask;
|
VkImageAspectFlags aspectMask = 0;
|
||||||
|
|
||||||
|
/// Some other format info flags
|
||||||
|
DxvkFormatFlags flags = 0;
|
||||||
|
|
||||||
|
/// Size, in pixels, of a compressed block. For
|
||||||
|
/// non-block formats, all these values are 1.
|
||||||
|
VkExtent3D blockSize = { 1, 1, 1 };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const DxvkFormatInfo* imageFormatInfo(VkFormat format);
|
const DxvkFormatInfo* imageFormatInfo(VkFormat format);
|
||||||
|
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user