core: Fix Vulkan dynamic texture threading (#4102)
This commit is contained in:
@@ -42,8 +42,7 @@ Texture2D::Texture2D(Context& context_)
|
||||
: context(context_) {}
|
||||
|
||||
Texture2D::~Texture2D() {
|
||||
destroyTexture();
|
||||
destroySampler();
|
||||
destroy(true);
|
||||
}
|
||||
|
||||
gfx::Texture2D& Texture2D::setSamplerConfiguration(const SamplerState& samplerState_) noexcept {
|
||||
@@ -132,6 +131,11 @@ void Texture2D::create() noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
void Texture2D::destroy(bool deferred) noexcept {
|
||||
destroyTexture(deferred);
|
||||
destroySampler(deferred);
|
||||
}
|
||||
|
||||
void Texture2D::upload() noexcept {
|
||||
if (!imageData) return;
|
||||
|
||||
@@ -151,7 +155,7 @@ void Texture2D::uploadSubRegion(const void* pixelData, const Size& size_, uint16
|
||||
const auto& encoder = context.createCommandEncoder();
|
||||
const auto& encoderImpl = static_cast<const CommandEncoder&>(*encoder);
|
||||
|
||||
uploadSubRegion(pixelData, size_, xOffset, yOffset, encoderImpl.getCommandBuffer());
|
||||
uploadSubRegion(pixelData, size_, xOffset, yOffset, encoderImpl.getCommandBuffer(), false);
|
||||
}
|
||||
|
||||
void Texture2D::uploadSubRegion(const void* pixelData,
|
||||
@@ -159,7 +163,7 @@ void Texture2D::uploadSubRegion(const void* pixelData,
|
||||
uint16_t xOffset,
|
||||
uint16_t yOffset,
|
||||
const vk::UniqueCommandBuffer& commandBuffer,
|
||||
DeletionQueue* deletionQueue) noexcept {
|
||||
bool submit) noexcept {
|
||||
if (!pixelData || size_.width == 0 || size_.height == 0) return;
|
||||
|
||||
create();
|
||||
@@ -189,39 +193,32 @@ void Texture2D::uploadSubRegion(const void* pixelData,
|
||||
vmaMapMemory(allocator, bufferAllocation->allocation, &bufferAllocation->mappedBuffer);
|
||||
memcpy(bufferAllocation->mappedBuffer, pixelData, bufferInfo.size);
|
||||
|
||||
const auto enqueueCommands = [&](const auto& buffer) {
|
||||
transitionToTransferWriteLayout(buffer);
|
||||
transitionToTransferWriteLayout(commandBuffer);
|
||||
|
||||
const auto region = vk::BufferImageCopy()
|
||||
.setBufferOffset(0)
|
||||
.setBufferRowLength(size_.width)
|
||||
.setImageSubresource(
|
||||
vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1))
|
||||
.setImageOffset(vk::Offset3D(xOffset, yOffset))
|
||||
.setImageExtent(vk::Extent3D(size_.width, size_.height, 1));
|
||||
const auto region = vk::BufferImageCopy()
|
||||
.setBufferOffset(0)
|
||||
.setBufferRowLength(size_.width)
|
||||
.setImageSubresource(vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1))
|
||||
.setImageOffset(vk::Offset3D(xOffset, yOffset))
|
||||
.setImageExtent(vk::Extent3D(size_.width, size_.height, 1));
|
||||
|
||||
buffer->copyBufferToImage(
|
||||
bufferAllocation->buffer, imageAllocation->image, imageLayout, region, backend.getDispatcher());
|
||||
commandBuffer->copyBufferToImage(
|
||||
bufferAllocation->buffer, imageAllocation->image, imageLayout, region, backend.getDispatcher());
|
||||
|
||||
if (samplerState.mipmapped && textureUsage == Texture2DUsage::ShaderInput) {
|
||||
generateMips(buffer);
|
||||
} else if (textureUsage == Texture2DUsage::Blit) {
|
||||
transitionToTransferReadLayout(buffer);
|
||||
} else {
|
||||
transitionToShaderReadLayout(buffer);
|
||||
}
|
||||
};
|
||||
|
||||
enqueueCommands(commandBuffer);
|
||||
|
||||
const auto function = [buffAlloc = std::move(bufferAllocation)](auto&) mutable {
|
||||
buffAlloc.reset();
|
||||
};
|
||||
|
||||
if (deletionQueue) {
|
||||
deletionQueue->push_back(std::move(function));
|
||||
if (samplerState.mipmapped && textureUsage == Texture2DUsage::ShaderInput) {
|
||||
generateMips(commandBuffer);
|
||||
} else if (textureUsage == Texture2DUsage::Blit) {
|
||||
transitionToTransferReadLayout(commandBuffer);
|
||||
} else {
|
||||
context.enqueueDeletion(std::move(function));
|
||||
transitionToShaderReadLayout(commandBuffer);
|
||||
}
|
||||
|
||||
if (submit) {
|
||||
commandBuffer->end(context.getBackend().getDispatcher());
|
||||
context.submitOneTimeCommand(commandBuffer);
|
||||
bufferAllocation.reset();
|
||||
} else {
|
||||
context.enqueueDeletion([buffAlloc = std::move(bufferAllocation)](auto&) mutable { buffAlloc.reset(); });
|
||||
}
|
||||
|
||||
context.threadSafeAccessRenderingStats([&](gfx::RenderingStats& stats) {
|
||||
@@ -429,9 +426,13 @@ void Texture2D::createSampler() {
|
||||
lastModified = util::MonotonicTimer::now();
|
||||
}
|
||||
|
||||
void Texture2D::destroyTexture() {
|
||||
void Texture2D::destroyTexture(bool deferred) {
|
||||
if (imageAllocation) {
|
||||
context.enqueueDeletion([allocation = std::move(imageAllocation)](auto&) mutable { allocation.reset(); });
|
||||
if (deferred) {
|
||||
context.enqueueDeletion([allocation = std::move(imageAllocation)](auto&) mutable { allocation.reset(); });
|
||||
} else {
|
||||
imageAllocation.reset();
|
||||
}
|
||||
|
||||
imageLayout = vk::ImageLayout::eUndefined;
|
||||
|
||||
@@ -442,11 +443,16 @@ void Texture2D::destroyTexture() {
|
||||
}
|
||||
}
|
||||
|
||||
void Texture2D::destroySampler() {
|
||||
void Texture2D::destroySampler(bool deferred) {
|
||||
if (sampler) {
|
||||
context.enqueueDeletion([sampler_ = std::move(sampler)](auto& context_) mutable {
|
||||
context_.getBackend().getDevice()->destroySampler(sampler_, nullptr, context_.getBackend().getDispatcher());
|
||||
});
|
||||
if (deferred) {
|
||||
context.enqueueDeletion([sampler_ = std::move(sampler)](auto& context_) mutable {
|
||||
context_.getBackend().getDevice()->destroySampler(
|
||||
sampler_, nullptr, context_.getBackend().getDispatcher());
|
||||
});
|
||||
} else {
|
||||
context.getBackend().getDevice()->destroySampler(sampler, nullptr, context.getBackend().getDispatcher());
|
||||
}
|
||||
|
||||
sampler = nullptr;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user