#include #include "dxvk_format.h" #include "dxvk_util.h" namespace dxvk::util { VkPipelineStageFlags pipelineStages( VkShaderStageFlags shaderStages) { VkPipelineStageFlags result = 0; if (shaderStages & VK_SHADER_STAGE_COMPUTE_BIT) result |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; if (shaderStages & VK_SHADER_STAGE_VERTEX_BIT) result |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT; if (shaderStages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) result |= VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT; if (shaderStages & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) result |= VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT; if (shaderStages & VK_SHADER_STAGE_GEOMETRY_BIT) result |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT; if (shaderStages & VK_SHADER_STAGE_FRAGMENT_BIT) result |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; return result; } uint32_t computeMipLevelCount(VkExtent3D imageSize) { uint32_t maxDim = std::max(imageSize.width, imageSize.height); maxDim = std::max(imageSize.depth, maxDim); uint32_t mipCnt = 0; while (maxDim > 0) { mipCnt += 1; maxDim /= 2; } return mipCnt; } void packImageData( void* dstBytes, const void* srcBytes, VkExtent3D blockCount, VkDeviceSize blockSize, VkDeviceSize pitchPerRow, VkDeviceSize pitchPerLayer) { auto dstData = reinterpret_cast< char*>(dstBytes); auto srcData = reinterpret_cast(srcBytes); const VkDeviceSize bytesPerRow = blockCount.width * blockSize; const VkDeviceSize bytesPerLayer = blockCount.height * bytesPerRow; const VkDeviceSize bytesTotal = blockCount.depth * bytesPerLayer; const bool directCopy = ((bytesPerRow == pitchPerRow ) || (blockCount.height == 1)) && ((bytesPerLayer == pitchPerLayer) || (blockCount.depth == 1)); if (directCopy) { std::memcpy(dstData, srcData, bytesTotal); } else { for (uint32_t i = 0; i < blockCount.depth; i++) { for (uint32_t j = 0; j < blockCount.height; j++) { std::memcpy( dstData + j * bytesPerRow, srcData + j * pitchPerRow, bytesPerRow); } srcData += pitchPerLayer; dstData += bytesPerLayer; } } } void packImageData( void* dstBytes, const void* srcBytes, VkDeviceSize srcRowPitch, VkDeviceSize srcSlicePitch, VkDeviceSize dstRowPitchIn, VkDeviceSize dstSlicePitchIn, VkImageType imageType, VkExtent3D imageExtent, uint32_t imageLayers, const DxvkFormatInfo* formatInfo, VkImageAspectFlags aspectMask) { for (uint32_t i = 0; i < imageLayers; i++) { auto dstData = reinterpret_cast< char*>(dstBytes); auto srcData = reinterpret_cast(srcBytes); for (auto aspects = aspectMask; aspects; ) { auto aspect = vk::getNextAspect(aspects); auto extent = imageExtent; auto elementSize = formatInfo->elementSize; if (formatInfo->flags.test(DxvkFormatFlag::MultiPlane)) { auto plane = &formatInfo->planes[vk::getPlaneIndex(aspect)]; extent.width /= plane->blockSize.width; extent.height /= plane->blockSize.height; elementSize = plane->elementSize; } auto blockCount = computeBlockCount(extent, formatInfo->blockSize); VkDeviceSize bytesPerRow = blockCount.width * elementSize; VkDeviceSize bytesPerSlice = blockCount.height * bytesPerRow; VkDeviceSize bytesTotal = blockCount.depth * bytesPerSlice; VkDeviceSize dstRowPitch = dstRowPitchIn ? dstRowPitchIn : bytesPerRow; VkDeviceSize dstSlicePitch = dstSlicePitchIn ? dstSlicePitchIn : bytesPerSlice; const bool directCopy = ((bytesPerRow == srcRowPitch && bytesPerRow == dstRowPitch ) || (blockCount.height == 1)) && ((bytesPerSlice == srcSlicePitch && bytesPerSlice == dstSlicePitch) || (blockCount.depth == 1)); if (directCopy) { std::memcpy(dstData, srcData, bytesTotal); switch (imageType) { case VK_IMAGE_TYPE_1D: srcData += srcRowPitch; dstData += dstRowPitch; break; case VK_IMAGE_TYPE_2D: srcData += blockCount.height * srcRowPitch; dstData += blockCount.height * dstRowPitch; break; case VK_IMAGE_TYPE_3D: srcData += blockCount.depth * srcSlicePitch; dstData += blockCount.depth * dstSlicePitch; break; default: ; } } else { for (uint32_t i = 0; i < blockCount.depth; i++) { for (uint32_t j = 0; j < blockCount.height; j++) { std::memcpy( dstData + j * dstRowPitch, srcData + j * srcRowPitch, bytesPerRow); } switch (imageType) { case VK_IMAGE_TYPE_1D: srcData += srcRowPitch; dstData += dstRowPitch; break; case VK_IMAGE_TYPE_2D: srcData += blockCount.height * srcRowPitch; dstData += blockCount.height * dstRowPitch; break; case VK_IMAGE_TYPE_3D: srcData += srcSlicePitch; dstData += dstSlicePitch; break; default: ; } } } } } } VkDeviceSize computeImageDataSize(VkFormat format, VkExtent3D extent) { const DxvkFormatInfo* formatInfo = imageFormatInfo(format); VkDeviceSize size = 0; for (auto aspects = formatInfo->aspectMask; aspects; ) { auto aspect = vk::getNextAspect(aspects); auto elementSize = formatInfo->elementSize; auto planeExtent = extent; if (formatInfo->flags.test(DxvkFormatFlag::MultiPlane)) { auto plane = &formatInfo->planes[vk::getPlaneIndex(aspect)]; planeExtent.width /= plane->blockSize.width; planeExtent.height /= plane->blockSize.height; elementSize = plane->elementSize; } size += elementSize * flattenImageExtent(computeBlockCount(planeExtent, formatInfo->blockSize)); } return size; } static VkColorComponentFlags remapComponentFlag( VkColorComponentFlags mask, VkComponentSwizzle swizzle, VkColorComponentFlagBits identity) { VkColorComponentFlags bit; switch (swizzle) { case VK_COMPONENT_SWIZZLE_IDENTITY: bit = identity; break; case VK_COMPONENT_SWIZZLE_R: bit = VK_COLOR_COMPONENT_R_BIT; break; case VK_COMPONENT_SWIZZLE_G: bit = VK_COLOR_COMPONENT_G_BIT; break; case VK_COMPONENT_SWIZZLE_B: bit = VK_COLOR_COMPONENT_B_BIT; break; case VK_COMPONENT_SWIZZLE_A: bit = VK_COLOR_COMPONENT_A_BIT; break; default: bit = 0; /* SWIZZLE_ZERO, SWIZZLE_ONE */ } return (mask & bit) ? identity : 0; } VkColorComponentFlags remapComponentMask( VkColorComponentFlags mask, VkComponentMapping mapping) { VkColorComponentFlags result = 0; result |= remapComponentFlag(mask, mapping.r, VK_COLOR_COMPONENT_R_BIT); result |= remapComponentFlag(mask, mapping.g, VK_COLOR_COMPONENT_G_BIT); result |= remapComponentFlag(mask, mapping.b, VK_COLOR_COMPONENT_B_BIT); result |= remapComponentFlag(mask, mapping.a, VK_COLOR_COMPONENT_A_BIT); return result; } static VkComponentSwizzle findComponentSwizzle( VkComponentSwizzle swizzle, VkComponentSwizzle identity, VkComponentMapping mapping) { if (identity == VK_COMPONENT_SWIZZLE_IDENTITY) return VK_COMPONENT_SWIZZLE_IDENTITY; if (mapping.r == swizzle) return VK_COMPONENT_SWIZZLE_R; if (mapping.g == swizzle) return VK_COMPONENT_SWIZZLE_G; if (mapping.b == swizzle) return VK_COMPONENT_SWIZZLE_B; if (mapping.a == swizzle) return VK_COMPONENT_SWIZZLE_A; return VK_COMPONENT_SWIZZLE_ZERO; } VkComponentMapping invertComponentMapping(VkComponentMapping mapping) { VkComponentMapping result; result.r = findComponentSwizzle(VK_COMPONENT_SWIZZLE_R, mapping.r, mapping); result.g = findComponentSwizzle(VK_COMPONENT_SWIZZLE_G, mapping.g, mapping); result.b = findComponentSwizzle(VK_COMPONENT_SWIZZLE_B, mapping.b, mapping); result.a = findComponentSwizzle(VK_COMPONENT_SWIZZLE_A, mapping.a, mapping); return result; } static VkComponentMapping normalizeComponentMapping( VkComponentMapping mapping) { mapping.r = mapping.r == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_R : mapping.r; mapping.g = mapping.g == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_G : mapping.g; mapping.b = mapping.b == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_B : mapping.b; mapping.a = mapping.a == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_A : mapping.a; return mapping; } static VkComponentSwizzle resolveComponentSwizzle( VkComponentSwizzle swizzle, VkComponentMapping dstMapping, VkComponentMapping srcMapping) { VkComponentSwizzle dstSwizzle = VK_COMPONENT_SWIZZLE_IDENTITY; if (dstMapping.r == swizzle) dstSwizzle = VK_COMPONENT_SWIZZLE_R; if (dstMapping.g == swizzle) dstSwizzle = VK_COMPONENT_SWIZZLE_G; if (dstMapping.b == swizzle) dstSwizzle = VK_COMPONENT_SWIZZLE_B; if (dstMapping.a == swizzle) dstSwizzle = VK_COMPONENT_SWIZZLE_A; switch (dstSwizzle) { case VK_COMPONENT_SWIZZLE_R: return srcMapping.r; case VK_COMPONENT_SWIZZLE_G: return srcMapping.g; case VK_COMPONENT_SWIZZLE_B: return srcMapping.b; case VK_COMPONENT_SWIZZLE_A: return srcMapping.a; default: return VK_COMPONENT_SWIZZLE_IDENTITY; } } VkComponentMapping resolveSrcComponentMapping( VkComponentMapping dstMapping, VkComponentMapping srcMapping) { dstMapping = normalizeComponentMapping(dstMapping); VkComponentMapping result; result.r = resolveComponentSwizzle(VK_COMPONENT_SWIZZLE_R, dstMapping, srcMapping); result.g = resolveComponentSwizzle(VK_COMPONENT_SWIZZLE_G, dstMapping, srcMapping); result.b = resolveComponentSwizzle(VK_COMPONENT_SWIZZLE_B, dstMapping, srcMapping); result.a = resolveComponentSwizzle(VK_COMPONENT_SWIZZLE_A, dstMapping, srcMapping); return result; } bool isIdentityMapping( VkComponentMapping mapping) { return (mapping.r == VK_COMPONENT_SWIZZLE_R || mapping.r == VK_COMPONENT_SWIZZLE_IDENTITY) && (mapping.g == VK_COMPONENT_SWIZZLE_G || mapping.g == VK_COMPONENT_SWIZZLE_IDENTITY) && (mapping.b == VK_COMPONENT_SWIZZLE_B || mapping.b == VK_COMPONENT_SWIZZLE_IDENTITY) && (mapping.a == VK_COMPONENT_SWIZZLE_A || mapping.a == VK_COMPONENT_SWIZZLE_IDENTITY); } uint32_t getComponentIndex( VkComponentSwizzle component, uint32_t identity) { switch (component) { case VK_COMPONENT_SWIZZLE_R: return 0; case VK_COMPONENT_SWIZZLE_G: return 1; case VK_COMPONENT_SWIZZLE_B: return 2; case VK_COMPONENT_SWIZZLE_A: return 3; default: return identity; /* identity, zero, one */ } } VkClearColorValue swizzleClearColor( VkClearColorValue color, VkComponentMapping mapping) { VkClearColorValue result; auto swizzles = &mapping.r; for (uint32_t i = 0; i < 4; i++) { uint32_t index = getComponentIndex(swizzles[i], i); result.uint32[i] = color.uint32[index]; } return result; } bool isBlendConstantBlendFactor(VkBlendFactor factor) { return factor == VK_BLEND_FACTOR_CONSTANT_COLOR || factor == VK_BLEND_FACTOR_CONSTANT_ALPHA || factor == VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR || factor == VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA; } bool isDualSourceBlendFactor(VkBlendFactor factor) { return factor == VK_BLEND_FACTOR_SRC1_COLOR || factor == VK_BLEND_FACTOR_SRC1_ALPHA || factor == VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR || factor == VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA; } }