new input system
This commit is contained in:
parent
b3db40ebec
commit
ac2eb7fb0a
31 changed files with 3292 additions and 781 deletions
|
|
@ -23,6 +23,8 @@ module;
|
|||
|
||||
export module Crafter.Graphics:ImageVulkan;
|
||||
import std;
|
||||
import Crafter.Asset;
|
||||
import :Decompress;
|
||||
import :VulkanBuffer;
|
||||
|
||||
export namespace Crafter {
|
||||
|
|
@ -35,6 +37,10 @@ export namespace Crafter {
|
|||
VkImage image;
|
||||
VkDeviceMemory imageMemory;
|
||||
VulkanBuffer<PixelType, true> buffer;
|
||||
// Lives until the compressed Update path's cmd buffer completes.
|
||||
// Same lifetime contract as Mesh::compressedStaging — caller must
|
||||
// not destroy / re-Update before the submit fence is signaled.
|
||||
VulkanBuffer<std::byte, true> compressedStaging;
|
||||
VkImageView imageView;
|
||||
VkDescriptorImageInfo descriptor;
|
||||
|
||||
|
|
@ -153,6 +159,114 @@ export namespace Crafter {
|
|||
}
|
||||
}
|
||||
|
||||
// GPU compressed-asset Update: stage compressed bytes, decompress
|
||||
// into `buffer` via VK_EXT_memory_decompression, then copy buffer→image
|
||||
// and transition to `layout`. Falls back to CPU decode + the existing
|
||||
// Update path when Device::memoryDecompressionSupported is false.
|
||||
// Caller is responsible for the dimensions matching: asset.sizeX/sizeY
|
||||
// must equal this->width/height (set by Create), and asset.pixelStride
|
||||
// must equal sizeof(PixelType).
|
||||
void Update(const CompressedTextureAsset& asset, VkCommandBuffer cmd, VkImageLayout layout) {
|
||||
if (asset.pixelStride != sizeof(PixelType)) {
|
||||
throw std::runtime_error("ImageVulkan::Update(compressed): pixel stride mismatch");
|
||||
}
|
||||
if (!Device::memoryDecompressionSupported) {
|
||||
std::span<PixelType> dst{ buffer.value, static_cast<std::size_t>(width) * height };
|
||||
std::array<std::span<std::byte>, 1> outputs = {
|
||||
std::as_writable_bytes(dst),
|
||||
};
|
||||
Compression::DecompressCPU(asset.blob, outputs);
|
||||
Update(cmd, layout);
|
||||
return;
|
||||
}
|
||||
|
||||
// Re-create the staging-into-image buffer with MEMORY_DECOMPRESSION
|
||||
// permission so the GPU codec can write into it. Keeps it
|
||||
// HOST_VISIBLE (matches the existing path) — on UMA / ReBAR that's
|
||||
// a fast path, on older systems the decompress writes traverse
|
||||
// PCIe but correctness is unchanged.
|
||||
buffer.Resize(
|
||||
VK_BUFFER_USAGE_TRANSFER_SRC_BIT
|
||||
| VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT
|
||||
| VK_BUFFER_USAGE_2_MEMORY_DECOMPRESSION_BIT_EXT,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
|
||||
static_cast<std::uint32_t>(width) * height);
|
||||
|
||||
compressedStaging.Resize(
|
||||
VK_BUFFER_USAGE_TRANSFER_SRC_BIT
|
||||
| VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT
|
||||
| VK_BUFFER_USAGE_2_MEMORY_DECOMPRESSION_BIT_EXT,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
|
||||
static_cast<std::uint32_t>(asset.blob.bytes.size()));
|
||||
std::memcpy(compressedStaging.value, asset.blob.bytes.data(), asset.blob.bytes.size());
|
||||
compressedStaging.FlushDevice();
|
||||
|
||||
std::vector<VkDecompressMemoryRegionEXT> regions;
|
||||
for (const Compression::RegionMeta& r : asset.blob.regions) {
|
||||
if (r.decompressedSize == 0) continue;
|
||||
std::span<const std::byte> streamBytes(
|
||||
asset.blob.bytes.data() + r.srcOffset,
|
||||
static_cast<std::size_t>(r.compressedSize));
|
||||
Decompress::ExpandStreamToTileRegions(
|
||||
streamBytes,
|
||||
compressedStaging.address + r.srcOffset,
|
||||
buffer.address,
|
||||
regions);
|
||||
}
|
||||
Decompress::DecompressOnGPU(
|
||||
cmd,
|
||||
regions,
|
||||
VK_PIPELINE_STAGE_2_COPY_BIT,
|
||||
VK_ACCESS_2_TRANSFER_READ_BIT);
|
||||
|
||||
// Continue with the existing buffer→image upload + layout transitions.
|
||||
// We've already inserted the decompress→transfer-read barrier,
|
||||
// so we skip the FlushDevice host-write barrier the regular Update
|
||||
// would emit (no host write happened).
|
||||
TransitionImageLayout(cmd, image, layout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, 0, mipLevels);
|
||||
|
||||
VkBufferImageCopy region{};
|
||||
region.bufferOffset = 0;
|
||||
region.bufferRowLength = 0;
|
||||
region.bufferImageHeight = 0;
|
||||
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
region.imageSubresource.mipLevel = 0;
|
||||
region.imageSubresource.baseArrayLayer = 0;
|
||||
region.imageSubresource.layerCount = 1;
|
||||
region.imageOffset = {0, 0, 0};
|
||||
region.imageExtent = { width, height, 1 };
|
||||
vkCmdCopyBufferToImage(cmd, buffer.buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
||||
|
||||
if (mipLevels > 1) {
|
||||
TransitionImageLayout(cmd, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, 0, 1);
|
||||
for (std::uint16_t i = 1; i < mipLevels; ++i) {
|
||||
std::uint16_t mipWidth = width >> i;
|
||||
std::uint16_t mipHeight = height >> i;
|
||||
std::uint16_t previousMipWidth = width >> (i - std::uint16_t(1));
|
||||
std::uint16_t previousMipHeight = height >> (i - std::uint16_t(1));
|
||||
|
||||
VkImageBlit blit = {};
|
||||
blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
blit.srcSubresource.mipLevel = i - 1;
|
||||
blit.srcSubresource.baseArrayLayer = 0;
|
||||
blit.srcSubresource.layerCount = 1;
|
||||
blit.srcOffsets[0] = { 0, 0, 0 };
|
||||
blit.srcOffsets[1] = { (int32_t)previousMipWidth, (int32_t)previousMipHeight, 1 };
|
||||
blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
blit.dstSubresource.mipLevel = i;
|
||||
blit.dstSubresource.baseArrayLayer = 0;
|
||||
blit.dstSubresource.layerCount = 1;
|
||||
blit.dstOffsets[0] = { 0, 0, 0 };
|
||||
blit.dstOffsets[1] = { (int32_t)mipWidth, (int32_t)mipHeight, 1 };
|
||||
vkCmdBlitImage(cmd, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, VK_FILTER_LINEAR);
|
||||
TransitionImageLayout(cmd, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, i, 1);
|
||||
}
|
||||
TransitionImageLayout(cmd, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, layout, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_SHADER_READ_BIT, 0, mipLevels);
|
||||
} else {
|
||||
TransitionImageLayout(cmd, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, layout, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, 0, mipLevels);
|
||||
}
|
||||
}
|
||||
|
||||
void Destroy() {
|
||||
vkDestroyImageView(Device::device, imageView, nullptr);
|
||||
vkDestroyImage(Device::device, image, nullptr);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue