Vulkan: Create a util WritebackTexture function (unused atm)
This commit is contained in:
parent
09c29bbdc5
commit
4809f3eb51
|
@ -116,7 +116,9 @@ TextureCache::TextureCache(Memory* memory, RegisterFile* register_file,
|
||||||
trace_writer_(trace_writer),
|
trace_writer_(trace_writer),
|
||||||
device_(device),
|
device_(device),
|
||||||
staging_buffer_(device, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
staging_buffer_(device, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
||||||
kStagingBufferSize) {
|
kStagingBufferSize),
|
||||||
|
wb_staging_buffer_(device, VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||||
|
kStagingBufferSize) {
|
||||||
VkResult err = VK_SUCCESS;
|
VkResult err = VK_SUCCESS;
|
||||||
|
|
||||||
// Descriptor pool used for all of our cached descriptors.
|
// Descriptor pool used for all of our cached descriptors.
|
||||||
|
@ -127,6 +129,9 @@ TextureCache::TextureCache(Memory* memory, RegisterFile* register_file,
|
||||||
*device_, 32768,
|
*device_, 32768,
|
||||||
std::vector<VkDescriptorPoolSize>(pool_sizes, std::end(pool_sizes)));
|
std::vector<VkDescriptorPoolSize>(pool_sizes, std::end(pool_sizes)));
|
||||||
|
|
||||||
|
wb_command_pool_ = std::make_unique<ui::vulkan::CommandBufferPool>(
|
||||||
|
*device_, VK_QUEUE_FAMILY_IGNORED);
|
||||||
|
|
||||||
// Check some device limits
|
// Check some device limits
|
||||||
// On low sampler counts: Rarely would we experience over 16 unique samplers.
|
// On low sampler counts: Rarely would we experience over 16 unique samplers.
|
||||||
// This code could be refactored to scale up/down to the # of samplers.
|
// This code could be refactored to scale up/down to the # of samplers.
|
||||||
|
@ -169,6 +174,10 @@ TextureCache::TextureCache(Memory* memory, RegisterFile* register_file,
|
||||||
assert_always();
|
assert_always();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!wb_staging_buffer_.Initialize()) {
|
||||||
|
assert_always();
|
||||||
|
}
|
||||||
|
|
||||||
invalidated_textures_sets_[0].reserve(64);
|
invalidated_textures_sets_[0].reserve(64);
|
||||||
invalidated_textures_sets_[1].reserve(64);
|
invalidated_textures_sets_[1].reserve(64);
|
||||||
invalidated_textures_ = &invalidated_textures_sets_[0];
|
invalidated_textures_ = &invalidated_textures_sets_[0];
|
||||||
|
@ -424,21 +433,8 @@ TextureCache::Texture* TextureCache::Demand(const TextureInfo& texture_info,
|
||||||
trace_writer_->WriteMemoryRead(texture_info.guest_address,
|
trace_writer_->WriteMemoryRead(texture_info.guest_address,
|
||||||
texture_info.input_length);
|
texture_info.input_length);
|
||||||
|
|
||||||
if (!UploadTexture(command_buffer, completion_fence, texture, texture_info)) {
|
// Okay. Put a writewatch on it to tell us if it's been modified from the
|
||||||
FreeTexture(texture);
|
// guest.
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup a debug name for the texture.
|
|
||||||
device_->DbgSetObjectName(
|
|
||||||
reinterpret_cast<uint64_t>(texture->image),
|
|
||||||
VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
|
|
||||||
xe::format_string(
|
|
||||||
"0x%.8X - 0x%.8X", texture_info.guest_address,
|
|
||||||
texture_info.guest_address + texture_info.input_length));
|
|
||||||
|
|
||||||
// Okay. Now that the texture is uploaded from system memory, put a writewatch
|
|
||||||
// on it to tell us if it's been modified from the guest.
|
|
||||||
texture->access_watch_handle = memory_->AddPhysicalAccessWatch(
|
texture->access_watch_handle = memory_->AddPhysicalAccessWatch(
|
||||||
texture_info.guest_address, texture_info.input_length,
|
texture_info.guest_address, texture_info.input_length,
|
||||||
cpu::MMIOHandler::kWatchWrite,
|
cpu::MMIOHandler::kWatchWrite,
|
||||||
|
@ -457,6 +453,19 @@ TextureCache::Texture* TextureCache::Demand(const TextureInfo& texture_info,
|
||||||
},
|
},
|
||||||
this, texture);
|
this, texture);
|
||||||
|
|
||||||
|
if (!UploadTexture(command_buffer, completion_fence, texture, texture_info)) {
|
||||||
|
FreeTexture(texture);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup a debug name for the texture.
|
||||||
|
device_->DbgSetObjectName(
|
||||||
|
reinterpret_cast<uint64_t>(texture->image),
|
||||||
|
VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
|
||||||
|
xe::format_string(
|
||||||
|
"0x%.8X - 0x%.8X", texture_info.guest_address,
|
||||||
|
texture_info.guest_address + texture_info.input_length));
|
||||||
|
|
||||||
textures_[texture_hash] = texture;
|
textures_[texture_hash] = texture;
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
@ -1115,6 +1124,76 @@ bool TextureCache::ComputeTextureStorage(size_t* output_length,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextureCache::WritebackTexture(Texture* texture) {
|
||||||
|
VkResult status = VK_SUCCESS;
|
||||||
|
VkFence fence = wb_command_pool_->BeginBatch();
|
||||||
|
auto alloc = wb_staging_buffer_.Acquire(texture->memory_size, fence);
|
||||||
|
if (!alloc) {
|
||||||
|
wb_command_pool_->EndBatch();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto command_buffer = wb_command_pool_->AcquireEntry();
|
||||||
|
|
||||||
|
VkCommandBufferBeginInfo begin_info = {
|
||||||
|
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr,
|
||||||
|
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr,
|
||||||
|
};
|
||||||
|
vkBeginCommandBuffer(command_buffer, &begin_info);
|
||||||
|
|
||||||
|
// TODO: Transition the texture to a transfer source.
|
||||||
|
|
||||||
|
VkBufferImageCopy region = {
|
||||||
|
alloc->offset,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
{VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
|
||||||
|
{0, 0, 0},
|
||||||
|
{texture->texture_info.width + 1, texture->texture_info.height + 1, 1},
|
||||||
|
};
|
||||||
|
|
||||||
|
vkCmdCopyImageToBuffer(command_buffer, texture->image,
|
||||||
|
VK_IMAGE_LAYOUT_GENERAL,
|
||||||
|
wb_staging_buffer_.gpu_buffer(), 1, ®ion);
|
||||||
|
|
||||||
|
// TODO: Transition the texture back to a shader resource.
|
||||||
|
|
||||||
|
vkEndCommandBuffer(command_buffer);
|
||||||
|
|
||||||
|
// Submit the command buffer.
|
||||||
|
// Submit commands and wait.
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex>(device_->primary_queue_mutex());
|
||||||
|
VkSubmitInfo submit_info = {
|
||||||
|
VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
||||||
|
nullptr,
|
||||||
|
0,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
1,
|
||||||
|
&command_buffer,
|
||||||
|
0,
|
||||||
|
nullptr,
|
||||||
|
};
|
||||||
|
status = vkQueueSubmit(device_->primary_queue(), 1, &submit_info, fence);
|
||||||
|
CheckResult(status, "vkQueueSubmit");
|
||||||
|
|
||||||
|
if (status == VK_SUCCESS) {
|
||||||
|
status = vkQueueWaitIdle(device_->primary_queue());
|
||||||
|
CheckResult(status, "vkQueueWaitIdle");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wb_command_pool_->EndBatch();
|
||||||
|
|
||||||
|
auto dest = memory_->TranslatePhysical(texture->texture_info.guest_address);
|
||||||
|
if (status == VK_SUCCESS) {
|
||||||
|
std::memcpy(dest, alloc->host_ptr, texture->texture_info.input_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
wb_staging_buffer_.Scavenge();
|
||||||
|
}
|
||||||
|
|
||||||
bool TextureCache::UploadTexture(VkCommandBuffer command_buffer,
|
bool TextureCache::UploadTexture(VkCommandBuffer command_buffer,
|
||||||
VkFence completion_fence, Texture* dest,
|
VkFence completion_fence, Texture* dest,
|
||||||
const TextureInfo& src) {
|
const TextureInfo& src) {
|
||||||
|
|
|
@ -148,6 +148,10 @@ class TextureCache {
|
||||||
const TextureInfo& src);
|
const TextureInfo& src);
|
||||||
bool ComputeTextureStorage(size_t* output_length, const TextureInfo& src);
|
bool ComputeTextureStorage(size_t* output_length, const TextureInfo& src);
|
||||||
|
|
||||||
|
// Writes a texture back into guest memory. This call is (mostly) asynchronous
|
||||||
|
// but the texture must not be flagged for destruction.
|
||||||
|
void WritebackTexture(Texture* texture);
|
||||||
|
|
||||||
// Queues commands to upload a texture from system memory, applying any
|
// Queues commands to upload a texture from system memory, applying any
|
||||||
// conversions necessary. This may flush the command buffer to the GPU if we
|
// conversions necessary. This may flush the command buffer to the GPU if we
|
||||||
// run out of staging memory.
|
// run out of staging memory.
|
||||||
|
@ -175,11 +179,13 @@ class TextureCache {
|
||||||
ui::vulkan::VulkanDevice* device_ = nullptr;
|
ui::vulkan::VulkanDevice* device_ = nullptr;
|
||||||
VkQueue device_queue_ = nullptr;
|
VkQueue device_queue_ = nullptr;
|
||||||
|
|
||||||
|
std::unique_ptr<xe::ui::vulkan::CommandBufferPool> wb_command_pool_ = nullptr;
|
||||||
std::unique_ptr<xe::ui::vulkan::DescriptorPool> descriptor_pool_ = nullptr;
|
std::unique_ptr<xe::ui::vulkan::DescriptorPool> descriptor_pool_ = nullptr;
|
||||||
std::unordered_map<uint64_t, VkDescriptorSet> texture_bindings_;
|
std::unordered_map<uint64_t, VkDescriptorSet> texture_bindings_;
|
||||||
VkDescriptorSetLayout texture_descriptor_set_layout_ = nullptr;
|
VkDescriptorSetLayout texture_descriptor_set_layout_ = nullptr;
|
||||||
|
|
||||||
ui::vulkan::CircularBuffer staging_buffer_;
|
ui::vulkan::CircularBuffer staging_buffer_;
|
||||||
|
ui::vulkan::CircularBuffer wb_staging_buffer_;
|
||||||
std::unordered_map<uint64_t, Texture*> textures_;
|
std::unordered_map<uint64_t, Texture*> textures_;
|
||||||
std::unordered_map<uint64_t, Sampler*> samplers_;
|
std::unordered_map<uint64_t, Sampler*> samplers_;
|
||||||
std::list<Texture*> pending_delete_textures_;
|
std::list<Texture*> pending_delete_textures_;
|
||||||
|
|
Loading…
Reference in New Issue