mirror of
https://git.suyu.dev/suyu/suyu.git
synced 2024-12-27 10:50:57 +01:00
Merge pull request #4364 from lioncash/desig5
vulkan: Make use of designated initializers where applicable
This commit is contained in:
commit
821d295f24
19 changed files with 758 additions and 659 deletions
|
@ -39,16 +39,17 @@ std::unique_ptr<VKStreamBuffer> CreateStreamBuffer(const VKDevice& device, VKSch
|
|||
|
||||
Buffer::Buffer(const VKDevice& device, VKMemoryManager& memory_manager, VKScheduler& scheduler_,
|
||||
VKStagingBufferPool& staging_pool_, VAddr cpu_addr, std::size_t size)
|
||||
: VideoCommon::BufferBlock{cpu_addr, size}, scheduler{scheduler_}, staging_pool{staging_pool_} {
|
||||
VkBufferCreateInfo ci;
|
||||
ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
ci.pNext = nullptr;
|
||||
ci.flags = 0;
|
||||
ci.size = static_cast<VkDeviceSize>(size);
|
||||
ci.usage = BUFFER_USAGE | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
||||
ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
ci.queueFamilyIndexCount = 0;
|
||||
ci.pQueueFamilyIndices = nullptr;
|
||||
: BufferBlock{cpu_addr, size}, scheduler{scheduler_}, staging_pool{staging_pool_} {
|
||||
const VkBufferCreateInfo ci{
|
||||
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.size = static_cast<VkDeviceSize>(size),
|
||||
.usage = BUFFER_USAGE | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
||||
.queueFamilyIndexCount = 0,
|
||||
.pQueueFamilyIndices = nullptr,
|
||||
};
|
||||
|
||||
buffer.handle = device.GetLogical().CreateBuffer(ci);
|
||||
buffer.commit = memory_manager.Commit(buffer.handle, false);
|
||||
|
@ -66,16 +67,17 @@ void Buffer::Upload(std::size_t offset, std::size_t size, const u8* data) {
|
|||
scheduler.Record([staging = *staging.handle, handle, offset, size](vk::CommandBuffer cmdbuf) {
|
||||
cmdbuf.CopyBuffer(staging, handle, VkBufferCopy{0, offset, size});
|
||||
|
||||
VkBufferMemoryBarrier barrier;
|
||||
barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
|
||||
barrier.pNext = nullptr;
|
||||
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
barrier.dstAccessMask = UPLOAD_ACCESS_BARRIERS;
|
||||
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barrier.buffer = handle;
|
||||
barrier.offset = offset;
|
||||
barrier.size = size;
|
||||
const VkBufferMemoryBarrier barrier{
|
||||
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
|
||||
.pNext = nullptr,
|
||||
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
.dstAccessMask = UPLOAD_ACCESS_BARRIERS,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.buffer = handle,
|
||||
.offset = offset,
|
||||
.size = size,
|
||||
};
|
||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, UPLOAD_PIPELINE_STAGE, 0, {},
|
||||
barrier, {});
|
||||
});
|
||||
|
@ -87,16 +89,17 @@ void Buffer::Download(std::size_t offset, std::size_t size, u8* data) {
|
|||
|
||||
const VkBuffer handle = Handle();
|
||||
scheduler.Record([staging = *staging.handle, handle, offset, size](vk::CommandBuffer cmdbuf) {
|
||||
VkBufferMemoryBarrier barrier;
|
||||
barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
|
||||
barrier.pNext = nullptr;
|
||||
barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
|
||||
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
||||
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barrier.buffer = handle;
|
||||
barrier.offset = offset;
|
||||
barrier.size = size;
|
||||
const VkBufferMemoryBarrier barrier{
|
||||
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
|
||||
.pNext = nullptr,
|
||||
.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT,
|
||||
.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.buffer = handle,
|
||||
.offset = offset,
|
||||
.size = size,
|
||||
};
|
||||
|
||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||
|
|
|
@ -115,32 +115,32 @@ constexpr u8 quad_array[] = {
|
|||
0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00};
|
||||
|
||||
VkDescriptorSetLayoutBinding BuildQuadArrayPassDescriptorSetLayoutBinding() {
|
||||
VkDescriptorSetLayoutBinding binding;
|
||||
binding.binding = 0;
|
||||
binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||
binding.descriptorCount = 1;
|
||||
binding.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
|
||||
binding.pImmutableSamplers = nullptr;
|
||||
return binding;
|
||||
return {
|
||||
.binding = 0,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
|
||||
.pImmutableSamplers = nullptr,
|
||||
};
|
||||
}
|
||||
|
||||
VkDescriptorUpdateTemplateEntryKHR BuildQuadArrayPassDescriptorUpdateTemplateEntry() {
|
||||
VkDescriptorUpdateTemplateEntryKHR entry;
|
||||
entry.dstBinding = 0;
|
||||
entry.dstArrayElement = 0;
|
||||
entry.descriptorCount = 1;
|
||||
entry.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||
entry.offset = 0;
|
||||
entry.stride = sizeof(DescriptorUpdateEntry);
|
||||
return entry;
|
||||
return {
|
||||
.dstBinding = 0,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
.offset = 0,
|
||||
.stride = sizeof(DescriptorUpdateEntry),
|
||||
};
|
||||
}
|
||||
|
||||
VkPushConstantRange BuildComputePushConstantRange(std::size_t size) {
|
||||
VkPushConstantRange range;
|
||||
range.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
|
||||
range.offset = 0;
|
||||
range.size = static_cast<u32>(size);
|
||||
return range;
|
||||
return {
|
||||
.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
|
||||
.offset = 0,
|
||||
.size = static_cast<u32>(size),
|
||||
};
|
||||
}
|
||||
|
||||
// Uint8 SPIR-V module. Generated from the "shaders/" directory.
|
||||
|
@ -344,29 +344,33 @@ constexpr u8 QUAD_INDEXED_SPV[] = {
|
|||
0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00};
|
||||
|
||||
std::array<VkDescriptorSetLayoutBinding, 2> BuildInputOutputDescriptorSetBindings() {
|
||||
std::array<VkDescriptorSetLayoutBinding, 2> bindings;
|
||||
bindings[0].binding = 0;
|
||||
bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||
bindings[0].descriptorCount = 1;
|
||||
bindings[0].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
|
||||
bindings[0].pImmutableSamplers = nullptr;
|
||||
bindings[1].binding = 1;
|
||||
bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||
bindings[1].descriptorCount = 1;
|
||||
bindings[1].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
|
||||
bindings[1].pImmutableSamplers = nullptr;
|
||||
return bindings;
|
||||
return {{
|
||||
{
|
||||
.binding = 0,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
|
||||
.pImmutableSamplers = nullptr,
|
||||
},
|
||||
{
|
||||
.binding = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
|
||||
.pImmutableSamplers = nullptr,
|
||||
},
|
||||
}};
|
||||
}
|
||||
|
||||
VkDescriptorUpdateTemplateEntryKHR BuildInputOutputDescriptorUpdateTemplate() {
|
||||
VkDescriptorUpdateTemplateEntryKHR entry;
|
||||
entry.dstBinding = 0;
|
||||
entry.dstArrayElement = 0;
|
||||
entry.descriptorCount = 2;
|
||||
entry.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||
entry.offset = 0;
|
||||
entry.stride = sizeof(DescriptorUpdateEntry);
|
||||
return entry;
|
||||
return {
|
||||
.dstBinding = 0,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 2,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
.offset = 0,
|
||||
.stride = sizeof(DescriptorUpdateEntry),
|
||||
};
|
||||
}
|
||||
|
||||
} // Anonymous namespace
|
||||
|
@ -376,37 +380,37 @@ VKComputePass::VKComputePass(const VKDevice& device, VKDescriptorPool& descripto
|
|||
vk::Span<VkDescriptorUpdateTemplateEntryKHR> templates,
|
||||
vk::Span<VkPushConstantRange> push_constants, std::size_t code_size,
|
||||
const u8* code) {
|
||||
VkDescriptorSetLayoutCreateInfo descriptor_layout_ci;
|
||||
descriptor_layout_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
||||
descriptor_layout_ci.pNext = nullptr;
|
||||
descriptor_layout_ci.flags = 0;
|
||||
descriptor_layout_ci.bindingCount = bindings.size();
|
||||
descriptor_layout_ci.pBindings = bindings.data();
|
||||
descriptor_set_layout = device.GetLogical().CreateDescriptorSetLayout(descriptor_layout_ci);
|
||||
descriptor_set_layout = device.GetLogical().CreateDescriptorSetLayout({
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.bindingCount = bindings.size(),
|
||||
.pBindings = bindings.data(),
|
||||
});
|
||||
|
||||
VkPipelineLayoutCreateInfo pipeline_layout_ci;
|
||||
pipeline_layout_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||
pipeline_layout_ci.pNext = nullptr;
|
||||
pipeline_layout_ci.flags = 0;
|
||||
pipeline_layout_ci.setLayoutCount = 1;
|
||||
pipeline_layout_ci.pSetLayouts = descriptor_set_layout.address();
|
||||
pipeline_layout_ci.pushConstantRangeCount = push_constants.size();
|
||||
pipeline_layout_ci.pPushConstantRanges = push_constants.data();
|
||||
layout = device.GetLogical().CreatePipelineLayout(pipeline_layout_ci);
|
||||
layout = device.GetLogical().CreatePipelineLayout({
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.setLayoutCount = 1,
|
||||
.pSetLayouts = descriptor_set_layout.address(),
|
||||
.pushConstantRangeCount = push_constants.size(),
|
||||
.pPushConstantRanges = push_constants.data(),
|
||||
});
|
||||
|
||||
if (!templates.empty()) {
|
||||
VkDescriptorUpdateTemplateCreateInfoKHR template_ci;
|
||||
template_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR;
|
||||
template_ci.pNext = nullptr;
|
||||
template_ci.flags = 0;
|
||||
template_ci.descriptorUpdateEntryCount = templates.size();
|
||||
template_ci.pDescriptorUpdateEntries = templates.data();
|
||||
template_ci.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR;
|
||||
template_ci.descriptorSetLayout = *descriptor_set_layout;
|
||||
template_ci.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||
template_ci.pipelineLayout = *layout;
|
||||
template_ci.set = 0;
|
||||
descriptor_template = device.GetLogical().CreateDescriptorUpdateTemplateKHR(template_ci);
|
||||
descriptor_template = device.GetLogical().CreateDescriptorUpdateTemplateKHR({
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.descriptorUpdateEntryCount = templates.size(),
|
||||
.pDescriptorUpdateEntries = templates.data(),
|
||||
.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR,
|
||||
.descriptorSetLayout = *descriptor_set_layout,
|
||||
.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
.pipelineLayout = *layout,
|
||||
.set = 0,
|
||||
});
|
||||
|
||||
descriptor_allocator.emplace(descriptor_pool, *descriptor_set_layout);
|
||||
}
|
||||
|
@ -414,32 +418,32 @@ VKComputePass::VKComputePass(const VKDevice& device, VKDescriptorPool& descripto
|
|||
auto code_copy = std::make_unique<u32[]>(code_size / sizeof(u32) + 1);
|
||||
std::memcpy(code_copy.get(), code, code_size);
|
||||
|
||||
VkShaderModuleCreateInfo module_ci;
|
||||
module_ci.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||
module_ci.pNext = nullptr;
|
||||
module_ci.flags = 0;
|
||||
module_ci.codeSize = code_size;
|
||||
module_ci.pCode = code_copy.get();
|
||||
module = device.GetLogical().CreateShaderModule(module_ci);
|
||||
module = device.GetLogical().CreateShaderModule({
|
||||
.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.codeSize = code_size,
|
||||
.pCode = code_copy.get(),
|
||||
});
|
||||
|
||||
VkComputePipelineCreateInfo pipeline_ci;
|
||||
pipeline_ci.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
|
||||
pipeline_ci.pNext = nullptr;
|
||||
pipeline_ci.flags = 0;
|
||||
pipeline_ci.layout = *layout;
|
||||
pipeline_ci.basePipelineHandle = nullptr;
|
||||
pipeline_ci.basePipelineIndex = 0;
|
||||
|
||||
VkPipelineShaderStageCreateInfo& stage_ci = pipeline_ci.stage;
|
||||
stage_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||
stage_ci.pNext = nullptr;
|
||||
stage_ci.flags = 0;
|
||||
stage_ci.stage = VK_SHADER_STAGE_COMPUTE_BIT;
|
||||
stage_ci.module = *module;
|
||||
stage_ci.pName = "main";
|
||||
stage_ci.pSpecializationInfo = nullptr;
|
||||
|
||||
pipeline = device.GetLogical().CreateComputePipeline(pipeline_ci);
|
||||
pipeline = device.GetLogical().CreateComputePipeline({
|
||||
.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.stage =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.stage = VK_SHADER_STAGE_COMPUTE_BIT,
|
||||
.module = *module,
|
||||
.pName = "main",
|
||||
.pSpecializationInfo = nullptr,
|
||||
},
|
||||
.layout = *layout,
|
||||
.basePipelineHandle = nullptr,
|
||||
.basePipelineIndex = 0,
|
||||
});
|
||||
}
|
||||
|
||||
VKComputePass::~VKComputePass() = default;
|
||||
|
|
|
@ -43,12 +43,13 @@ vk::DescriptorSetLayout VKComputePipeline::CreateDescriptorSetLayout() const {
|
|||
const auto add_bindings = [&](VkDescriptorType descriptor_type, std::size_t num_entries) {
|
||||
// TODO(Rodrigo): Maybe make individual bindings here?
|
||||
for (u32 bindpoint = 0; bindpoint < static_cast<u32>(num_entries); ++bindpoint) {
|
||||
VkDescriptorSetLayoutBinding& entry = bindings.emplace_back();
|
||||
entry.binding = binding++;
|
||||
entry.descriptorType = descriptor_type;
|
||||
entry.descriptorCount = 1;
|
||||
entry.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
|
||||
entry.pImmutableSamplers = nullptr;
|
||||
bindings.push_back({
|
||||
.binding = binding++,
|
||||
.descriptorType = descriptor_type,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
|
||||
.pImmutableSamplers = nullptr,
|
||||
});
|
||||
}
|
||||
};
|
||||
add_bindings(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, entries.const_buffers.size());
|
||||
|
@ -58,25 +59,25 @@ vk::DescriptorSetLayout VKComputePipeline::CreateDescriptorSetLayout() const {
|
|||
add_bindings(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, entries.storage_texels.size());
|
||||
add_bindings(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, entries.images.size());
|
||||
|
||||
VkDescriptorSetLayoutCreateInfo ci;
|
||||
ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
||||
ci.pNext = nullptr;
|
||||
ci.flags = 0;
|
||||
ci.bindingCount = static_cast<u32>(bindings.size());
|
||||
ci.pBindings = bindings.data();
|
||||
return device.GetLogical().CreateDescriptorSetLayout(ci);
|
||||
return device.GetLogical().CreateDescriptorSetLayout({
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.bindingCount = static_cast<u32>(bindings.size()),
|
||||
.pBindings = bindings.data(),
|
||||
});
|
||||
}
|
||||
|
||||
vk::PipelineLayout VKComputePipeline::CreatePipelineLayout() const {
|
||||
VkPipelineLayoutCreateInfo ci;
|
||||
ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||
ci.pNext = nullptr;
|
||||
ci.flags = 0;
|
||||
ci.setLayoutCount = 1;
|
||||
ci.pSetLayouts = descriptor_set_layout.address();
|
||||
ci.pushConstantRangeCount = 0;
|
||||
ci.pPushConstantRanges = nullptr;
|
||||
return device.GetLogical().CreatePipelineLayout(ci);
|
||||
return device.GetLogical().CreatePipelineLayout({
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.setLayoutCount = 1,
|
||||
.pSetLayouts = descriptor_set_layout.address(),
|
||||
.pushConstantRangeCount = 0,
|
||||
.pPushConstantRanges = nullptr,
|
||||
});
|
||||
}
|
||||
|
||||
vk::DescriptorUpdateTemplateKHR VKComputePipeline::CreateDescriptorUpdateTemplate() const {
|
||||
|
@ -89,59 +90,63 @@ vk::DescriptorUpdateTemplateKHR VKComputePipeline::CreateDescriptorUpdateTemplat
|
|||
return {};
|
||||
}
|
||||
|
||||
VkDescriptorUpdateTemplateCreateInfoKHR ci;
|
||||
ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR;
|
||||
ci.pNext = nullptr;
|
||||
ci.flags = 0;
|
||||
ci.descriptorUpdateEntryCount = static_cast<u32>(template_entries.size());
|
||||
ci.pDescriptorUpdateEntries = template_entries.data();
|
||||
ci.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR;
|
||||
ci.descriptorSetLayout = *descriptor_set_layout;
|
||||
ci.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||
ci.pipelineLayout = *layout;
|
||||
ci.set = DESCRIPTOR_SET;
|
||||
return device.GetLogical().CreateDescriptorUpdateTemplateKHR(ci);
|
||||
return device.GetLogical().CreateDescriptorUpdateTemplateKHR({
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.descriptorUpdateEntryCount = static_cast<u32>(template_entries.size()),
|
||||
.pDescriptorUpdateEntries = template_entries.data(),
|
||||
.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR,
|
||||
.descriptorSetLayout = *descriptor_set_layout,
|
||||
.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
.pipelineLayout = *layout,
|
||||
.set = DESCRIPTOR_SET,
|
||||
});
|
||||
}
|
||||
|
||||
vk::ShaderModule VKComputePipeline::CreateShaderModule(const std::vector<u32>& code) const {
|
||||
device.SaveShader(code);
|
||||
|
||||
VkShaderModuleCreateInfo ci;
|
||||
ci.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||
ci.pNext = nullptr;
|
||||
ci.flags = 0;
|
||||
ci.codeSize = code.size() * sizeof(u32);
|
||||
ci.pCode = code.data();
|
||||
return device.GetLogical().CreateShaderModule(ci);
|
||||
return device.GetLogical().CreateShaderModule({
|
||||
.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.codeSize = code.size() * sizeof(u32),
|
||||
.pCode = code.data(),
|
||||
});
|
||||
}
|
||||
|
||||
vk::Pipeline VKComputePipeline::CreatePipeline() const {
|
||||
VkComputePipelineCreateInfo ci;
|
||||
VkPipelineShaderStageCreateInfo& stage_ci = ci.stage;
|
||||
stage_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||
stage_ci.pNext = nullptr;
|
||||
stage_ci.flags = 0;
|
||||
stage_ci.stage = VK_SHADER_STAGE_COMPUTE_BIT;
|
||||
stage_ci.module = *shader_module;
|
||||
stage_ci.pName = "main";
|
||||
stage_ci.pSpecializationInfo = nullptr;
|
||||
|
||||
VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT subgroup_size_ci;
|
||||
subgroup_size_ci.sType =
|
||||
VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT;
|
||||
subgroup_size_ci.pNext = nullptr;
|
||||
subgroup_size_ci.requiredSubgroupSize = GuestWarpSize;
|
||||
VkComputePipelineCreateInfo ci{
|
||||
.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.stage =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.stage = VK_SHADER_STAGE_COMPUTE_BIT,
|
||||
.module = *shader_module,
|
||||
.pName = "main",
|
||||
.pSpecializationInfo = nullptr,
|
||||
},
|
||||
.layout = *layout,
|
||||
.basePipelineHandle = nullptr,
|
||||
.basePipelineIndex = 0,
|
||||
};
|
||||
|
||||
const VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT subgroup_size_ci{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT,
|
||||
.pNext = nullptr,
|
||||
.requiredSubgroupSize = GuestWarpSize,
|
||||
};
|
||||
|
||||
if (entries.uses_warps && device.IsGuestWarpSizeSupported(VK_SHADER_STAGE_COMPUTE_BIT)) {
|
||||
stage_ci.pNext = &subgroup_size_ci;
|
||||
ci.stage.pNext = &subgroup_size_ci;
|
||||
}
|
||||
|
||||
ci.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
|
||||
ci.pNext = nullptr;
|
||||
ci.flags = 0;
|
||||
ci.layout = *layout;
|
||||
ci.basePipelineHandle = nullptr;
|
||||
ci.basePipelineIndex = 0;
|
||||
return device.GetLogical().CreateComputePipeline(ci);
|
||||
}
|
||||
|
||||
|
|
|
@ -43,27 +43,30 @@ vk::DescriptorPool* VKDescriptorPool::AllocateNewPool() {
|
|||
{VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, num_sets * 64},
|
||||
{VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, num_sets * 64},
|
||||
{VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, num_sets * 64},
|
||||
{VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, num_sets * 40}};
|
||||
{VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, num_sets * 40},
|
||||
};
|
||||
|
||||
VkDescriptorPoolCreateInfo ci;
|
||||
ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
||||
ci.pNext = nullptr;
|
||||
ci.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
|
||||
ci.maxSets = num_sets;
|
||||
ci.poolSizeCount = static_cast<u32>(std::size(pool_sizes));
|
||||
ci.pPoolSizes = std::data(pool_sizes);
|
||||
const VkDescriptorPoolCreateInfo ci{
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
|
||||
.maxSets = num_sets,
|
||||
.poolSizeCount = static_cast<u32>(std::size(pool_sizes)),
|
||||
.pPoolSizes = std::data(pool_sizes),
|
||||
};
|
||||
return &pools.emplace_back(device.GetLogical().CreateDescriptorPool(ci));
|
||||
}
|
||||
|
||||
vk::DescriptorSets VKDescriptorPool::AllocateDescriptors(VkDescriptorSetLayout layout,
|
||||
std::size_t count) {
|
||||
const std::vector layout_copies(count, layout);
|
||||
VkDescriptorSetAllocateInfo ai;
|
||||
ai.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
||||
ai.pNext = nullptr;
|
||||
ai.descriptorPool = **active_pool;
|
||||
ai.descriptorSetCount = static_cast<u32>(count);
|
||||
ai.pSetLayouts = layout_copies.data();
|
||||
VkDescriptorSetAllocateInfo ai{
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.descriptorPool = **active_pool,
|
||||
.descriptorSetCount = static_cast<u32>(count),
|
||||
.pSetLayouts = layout_copies.data(),
|
||||
};
|
||||
|
||||
vk::DescriptorSets sets = active_pool->Allocate(ai);
|
||||
if (!sets.IsOutOfPoolMemory()) {
|
||||
|
|
|
@ -102,21 +102,29 @@ bool VKImage::HasChanged(u32 base_layer, u32 num_layers, u32 base_level, u32 num
|
|||
|
||||
void VKImage::CreatePresentView() {
|
||||
// Image type has to be 2D to be presented.
|
||||
VkImageViewCreateInfo image_view_ci;
|
||||
image_view_ci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
image_view_ci.pNext = nullptr;
|
||||
image_view_ci.flags = 0;
|
||||
image_view_ci.image = *image;
|
||||
image_view_ci.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
image_view_ci.format = format;
|
||||
image_view_ci.components = {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY};
|
||||
image_view_ci.subresourceRange.aspectMask = aspect_mask;
|
||||
image_view_ci.subresourceRange.baseMipLevel = 0;
|
||||
image_view_ci.subresourceRange.levelCount = 1;
|
||||
image_view_ci.subresourceRange.baseArrayLayer = 0;
|
||||
image_view_ci.subresourceRange.layerCount = 1;
|
||||
present_view = device.GetLogical().CreateImageView(image_view_ci);
|
||||
present_view = device.GetLogical().CreateImageView({
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.image = *image,
|
||||
.viewType = VK_IMAGE_VIEW_TYPE_2D,
|
||||
.format = format,
|
||||
.components =
|
||||
{
|
||||
.r = VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
.g = VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
.b = VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
.a = VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
},
|
||||
.subresourceRange =
|
||||
{
|
||||
.aspectMask = aspect_mask,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = 1,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
VKImage::SubrangeState& VKImage::GetSubrangeState(u32 layer, u32 level) noexcept {
|
||||
|
|
|
@ -178,13 +178,12 @@ bool VKMemoryManager::AllocMemory(VkMemoryPropertyFlags wanted_properties, u32 t
|
|||
}();
|
||||
|
||||
// Try to allocate found type.
|
||||
VkMemoryAllocateInfo memory_ai;
|
||||
memory_ai.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
memory_ai.pNext = nullptr;
|
||||
memory_ai.allocationSize = size;
|
||||
memory_ai.memoryTypeIndex = type;
|
||||
|
||||
vk::DeviceMemory memory = device.GetLogical().TryAllocateMemory(memory_ai);
|
||||
vk::DeviceMemory memory = device.GetLogical().TryAllocateMemory({
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.allocationSize = size,
|
||||
.memoryTypeIndex = type,
|
||||
});
|
||||
if (!memory) {
|
||||
LOG_CRITICAL(Render_Vulkan, "Device allocation failed!");
|
||||
return false;
|
||||
|
|
|
@ -88,12 +88,13 @@ void AddBindings(std::vector<VkDescriptorSetLayoutBinding>& bindings, u32& bindi
|
|||
// Combined image samplers can be arrayed.
|
||||
count = container[i].size;
|
||||
}
|
||||
VkDescriptorSetLayoutBinding& entry = bindings.emplace_back();
|
||||
entry.binding = binding++;
|
||||
entry.descriptorType = descriptor_type;
|
||||
entry.descriptorCount = count;
|
||||
entry.stageFlags = stage_flags;
|
||||
entry.pImmutableSamplers = nullptr;
|
||||
bindings.push_back({
|
||||
.binding = binding++,
|
||||
.descriptorType = descriptor_type,
|
||||
.descriptorCount = count,
|
||||
.stageFlags = stage_flags,
|
||||
.pImmutableSamplers = nullptr,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -259,10 +260,10 @@ VKComputePipeline& VKPipelineCache::GetComputePipeline(const ComputePipelineCach
|
|||
}
|
||||
}
|
||||
|
||||
Specialization specialization;
|
||||
specialization.workgroup_size = key.workgroup_size;
|
||||
specialization.shared_memory_size = key.shared_memory_size;
|
||||
|
||||
const Specialization specialization{
|
||||
.workgroup_size = key.workgroup_size,
|
||||
.shared_memory_size = key.shared_memory_size,
|
||||
};
|
||||
const SPIRVShader spirv_shader{Decompile(device, shader->GetIR(), ShaderType::Compute,
|
||||
shader->GetRegistry(), specialization),
|
||||
shader->GetEntries()};
|
||||
|
@ -370,13 +371,14 @@ void AddEntry(std::vector<VkDescriptorUpdateTemplateEntry>& template_entries, u3
|
|||
if constexpr (descriptor_type == COMBINED_IMAGE_SAMPLER) {
|
||||
for (u32 i = 0; i < count; ++i) {
|
||||
const u32 num_samplers = container[i].size;
|
||||
VkDescriptorUpdateTemplateEntry& entry = template_entries.emplace_back();
|
||||
entry.dstBinding = binding;
|
||||
entry.dstArrayElement = 0;
|
||||
entry.descriptorCount = num_samplers;
|
||||
entry.descriptorType = descriptor_type;
|
||||
entry.offset = offset;
|
||||
entry.stride = entry_size;
|
||||
template_entries.push_back({
|
||||
.dstBinding = binding,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = num_samplers,
|
||||
.descriptorType = descriptor_type,
|
||||
.offset = offset,
|
||||
.stride = entry_size,
|
||||
});
|
||||
|
||||
++binding;
|
||||
offset += num_samplers * entry_size;
|
||||
|
@ -389,22 +391,24 @@ void AddEntry(std::vector<VkDescriptorUpdateTemplateEntry>& template_entries, u3
|
|||
// Nvidia has a bug where updating multiple texels at once causes the driver to crash.
|
||||
// Note: Fixed in driver Windows 443.24, Linux 440.66.15
|
||||
for (u32 i = 0; i < count; ++i) {
|
||||
VkDescriptorUpdateTemplateEntry& entry = template_entries.emplace_back();
|
||||
entry.dstBinding = binding + i;
|
||||
entry.dstArrayElement = 0;
|
||||
entry.descriptorCount = 1;
|
||||
entry.descriptorType = descriptor_type;
|
||||
entry.offset = static_cast<std::size_t>(offset + i * entry_size);
|
||||
entry.stride = entry_size;
|
||||
template_entries.push_back({
|
||||
.dstBinding = binding + i,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = descriptor_type,
|
||||
.offset = static_cast<std::size_t>(offset + i * entry_size),
|
||||
.stride = entry_size,
|
||||
});
|
||||
}
|
||||
} else if (count > 0) {
|
||||
VkDescriptorUpdateTemplateEntry& entry = template_entries.emplace_back();
|
||||
entry.dstBinding = binding;
|
||||
entry.dstArrayElement = 0;
|
||||
entry.descriptorCount = count;
|
||||
entry.descriptorType = descriptor_type;
|
||||
entry.offset = offset;
|
||||
entry.stride = entry_size;
|
||||
template_entries.push_back({
|
||||
.dstBinding = binding,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = count,
|
||||
.descriptorType = descriptor_type,
|
||||
.offset = offset,
|
||||
.stride = entry_size,
|
||||
});
|
||||
}
|
||||
offset += count * entry_size;
|
||||
binding += count;
|
||||
|
|
|
@ -47,14 +47,14 @@ std::pair<VkQueryPool, u32> QueryPool::Commit(VKFence& fence) {
|
|||
void QueryPool::Allocate(std::size_t begin, std::size_t end) {
|
||||
usage.resize(end);
|
||||
|
||||
VkQueryPoolCreateInfo query_pool_ci;
|
||||
query_pool_ci.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;
|
||||
query_pool_ci.pNext = nullptr;
|
||||
query_pool_ci.flags = 0;
|
||||
query_pool_ci.queryType = GetTarget(type);
|
||||
query_pool_ci.queryCount = static_cast<u32>(end - begin);
|
||||
query_pool_ci.pipelineStatistics = 0;
|
||||
pools.push_back(device->GetLogical().CreateQueryPool(query_pool_ci));
|
||||
pools.push_back(device->GetLogical().CreateQueryPool({
|
||||
.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.queryType = GetTarget(type),
|
||||
.queryCount = static_cast<u32>(end - begin),
|
||||
.pipelineStatistics = 0,
|
||||
}));
|
||||
}
|
||||
|
||||
void QueryPool::Reserve(std::pair<VkQueryPool, u32> query) {
|
||||
|
|
|
@ -64,20 +64,22 @@ VkViewport GetViewportState(const VKDevice& device, const Maxwell& regs, std::si
|
|||
const auto& src = regs.viewport_transform[index];
|
||||
const float width = src.scale_x * 2.0f;
|
||||
const float height = src.scale_y * 2.0f;
|
||||
|
||||
VkViewport viewport;
|
||||
viewport.x = src.translate_x - src.scale_x;
|
||||
viewport.y = src.translate_y - src.scale_y;
|
||||
viewport.width = width != 0.0f ? width : 1.0f;
|
||||
viewport.height = height != 0.0f ? height : 1.0f;
|
||||
|
||||
const float reduce_z = regs.depth_mode == Maxwell::DepthMode::MinusOneToOne ? 1.0f : 0.0f;
|
||||
viewport.minDepth = src.translate_z - src.scale_z * reduce_z;
|
||||
viewport.maxDepth = src.translate_z + src.scale_z;
|
||||
|
||||
VkViewport viewport{
|
||||
.x = src.translate_x - src.scale_x,
|
||||
.y = src.translate_y - src.scale_y,
|
||||
.width = width != 0.0f ? width : 1.0f,
|
||||
.height = height != 0.0f ? height : 1.0f,
|
||||
.minDepth = src.translate_z - src.scale_z * reduce_z,
|
||||
.maxDepth = src.translate_z + src.scale_z,
|
||||
};
|
||||
|
||||
if (!device.IsExtDepthRangeUnrestrictedSupported()) {
|
||||
viewport.minDepth = std::clamp(viewport.minDepth, 0.0f, 1.0f);
|
||||
viewport.maxDepth = std::clamp(viewport.maxDepth, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
return viewport;
|
||||
}
|
||||
|
||||
|
@ -508,10 +510,11 @@ void RasterizerVulkan::Clear() {
|
|||
|
||||
const u32 color_attachment = regs.clear_buffers.RT;
|
||||
scheduler.Record([color_attachment, clear_value, clear_rect](vk::CommandBuffer cmdbuf) {
|
||||
VkClearAttachment attachment;
|
||||
attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
attachment.colorAttachment = color_attachment;
|
||||
attachment.clearValue = clear_value;
|
||||
const VkClearAttachment attachment{
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.colorAttachment = color_attachment,
|
||||
.clearValue = clear_value,
|
||||
};
|
||||
cmdbuf.ClearAttachments(attachment, clear_rect);
|
||||
});
|
||||
}
|
||||
|
@ -551,13 +554,16 @@ void RasterizerVulkan::DispatchCompute(GPUVAddr code_addr) {
|
|||
query_cache.UpdateCounters();
|
||||
|
||||
const auto& launch_desc = system.GPU().KeplerCompute().launch_description;
|
||||
ComputePipelineCacheKey key;
|
||||
key.shader = code_addr;
|
||||
key.shared_memory_size = launch_desc.shared_alloc;
|
||||
key.workgroup_size = {launch_desc.block_dim_x, launch_desc.block_dim_y,
|
||||
launch_desc.block_dim_z};
|
||||
|
||||
auto& pipeline = pipeline_cache.GetComputePipeline(key);
|
||||
auto& pipeline = pipeline_cache.GetComputePipeline({
|
||||
.shader = code_addr,
|
||||
.shared_memory_size = launch_desc.shared_alloc,
|
||||
.workgroup_size =
|
||||
{
|
||||
launch_desc.block_dim_x,
|
||||
launch_desc.block_dim_y,
|
||||
launch_desc.block_dim_z,
|
||||
},
|
||||
});
|
||||
|
||||
// Compute dispatches can't be executed inside a renderpass
|
||||
scheduler.RequestOutsideRenderPassOperationContext();
|
||||
|
@ -841,17 +847,17 @@ std::tuple<VkFramebuffer, VkExtent2D> RasterizerVulkan::ConfigureFramebuffers(
|
|||
const auto [fbentry, is_cache_miss] = framebuffer_cache.try_emplace(key);
|
||||
auto& framebuffer = fbentry->second;
|
||||
if (is_cache_miss) {
|
||||
VkFramebufferCreateInfo framebuffer_ci;
|
||||
framebuffer_ci.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
||||
framebuffer_ci.pNext = nullptr;
|
||||
framebuffer_ci.flags = 0;
|
||||
framebuffer_ci.renderPass = key.renderpass;
|
||||
framebuffer_ci.attachmentCount = static_cast<u32>(key.views.size());
|
||||
framebuffer_ci.pAttachments = key.views.data();
|
||||
framebuffer_ci.width = key.width;
|
||||
framebuffer_ci.height = key.height;
|
||||
framebuffer_ci.layers = key.layers;
|
||||
framebuffer = device.GetLogical().CreateFramebuffer(framebuffer_ci);
|
||||
framebuffer = device.GetLogical().CreateFramebuffer({
|
||||
.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.renderPass = key.renderpass,
|
||||
.attachmentCount = static_cast<u32>(key.views.size()),
|
||||
.pAttachments = key.views.data(),
|
||||
.width = key.width,
|
||||
.height = key.height,
|
||||
.layers = key.layers,
|
||||
});
|
||||
}
|
||||
|
||||
return {*framebuffer, VkExtent2D{key.width, key.height}};
|
||||
|
@ -1553,17 +1559,17 @@ VkBuffer RasterizerVulkan::DefaultBuffer() {
|
|||
return *default_buffer;
|
||||
}
|
||||
|
||||
VkBufferCreateInfo ci;
|
||||
ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
ci.pNext = nullptr;
|
||||
ci.flags = 0;
|
||||
ci.size = DEFAULT_BUFFER_SIZE;
|
||||
ci.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
|
||||
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
|
||||
ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
ci.queueFamilyIndexCount = 0;
|
||||
ci.pQueueFamilyIndices = nullptr;
|
||||
default_buffer = device.GetLogical().CreateBuffer(ci);
|
||||
default_buffer = device.GetLogical().CreateBuffer({
|
||||
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.size = DEFAULT_BUFFER_SIZE,
|
||||
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
|
||||
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
|
||||
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
||||
.queueFamilyIndexCount = 0,
|
||||
.pQueueFamilyIndices = nullptr,
|
||||
});
|
||||
default_buffer_commit = memory_manager.Commit(default_buffer, false);
|
||||
|
||||
scheduler.RequestOutsideRenderPassOperationContext();
|
||||
|
|
|
@ -39,10 +39,14 @@ VkRenderPass VKRenderPassCache::GetRenderPass(const RenderPassParams& params) {
|
|||
|
||||
vk::RenderPass VKRenderPassCache::CreateRenderPass(const RenderPassParams& params) const {
|
||||
using namespace VideoCore::Surface;
|
||||
std::vector<VkAttachmentDescription> descriptors;
|
||||
std::vector<VkAttachmentReference> color_references;
|
||||
|
||||
const std::size_t num_attachments = static_cast<std::size_t>(params.num_color_attachments);
|
||||
|
||||
std::vector<VkAttachmentDescription> descriptors;
|
||||
descriptors.reserve(num_attachments);
|
||||
|
||||
std::vector<VkAttachmentReference> color_references;
|
||||
color_references.reserve(num_attachments);
|
||||
|
||||
for (std::size_t rt = 0; rt < num_attachments; ++rt) {
|
||||
const auto guest_format = static_cast<Tegra::RenderTargetFormat>(params.color_formats[rt]);
|
||||
const PixelFormat pixel_format = PixelFormatFromRenderTargetFormat(guest_format);
|
||||
|
@ -54,20 +58,22 @@ vk::RenderPass VKRenderPassCache::CreateRenderPass(const RenderPassParams& param
|
|||
const VkImageLayout color_layout = ((params.texceptions >> rt) & 1) != 0
|
||||
? VK_IMAGE_LAYOUT_GENERAL
|
||||
: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
VkAttachmentDescription& descriptor = descriptors.emplace_back();
|
||||
descriptor.flags = VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT;
|
||||
descriptor.format = format.format;
|
||||
descriptor.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
descriptor.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
descriptor.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
descriptor.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
descriptor.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
descriptor.initialLayout = color_layout;
|
||||
descriptor.finalLayout = color_layout;
|
||||
descriptors.push_back({
|
||||
.flags = VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT,
|
||||
.format = format.format,
|
||||
.samples = VK_SAMPLE_COUNT_1_BIT,
|
||||
.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
|
||||
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
|
||||
.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
||||
.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
|
||||
.initialLayout = color_layout,
|
||||
.finalLayout = color_layout,
|
||||
});
|
||||
|
||||
VkAttachmentReference& reference = color_references.emplace_back();
|
||||
reference.attachment = static_cast<u32>(rt);
|
||||
reference.layout = color_layout;
|
||||
color_references.push_back({
|
||||
.attachment = static_cast<u32>(rt),
|
||||
.layout = color_layout,
|
||||
});
|
||||
}
|
||||
|
||||
VkAttachmentReference zeta_attachment_ref;
|
||||
|
@ -82,32 +88,36 @@ vk::RenderPass VKRenderPassCache::CreateRenderPass(const RenderPassParams& param
|
|||
const VkImageLayout zeta_layout = params.zeta_texception != 0
|
||||
? VK_IMAGE_LAYOUT_GENERAL
|
||||
: VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
VkAttachmentDescription& descriptor = descriptors.emplace_back();
|
||||
descriptor.flags = 0;
|
||||
descriptor.format = format.format;
|
||||
descriptor.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
descriptor.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
descriptor.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
descriptor.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
descriptor.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
descriptor.initialLayout = zeta_layout;
|
||||
descriptor.finalLayout = zeta_layout;
|
||||
descriptors.push_back({
|
||||
.flags = 0,
|
||||
.format = format.format,
|
||||
.samples = VK_SAMPLE_COUNT_1_BIT,
|
||||
.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
|
||||
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
|
||||
.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
|
||||
.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE,
|
||||
.initialLayout = zeta_layout,
|
||||
.finalLayout = zeta_layout,
|
||||
});
|
||||
|
||||
zeta_attachment_ref.attachment = static_cast<u32>(num_attachments);
|
||||
zeta_attachment_ref.layout = zeta_layout;
|
||||
zeta_attachment_ref = {
|
||||
.attachment = static_cast<u32>(num_attachments),
|
||||
.layout = zeta_layout,
|
||||
};
|
||||
}
|
||||
|
||||
VkSubpassDescription subpass_description;
|
||||
subpass_description.flags = 0;
|
||||
subpass_description.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||
subpass_description.inputAttachmentCount = 0;
|
||||
subpass_description.pInputAttachments = nullptr;
|
||||
subpass_description.colorAttachmentCount = static_cast<u32>(color_references.size());
|
||||
subpass_description.pColorAttachments = color_references.data();
|
||||
subpass_description.pResolveAttachments = nullptr;
|
||||
subpass_description.pDepthStencilAttachment = has_zeta ? &zeta_attachment_ref : nullptr;
|
||||
subpass_description.preserveAttachmentCount = 0;
|
||||
subpass_description.pPreserveAttachments = nullptr;
|
||||
const VkSubpassDescription subpass_description{
|
||||
.flags = 0,
|
||||
.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
.inputAttachmentCount = 0,
|
||||
.pInputAttachments = nullptr,
|
||||
.colorAttachmentCount = static_cast<u32>(color_references.size()),
|
||||
.pColorAttachments = color_references.data(),
|
||||
.pResolveAttachments = nullptr,
|
||||
.pDepthStencilAttachment = has_zeta ? &zeta_attachment_ref : nullptr,
|
||||
.preserveAttachmentCount = 0,
|
||||
.pPreserveAttachments = nullptr,
|
||||
};
|
||||
|
||||
VkAccessFlags access = 0;
|
||||
VkPipelineStageFlags stage = 0;
|
||||
|
@ -122,26 +132,27 @@ vk::RenderPass VKRenderPassCache::CreateRenderPass(const RenderPassParams& param
|
|||
stage |= VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
||||
}
|
||||
|
||||
VkSubpassDependency subpass_dependency;
|
||||
subpass_dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
|
||||
subpass_dependency.dstSubpass = 0;
|
||||
subpass_dependency.srcStageMask = stage;
|
||||
subpass_dependency.dstStageMask = stage;
|
||||
subpass_dependency.srcAccessMask = 0;
|
||||
subpass_dependency.dstAccessMask = access;
|
||||
subpass_dependency.dependencyFlags = 0;
|
||||
const VkSubpassDependency subpass_dependency{
|
||||
.srcSubpass = VK_SUBPASS_EXTERNAL,
|
||||
.dstSubpass = 0,
|
||||
.srcStageMask = stage,
|
||||
.dstStageMask = stage,
|
||||
.srcAccessMask = 0,
|
||||
.dstAccessMask = access,
|
||||
.dependencyFlags = 0,
|
||||
};
|
||||
|
||||
VkRenderPassCreateInfo ci;
|
||||
ci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
||||
ci.pNext = nullptr;
|
||||
ci.flags = 0;
|
||||
ci.attachmentCount = static_cast<u32>(descriptors.size());
|
||||
ci.pAttachments = descriptors.data();
|
||||
ci.subpassCount = 1;
|
||||
ci.pSubpasses = &subpass_description;
|
||||
ci.dependencyCount = 1;
|
||||
ci.pDependencies = &subpass_dependency;
|
||||
return device.GetLogical().CreateRenderPass(ci);
|
||||
return device.GetLogical().CreateRenderPass({
|
||||
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.attachmentCount = static_cast<u32>(descriptors.size()),
|
||||
.pAttachments = descriptors.data(),
|
||||
.subpassCount = 1,
|
||||
.pSubpasses = &subpass_description,
|
||||
.dependencyCount = 1,
|
||||
.pDependencies = &subpass_dependency,
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace Vulkan
|
||||
|
|
|
@ -18,33 +18,32 @@ namespace {
|
|||
constexpr std::size_t COMMAND_BUFFER_POOL_SIZE = 0x1000;
|
||||
constexpr std::size_t FENCES_GROW_STEP = 0x40;
|
||||
|
||||
VkFenceCreateInfo BuildFenceCreateInfo() {
|
||||
VkFenceCreateInfo fence_ci;
|
||||
fence_ci.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
|
||||
fence_ci.pNext = nullptr;
|
||||
fence_ci.flags = 0;
|
||||
return fence_ci;
|
||||
constexpr VkFenceCreateInfo BuildFenceCreateInfo() {
|
||||
return {
|
||||
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
};
|
||||
}
|
||||
|
||||
} // Anonymous namespace
|
||||
|
||||
class CommandBufferPool final : public VKFencedPool {
|
||||
public:
|
||||
CommandBufferPool(const VKDevice& device)
|
||||
explicit CommandBufferPool(const VKDevice& device)
|
||||
: VKFencedPool(COMMAND_BUFFER_POOL_SIZE), device{device} {}
|
||||
|
||||
void Allocate(std::size_t begin, std::size_t end) override {
|
||||
// Command buffers are going to be commited, recorded, executed every single usage cycle.
|
||||
// They are also going to be reseted when commited.
|
||||
VkCommandPoolCreateInfo command_pool_ci;
|
||||
command_pool_ci.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
||||
command_pool_ci.pNext = nullptr;
|
||||
command_pool_ci.flags =
|
||||
VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
||||
command_pool_ci.queueFamilyIndex = device.GetGraphicsFamily();
|
||||
|
||||
Pool& pool = pools.emplace_back();
|
||||
pool.handle = device.GetLogical().CreateCommandPool(command_pool_ci);
|
||||
pool.handle = device.GetLogical().CreateCommandPool({
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT |
|
||||
VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
|
||||
.queueFamilyIndex = device.GetGraphicsFamily(),
|
||||
});
|
||||
pool.cmdbufs = pool.handle.Allocate(COMMAND_BUFFER_POOL_SIZE);
|
||||
}
|
||||
|
||||
|
|
|
@ -44,32 +44,35 @@ vk::Sampler VKSamplerCache::CreateSampler(const Tegra::Texture::TSCEntry& tsc) c
|
|||
const bool arbitrary_borders = device.IsExtCustomBorderColorSupported();
|
||||
const std::array color = tsc.GetBorderColor();
|
||||
|
||||
VkSamplerCustomBorderColorCreateInfoEXT border;
|
||||
border.sType = VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT;
|
||||
border.pNext = nullptr;
|
||||
border.format = VK_FORMAT_UNDEFINED;
|
||||
VkSamplerCustomBorderColorCreateInfoEXT border{
|
||||
.sType = VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT,
|
||||
.pNext = nullptr,
|
||||
.format = VK_FORMAT_UNDEFINED,
|
||||
};
|
||||
std::memcpy(&border.customBorderColor, color.data(), sizeof(color));
|
||||
|
||||
VkSamplerCreateInfo ci;
|
||||
ci.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
|
||||
ci.pNext = arbitrary_borders ? &border : nullptr;
|
||||
ci.flags = 0;
|
||||
ci.magFilter = MaxwellToVK::Sampler::Filter(tsc.mag_filter);
|
||||
ci.minFilter = MaxwellToVK::Sampler::Filter(tsc.min_filter);
|
||||
ci.mipmapMode = MaxwellToVK::Sampler::MipmapMode(tsc.mipmap_filter);
|
||||
ci.addressModeU = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_u, tsc.mag_filter);
|
||||
ci.addressModeV = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_v, tsc.mag_filter);
|
||||
ci.addressModeW = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_p, tsc.mag_filter);
|
||||
ci.mipLodBias = tsc.GetLodBias();
|
||||
ci.anisotropyEnable = tsc.GetMaxAnisotropy() > 1.0f ? VK_TRUE : VK_FALSE;
|
||||
ci.maxAnisotropy = tsc.GetMaxAnisotropy();
|
||||
ci.compareEnable = tsc.depth_compare_enabled;
|
||||
ci.compareOp = MaxwellToVK::Sampler::DepthCompareFunction(tsc.depth_compare_func);
|
||||
ci.minLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.0f : tsc.GetMinLod();
|
||||
ci.maxLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.25f : tsc.GetMaxLod();
|
||||
ci.borderColor = arbitrary_borders ? VK_BORDER_COLOR_INT_CUSTOM_EXT : ConvertBorderColor(color);
|
||||
ci.unnormalizedCoordinates = VK_FALSE;
|
||||
return device.GetLogical().CreateSampler(ci);
|
||||
return device.GetLogical().CreateSampler({
|
||||
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
|
||||
.pNext = arbitrary_borders ? &border : nullptr,
|
||||
.flags = 0,
|
||||
.magFilter = MaxwellToVK::Sampler::Filter(tsc.mag_filter),
|
||||
.minFilter = MaxwellToVK::Sampler::Filter(tsc.min_filter),
|
||||
.mipmapMode = MaxwellToVK::Sampler::MipmapMode(tsc.mipmap_filter),
|
||||
.addressModeU = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_u, tsc.mag_filter),
|
||||
.addressModeV = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_v, tsc.mag_filter),
|
||||
.addressModeW = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_p, tsc.mag_filter),
|
||||
.mipLodBias = tsc.GetLodBias(),
|
||||
.anisotropyEnable =
|
||||
static_cast<VkBool32>(tsc.GetMaxAnisotropy() > 1.0f ? VK_TRUE : VK_FALSE),
|
||||
.maxAnisotropy = tsc.GetMaxAnisotropy(),
|
||||
.compareEnable = tsc.depth_compare_enabled,
|
||||
.compareOp = MaxwellToVK::Sampler::DepthCompareFunction(tsc.depth_compare_func),
|
||||
.minLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.0f : tsc.GetMinLod(),
|
||||
.maxLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.25f : tsc.GetMaxLod(),
|
||||
.borderColor =
|
||||
arbitrary_borders ? VK_BORDER_COLOR_INT_CUSTOM_EXT : ConvertBorderColor(color),
|
||||
.unnormalizedCoordinates = VK_FALSE,
|
||||
});
|
||||
}
|
||||
|
||||
VkSampler VKSamplerCache::ToSamplerType(const vk::Sampler& sampler) const {
|
||||
|
|
|
@ -100,16 +100,19 @@ void VKScheduler::RequestRenderpass(VkRenderPass renderpass, VkFramebuffer frame
|
|||
state.framebuffer = framebuffer;
|
||||
state.render_area = render_area;
|
||||
|
||||
VkRenderPassBeginInfo renderpass_bi;
|
||||
renderpass_bi.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||
renderpass_bi.pNext = nullptr;
|
||||
renderpass_bi.renderPass = renderpass;
|
||||
renderpass_bi.framebuffer = framebuffer;
|
||||
renderpass_bi.renderArea.offset.x = 0;
|
||||
renderpass_bi.renderArea.offset.y = 0;
|
||||
renderpass_bi.renderArea.extent = render_area;
|
||||
renderpass_bi.clearValueCount = 0;
|
||||
renderpass_bi.pClearValues = nullptr;
|
||||
const VkRenderPassBeginInfo renderpass_bi{
|
||||
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
||||
.pNext = nullptr,
|
||||
.renderPass = renderpass,
|
||||
.framebuffer = framebuffer,
|
||||
.renderArea =
|
||||
{
|
||||
.offset = {.x = 0, .y = 0},
|
||||
.extent = render_area,
|
||||
},
|
||||
.clearValueCount = 0,
|
||||
.pClearValues = nullptr,
|
||||
};
|
||||
|
||||
Record([renderpass_bi, end_renderpass](vk::CommandBuffer cmdbuf) {
|
||||
if (end_renderpass) {
|
||||
|
@ -157,16 +160,17 @@ void VKScheduler::SubmitExecution(VkSemaphore semaphore) {
|
|||
|
||||
current_cmdbuf.End();
|
||||
|
||||
VkSubmitInfo submit_info;
|
||||
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||
submit_info.pNext = nullptr;
|
||||
submit_info.waitSemaphoreCount = 0;
|
||||
submit_info.pWaitSemaphores = nullptr;
|
||||
submit_info.pWaitDstStageMask = nullptr;
|
||||
submit_info.commandBufferCount = 1;
|
||||
submit_info.pCommandBuffers = current_cmdbuf.address();
|
||||
submit_info.signalSemaphoreCount = semaphore ? 1 : 0;
|
||||
submit_info.pSignalSemaphores = &semaphore;
|
||||
const VkSubmitInfo submit_info{
|
||||
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
||||
.pNext = nullptr,
|
||||
.waitSemaphoreCount = 0,
|
||||
.pWaitSemaphores = nullptr,
|
||||
.pWaitDstStageMask = nullptr,
|
||||
.commandBufferCount = 1,
|
||||
.pCommandBuffers = current_cmdbuf.address(),
|
||||
.signalSemaphoreCount = semaphore ? 1U : 0U,
|
||||
.pSignalSemaphores = &semaphore,
|
||||
};
|
||||
switch (const VkResult result = device.GetGraphicsQueue().Submit(submit_info, *current_fence)) {
|
||||
case VK_SUCCESS:
|
||||
break;
|
||||
|
@ -181,19 +185,18 @@ void VKScheduler::SubmitExecution(VkSemaphore semaphore) {
|
|||
void VKScheduler::AllocateNewContext() {
|
||||
++ticks;
|
||||
|
||||
VkCommandBufferBeginInfo cmdbuf_bi;
|
||||
cmdbuf_bi.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||
cmdbuf_bi.pNext = nullptr;
|
||||
cmdbuf_bi.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||
cmdbuf_bi.pInheritanceInfo = nullptr;
|
||||
|
||||
std::unique_lock lock{mutex};
|
||||
current_fence = next_fence;
|
||||
next_fence = &resource_manager.CommitFence();
|
||||
|
||||
current_cmdbuf = vk::CommandBuffer(resource_manager.CommitCommandBuffer(*current_fence),
|
||||
device.GetDispatchLoader());
|
||||
current_cmdbuf.Begin(cmdbuf_bi);
|
||||
current_cmdbuf.Begin({
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
|
||||
.pInheritanceInfo = nullptr,
|
||||
});
|
||||
|
||||
// Enable counters once again. These are disabled when a command buffer is finished.
|
||||
if (query_cache) {
|
||||
|
|
|
@ -19,13 +19,13 @@ vk::ShaderModule BuildShader(const VKDevice& device, std::size_t code_size, cons
|
|||
const auto data = std::make_unique<u32[]>(code_size / sizeof(u32));
|
||||
std::memcpy(data.get(), code_data, code_size);
|
||||
|
||||
VkShaderModuleCreateInfo ci;
|
||||
ci.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||
ci.pNext = nullptr;
|
||||
ci.flags = 0;
|
||||
ci.codeSize = code_size;
|
||||
ci.pCode = data.get();
|
||||
return device.GetLogical().CreateShaderModule(ci);
|
||||
return device.GetLogical().CreateShaderModule({
|
||||
.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.codeSize = code_size,
|
||||
.pCode = data.get(),
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace Vulkan
|
||||
|
|
|
@ -71,20 +71,19 @@ VKBuffer* VKStagingBufferPool::TryGetReservedBuffer(std::size_t size, bool host_
|
|||
VKBuffer& VKStagingBufferPool::CreateStagingBuffer(std::size_t size, bool host_visible) {
|
||||
const u32 log2 = Common::Log2Ceil64(size);
|
||||
|
||||
VkBufferCreateInfo ci;
|
||||
ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
ci.pNext = nullptr;
|
||||
ci.flags = 0;
|
||||
ci.size = 1ULL << log2;
|
||||
ci.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
|
||||
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
|
||||
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
|
||||
ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
ci.queueFamilyIndexCount = 0;
|
||||
ci.pQueueFamilyIndices = nullptr;
|
||||
|
||||
auto buffer = std::make_unique<VKBuffer>();
|
||||
buffer->handle = device.GetLogical().CreateBuffer(ci);
|
||||
buffer->handle = device.GetLogical().CreateBuffer({
|
||||
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.size = 1ULL << log2,
|
||||
.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
|
||||
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
|
||||
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
|
||||
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
||||
.queueFamilyIndexCount = 0,
|
||||
.pQueueFamilyIndices = nullptr,
|
||||
});
|
||||
buffer->commit = memory_manager.Commit(buffer->handle, host_visible);
|
||||
|
||||
auto& entries = GetCache(host_visible)[log2].entries;
|
||||
|
|
|
@ -122,30 +122,27 @@ void VKStreamBuffer::CreateBuffers(VkBufferUsageFlags usage) {
|
|||
// Substract from the preferred heap size some bytes to avoid getting out of memory.
|
||||
const VkDeviceSize heap_size = memory_properties.memoryHeaps[preferred_heap].size;
|
||||
const VkDeviceSize allocable_size = heap_size - 9 * 1024 * 1024;
|
||||
|
||||
VkBufferCreateInfo buffer_ci;
|
||||
buffer_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
buffer_ci.pNext = nullptr;
|
||||
buffer_ci.flags = 0;
|
||||
buffer_ci.size = std::min(PREFERRED_STREAM_BUFFER_SIZE, allocable_size);
|
||||
buffer_ci.usage = usage;
|
||||
buffer_ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
buffer_ci.queueFamilyIndexCount = 0;
|
||||
buffer_ci.pQueueFamilyIndices = nullptr;
|
||||
|
||||
buffer = device.GetLogical().CreateBuffer(buffer_ci);
|
||||
buffer = device.GetLogical().CreateBuffer({
|
||||
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.size = std::min(PREFERRED_STREAM_BUFFER_SIZE, allocable_size),
|
||||
.usage = usage,
|
||||
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
||||
.queueFamilyIndexCount = 0,
|
||||
.pQueueFamilyIndices = nullptr,
|
||||
});
|
||||
|
||||
const auto requirements = device.GetLogical().GetBufferMemoryRequirements(*buffer);
|
||||
const u32 required_flags = requirements.memoryTypeBits;
|
||||
stream_buffer_size = static_cast<u64>(requirements.size);
|
||||
|
||||
VkMemoryAllocateInfo memory_ai;
|
||||
memory_ai.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
memory_ai.pNext = nullptr;
|
||||
memory_ai.allocationSize = requirements.size;
|
||||
memory_ai.memoryTypeIndex = GetMemoryType(memory_properties, required_flags);
|
||||
|
||||
memory = device.GetLogical().AllocateMemory(memory_ai);
|
||||
memory = device.GetLogical().AllocateMemory({
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.allocationSize = requirements.size,
|
||||
.memoryTypeIndex = GetMemoryType(memory_properties, required_flags),
|
||||
});
|
||||
buffer.BindMemory(*memory, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -95,15 +95,16 @@ bool VKSwapchain::Present(VkSemaphore render_semaphore, VKFence& fence) {
|
|||
const auto present_queue{device.GetPresentQueue()};
|
||||
bool recreated = false;
|
||||
|
||||
VkPresentInfoKHR present_info;
|
||||
present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
||||
present_info.pNext = nullptr;
|
||||
present_info.waitSemaphoreCount = render_semaphore ? 2U : 1U;
|
||||
present_info.pWaitSemaphores = semaphores.data();
|
||||
present_info.swapchainCount = 1;
|
||||
present_info.pSwapchains = swapchain.address();
|
||||
present_info.pImageIndices = &image_index;
|
||||
present_info.pResults = nullptr;
|
||||
const VkPresentInfoKHR present_info{
|
||||
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
||||
.pNext = nullptr,
|
||||
.waitSemaphoreCount = render_semaphore ? 2U : 1U,
|
||||
.pWaitSemaphores = semaphores.data(),
|
||||
.swapchainCount = 1,
|
||||
.pSwapchains = swapchain.address(),
|
||||
.pImageIndices = &image_index,
|
||||
.pResults = nullptr,
|
||||
};
|
||||
|
||||
switch (const VkResult result = present_queue.Present(present_info)) {
|
||||
case VK_SUCCESS:
|
||||
|
@ -147,24 +148,25 @@ void VKSwapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities,
|
|||
requested_image_count = capabilities.maxImageCount;
|
||||
}
|
||||
|
||||
VkSwapchainCreateInfoKHR swapchain_ci;
|
||||
swapchain_ci.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
||||
swapchain_ci.pNext = nullptr;
|
||||
swapchain_ci.flags = 0;
|
||||
swapchain_ci.surface = surface;
|
||||
swapchain_ci.minImageCount = requested_image_count;
|
||||
swapchain_ci.imageFormat = surface_format.format;
|
||||
swapchain_ci.imageColorSpace = surface_format.colorSpace;
|
||||
swapchain_ci.imageArrayLayers = 1;
|
||||
swapchain_ci.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
swapchain_ci.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
swapchain_ci.queueFamilyIndexCount = 0;
|
||||
swapchain_ci.pQueueFamilyIndices = nullptr;
|
||||
swapchain_ci.preTransform = capabilities.currentTransform;
|
||||
swapchain_ci.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
||||
swapchain_ci.presentMode = present_mode;
|
||||
swapchain_ci.clipped = VK_FALSE;
|
||||
swapchain_ci.oldSwapchain = nullptr;
|
||||
VkSwapchainCreateInfoKHR swapchain_ci{
|
||||
.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.surface = surface,
|
||||
.minImageCount = requested_image_count,
|
||||
.imageFormat = surface_format.format,
|
||||
.imageColorSpace = surface_format.colorSpace,
|
||||
.imageArrayLayers = 1,
|
||||
.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
||||
.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
||||
.queueFamilyIndexCount = 0,
|
||||
.pQueueFamilyIndices = nullptr,
|
||||
.preTransform = capabilities.currentTransform,
|
||||
.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
|
||||
.presentMode = present_mode,
|
||||
.clipped = VK_FALSE,
|
||||
.oldSwapchain = nullptr,
|
||||
};
|
||||
|
||||
const u32 graphics_family{device.GetGraphicsFamily()};
|
||||
const u32 present_family{device.GetPresentFamily()};
|
||||
|
@ -173,8 +175,6 @@ void VKSwapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities,
|
|||
swapchain_ci.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
|
||||
swapchain_ci.queueFamilyIndexCount = static_cast<u32>(queue_indices.size());
|
||||
swapchain_ci.pQueueFamilyIndices = queue_indices.data();
|
||||
} else {
|
||||
swapchain_ci.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
}
|
||||
|
||||
// Request the size again to reduce the possibility of a TOCTOU race condition.
|
||||
|
@ -200,20 +200,28 @@ void VKSwapchain::CreateSemaphores() {
|
|||
}
|
||||
|
||||
void VKSwapchain::CreateImageViews() {
|
||||
VkImageViewCreateInfo ci;
|
||||
ci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
ci.pNext = nullptr;
|
||||
ci.flags = 0;
|
||||
// ci.image
|
||||
ci.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
ci.format = image_format;
|
||||
ci.components = {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY};
|
||||
ci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
ci.subresourceRange.baseMipLevel = 0;
|
||||
ci.subresourceRange.levelCount = 1;
|
||||
ci.subresourceRange.baseArrayLayer = 0;
|
||||
ci.subresourceRange.layerCount = 1;
|
||||
VkImageViewCreateInfo ci{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.viewType = VK_IMAGE_VIEW_TYPE_2D,
|
||||
.format = image_format,
|
||||
.components =
|
||||
{
|
||||
.r = VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
.g = VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
.b = VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
.a = VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
},
|
||||
.subresourceRange =
|
||||
{
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = 1,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
};
|
||||
|
||||
image_views.resize(image_count);
|
||||
for (std::size_t i = 0; i < image_count; i++) {
|
||||
|
|
|
@ -95,17 +95,18 @@ VkImageViewType GetImageViewType(SurfaceTarget target) {
|
|||
vk::Buffer CreateBuffer(const VKDevice& device, const SurfaceParams& params,
|
||||
std::size_t host_memory_size) {
|
||||
// TODO(Rodrigo): Move texture buffer creation to the buffer cache
|
||||
VkBufferCreateInfo ci;
|
||||
ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
ci.pNext = nullptr;
|
||||
ci.flags = 0;
|
||||
ci.size = static_cast<VkDeviceSize>(host_memory_size);
|
||||
ci.usage = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT |
|
||||
VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
||||
ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
ci.queueFamilyIndexCount = 0;
|
||||
ci.pQueueFamilyIndices = nullptr;
|
||||
return device.GetLogical().CreateBuffer(ci);
|
||||
return device.GetLogical().CreateBuffer({
|
||||
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.size = static_cast<VkDeviceSize>(host_memory_size),
|
||||
.usage = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT |
|
||||
VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
|
||||
VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
||||
.queueFamilyIndexCount = 0,
|
||||
.pQueueFamilyIndices = nullptr,
|
||||
});
|
||||
}
|
||||
|
||||
VkBufferViewCreateInfo GenerateBufferViewCreateInfo(const VKDevice& device,
|
||||
|
@ -113,15 +114,16 @@ VkBufferViewCreateInfo GenerateBufferViewCreateInfo(const VKDevice& device,
|
|||
std::size_t host_memory_size) {
|
||||
ASSERT(params.IsBuffer());
|
||||
|
||||
VkBufferViewCreateInfo ci;
|
||||
ci.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO;
|
||||
ci.pNext = nullptr;
|
||||
ci.flags = 0;
|
||||
ci.buffer = buffer;
|
||||
ci.format = MaxwellToVK::SurfaceFormat(device, FormatType::Buffer, params.pixel_format).format;
|
||||
ci.offset = 0;
|
||||
ci.range = static_cast<VkDeviceSize>(host_memory_size);
|
||||
return ci;
|
||||
return {
|
||||
.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.buffer = buffer,
|
||||
.format =
|
||||
MaxwellToVK::SurfaceFormat(device, FormatType::Buffer, params.pixel_format).format,
|
||||
.offset = 0,
|
||||
.range = static_cast<VkDeviceSize>(host_memory_size),
|
||||
};
|
||||
}
|
||||
|
||||
VkImageCreateInfo GenerateImageCreateInfo(const VKDevice& device, const SurfaceParams& params) {
|
||||
|
@ -130,23 +132,23 @@ VkImageCreateInfo GenerateImageCreateInfo(const VKDevice& device, const SurfaceP
|
|||
const auto [format, attachable, storage] =
|
||||
MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, params.pixel_format);
|
||||
|
||||
VkImageCreateInfo ci;
|
||||
ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||
ci.pNext = nullptr;
|
||||
ci.flags = 0;
|
||||
ci.imageType = SurfaceTargetToImage(params.target);
|
||||
ci.format = format;
|
||||
ci.mipLevels = params.num_levels;
|
||||
ci.arrayLayers = static_cast<u32>(params.GetNumLayers());
|
||||
ci.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
ci.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
ci.queueFamilyIndexCount = 0;
|
||||
ci.pQueueFamilyIndices = nullptr;
|
||||
ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
|
||||
ci.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
|
||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||
VkImageCreateInfo ci{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.imageType = SurfaceTargetToImage(params.target),
|
||||
.format = format,
|
||||
.mipLevels = params.num_levels,
|
||||
.arrayLayers = static_cast<u32>(params.GetNumLayers()),
|
||||
.samples = VK_SAMPLE_COUNT_1_BIT,
|
||||
.tiling = VK_IMAGE_TILING_OPTIMAL,
|
||||
.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
|
||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
|
||||
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
||||
.queueFamilyIndexCount = 0,
|
||||
.pQueueFamilyIndices = nullptr,
|
||||
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
};
|
||||
if (attachable) {
|
||||
ci.usage |= params.IsPixelFormatZeta() ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
|
||||
: VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
|
@ -321,22 +323,25 @@ void CachedSurface::UploadImage(const std::vector<u8>& staging_buffer) {
|
|||
}
|
||||
|
||||
VkBufferImageCopy CachedSurface::GetBufferImageCopy(u32 level) const {
|
||||
VkBufferImageCopy copy;
|
||||
copy.bufferOffset = params.GetHostMipmapLevelOffset(level, is_converted);
|
||||
copy.bufferRowLength = 0;
|
||||
copy.bufferImageHeight = 0;
|
||||
copy.imageSubresource.aspectMask = image->GetAspectMask();
|
||||
copy.imageSubresource.mipLevel = level;
|
||||
copy.imageSubresource.baseArrayLayer = 0;
|
||||
copy.imageSubresource.layerCount = static_cast<u32>(params.GetNumLayers());
|
||||
copy.imageOffset.x = 0;
|
||||
copy.imageOffset.y = 0;
|
||||
copy.imageOffset.z = 0;
|
||||
copy.imageExtent.width = params.GetMipWidth(level);
|
||||
copy.imageExtent.height = params.GetMipHeight(level);
|
||||
copy.imageExtent.depth =
|
||||
params.target == SurfaceTarget::Texture3D ? params.GetMipDepth(level) : 1;
|
||||
return copy;
|
||||
return {
|
||||
.bufferOffset = params.GetHostMipmapLevelOffset(level, is_converted),
|
||||
.bufferRowLength = 0,
|
||||
.bufferImageHeight = 0,
|
||||
.imageSubresource =
|
||||
{
|
||||
.aspectMask = image->GetAspectMask(),
|
||||
.mipLevel = level,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = static_cast<u32>(params.GetNumLayers()),
|
||||
},
|
||||
.imageOffset = {.x = 0, .y = 0, .z = 0},
|
||||
.imageExtent =
|
||||
{
|
||||
.width = params.GetMipWidth(level),
|
||||
.height = params.GetMipHeight(level),
|
||||
.depth = params.target == SurfaceTarget::Texture3D ? params.GetMipDepth(level) : 1U,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
VkImageSubresourceRange CachedSurface::GetImageSubresourceRange() const {
|
||||
|
@ -416,20 +421,29 @@ VkImageView CachedSurfaceView::GetImageView(SwizzleSource x_source, SwizzleSourc
|
|||
ASSERT(num_slices == params.depth);
|
||||
}
|
||||
|
||||
VkImageViewCreateInfo ci;
|
||||
ci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
ci.pNext = nullptr;
|
||||
ci.flags = 0;
|
||||
ci.image = surface.GetImageHandle();
|
||||
ci.viewType = image_view_type;
|
||||
ci.format = surface.GetImage().GetFormat();
|
||||
ci.components = {swizzle[0], swizzle[1], swizzle[2], swizzle[3]};
|
||||
ci.subresourceRange.aspectMask = aspect;
|
||||
ci.subresourceRange.baseMipLevel = base_level;
|
||||
ci.subresourceRange.levelCount = num_levels;
|
||||
ci.subresourceRange.baseArrayLayer = base_layer;
|
||||
ci.subresourceRange.layerCount = num_layers;
|
||||
image_view = device.GetLogical().CreateImageView(ci);
|
||||
image_view = device.GetLogical().CreateImageView({
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.image = surface.GetImageHandle(),
|
||||
.viewType = image_view_type,
|
||||
.format = surface.GetImage().GetFormat(),
|
||||
.components =
|
||||
{
|
||||
.r = swizzle[0],
|
||||
.g = swizzle[1],
|
||||
.b = swizzle[2],
|
||||
.a = swizzle[3],
|
||||
},
|
||||
.subresourceRange =
|
||||
{
|
||||
.aspectMask = aspect,
|
||||
.baseMipLevel = base_level,
|
||||
.levelCount = num_levels,
|
||||
.baseArrayLayer = base_layer,
|
||||
.layerCount = num_layers,
|
||||
},
|
||||
});
|
||||
|
||||
return last_image_view = *image_view;
|
||||
}
|
||||
|
@ -439,17 +453,26 @@ VkImageView CachedSurfaceView::GetAttachment() {
|
|||
return *render_target;
|
||||
}
|
||||
|
||||
VkImageViewCreateInfo ci;
|
||||
ci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
ci.pNext = nullptr;
|
||||
ci.flags = 0;
|
||||
ci.image = surface.GetImageHandle();
|
||||
ci.format = surface.GetImage().GetFormat();
|
||||
ci.components = {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY};
|
||||
ci.subresourceRange.aspectMask = aspect_mask;
|
||||
ci.subresourceRange.baseMipLevel = base_level;
|
||||
ci.subresourceRange.levelCount = num_levels;
|
||||
VkImageViewCreateInfo ci{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.image = surface.GetImageHandle(),
|
||||
.format = surface.GetImage().GetFormat(),
|
||||
.components =
|
||||
{
|
||||
.r = VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
.g = VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
.b = VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
.a = VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
},
|
||||
.subresourceRange =
|
||||
{
|
||||
.aspectMask = aspect_mask,
|
||||
.baseMipLevel = base_level,
|
||||
.levelCount = num_levels,
|
||||
},
|
||||
};
|
||||
if (image_view_type == VK_IMAGE_VIEW_TYPE_3D) {
|
||||
ci.viewType = num_slices > 1 ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D;
|
||||
ci.subresourceRange.baseArrayLayer = base_slice;
|
||||
|
@ -502,24 +525,40 @@ void VKTextureCache::ImageCopy(Surface& src_surface, Surface& dst_surface,
|
|||
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
|
||||
VkImageCopy copy;
|
||||
copy.srcSubresource.aspectMask = src_surface->GetAspectMask();
|
||||
copy.srcSubresource.mipLevel = copy_params.source_level;
|
||||
copy.srcSubresource.baseArrayLayer = copy_params.source_z;
|
||||
copy.srcSubresource.layerCount = num_layers;
|
||||
copy.srcOffset.x = copy_params.source_x;
|
||||
copy.srcOffset.y = copy_params.source_y;
|
||||
copy.srcOffset.z = 0;
|
||||
copy.dstSubresource.aspectMask = dst_surface->GetAspectMask();
|
||||
copy.dstSubresource.mipLevel = copy_params.dest_level;
|
||||
copy.dstSubresource.baseArrayLayer = dst_base_layer;
|
||||
copy.dstSubresource.layerCount = num_layers;
|
||||
copy.dstOffset.x = copy_params.dest_x;
|
||||
copy.dstOffset.y = copy_params.dest_y;
|
||||
copy.dstOffset.z = dst_offset_z;
|
||||
copy.extent.width = copy_params.width;
|
||||
copy.extent.height = copy_params.height;
|
||||
copy.extent.depth = extent_z;
|
||||
const VkImageCopy copy{
|
||||
.srcSubresource =
|
||||
{
|
||||
.aspectMask = src_surface->GetAspectMask(),
|
||||
.mipLevel = copy_params.source_level,
|
||||
.baseArrayLayer = copy_params.source_z,
|
||||
.layerCount = num_layers,
|
||||
},
|
||||
.srcOffset =
|
||||
{
|
||||
.x = static_cast<s32>(copy_params.source_x),
|
||||
.y = static_cast<s32>(copy_params.source_y),
|
||||
.z = 0,
|
||||
},
|
||||
.dstSubresource =
|
||||
{
|
||||
.aspectMask = dst_surface->GetAspectMask(),
|
||||
.mipLevel = copy_params.dest_level,
|
||||
.baseArrayLayer = dst_base_layer,
|
||||
.layerCount = num_layers,
|
||||
},
|
||||
.dstOffset =
|
||||
{
|
||||
.x = static_cast<s32>(copy_params.dest_x),
|
||||
.y = static_cast<s32>(copy_params.dest_y),
|
||||
.z = static_cast<s32>(dst_offset_z),
|
||||
},
|
||||
.extent =
|
||||
{
|
||||
.width = copy_params.width,
|
||||
.height = copy_params.height,
|
||||
.depth = extent_z,
|
||||
},
|
||||
};
|
||||
|
||||
const VkImage src_image = src_surface->GetImageHandle();
|
||||
const VkImage dst_image = dst_surface->GetImageHandle();
|
||||
|
|
|
@ -377,24 +377,26 @@ VkResult Free(VkDevice device, VkCommandPool handle, Span<VkCommandBuffer> buffe
|
|||
|
||||
Instance Instance::Create(Span<const char*> layers, Span<const char*> extensions,
|
||||
InstanceDispatch& dld) noexcept {
|
||||
VkApplicationInfo application_info;
|
||||
application_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
||||
application_info.pNext = nullptr;
|
||||
application_info.pApplicationName = "yuzu Emulator";
|
||||
application_info.applicationVersion = VK_MAKE_VERSION(0, 1, 0);
|
||||
application_info.pEngineName = "yuzu Emulator";
|
||||
application_info.engineVersion = VK_MAKE_VERSION(0, 1, 0);
|
||||
application_info.apiVersion = VK_API_VERSION_1_1;
|
||||
static constexpr VkApplicationInfo application_info{
|
||||
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
|
||||
.pNext = nullptr,
|
||||
.pApplicationName = "yuzu Emulator",
|
||||
.applicationVersion = VK_MAKE_VERSION(0, 1, 0),
|
||||
.pEngineName = "yuzu Emulator",
|
||||
.engineVersion = VK_MAKE_VERSION(0, 1, 0),
|
||||
.apiVersion = VK_API_VERSION_1_1,
|
||||
};
|
||||
|
||||
VkInstanceCreateInfo ci;
|
||||
ci.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||||
ci.pNext = nullptr;
|
||||
ci.flags = 0;
|
||||
ci.pApplicationInfo = &application_info;
|
||||
ci.enabledLayerCount = layers.size();
|
||||
ci.ppEnabledLayerNames = layers.data();
|
||||
ci.enabledExtensionCount = extensions.size();
|
||||
ci.ppEnabledExtensionNames = extensions.data();
|
||||
const VkInstanceCreateInfo ci{
|
||||
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.pApplicationInfo = &application_info,
|
||||
.enabledLayerCount = layers.size(),
|
||||
.ppEnabledLayerNames = layers.data(),
|
||||
.enabledExtensionCount = extensions.size(),
|
||||
.ppEnabledExtensionNames = extensions.data(),
|
||||
};
|
||||
|
||||
VkInstance instance;
|
||||
if (dld.vkCreateInstance(&ci, nullptr, &instance) != VK_SUCCESS) {
|
||||
|
@ -425,19 +427,20 @@ std::optional<std::vector<VkPhysicalDevice>> Instance::EnumeratePhysicalDevices(
|
|||
|
||||
DebugCallback Instance::TryCreateDebugCallback(
|
||||
PFN_vkDebugUtilsMessengerCallbackEXT callback) noexcept {
|
||||
VkDebugUtilsMessengerCreateInfoEXT ci;
|
||||
ci.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
|
||||
ci.pNext = nullptr;
|
||||
ci.flags = 0;
|
||||
ci.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT |
|
||||
VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
|
||||
VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT |
|
||||
VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT;
|
||||
ci.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
|
||||
VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
|
||||
VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
|
||||
ci.pfnUserCallback = callback;
|
||||
ci.pUserData = nullptr;
|
||||
const VkDebugUtilsMessengerCreateInfoEXT ci{
|
||||
.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT |
|
||||
VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
|
||||
VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT |
|
||||
VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT,
|
||||
.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
|
||||
VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
|
||||
VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT,
|
||||
.pfnUserCallback = callback,
|
||||
.pUserData = nullptr,
|
||||
};
|
||||
|
||||
VkDebugUtilsMessengerEXT messenger;
|
||||
if (dld->vkCreateDebugUtilsMessengerEXT(handle, &ci, nullptr, &messenger) != VK_SUCCESS) {
|
||||
|
@ -468,12 +471,13 @@ DescriptorSets DescriptorPool::Allocate(const VkDescriptorSetAllocateInfo& ai) c
|
|||
}
|
||||
|
||||
CommandBuffers CommandPool::Allocate(std::size_t num_buffers, VkCommandBufferLevel level) const {
|
||||
VkCommandBufferAllocateInfo ai;
|
||||
ai.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
||||
ai.pNext = nullptr;
|
||||
ai.commandPool = handle;
|
||||
ai.level = level;
|
||||
ai.commandBufferCount = static_cast<u32>(num_buffers);
|
||||
const VkCommandBufferAllocateInfo ai{
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.commandPool = handle,
|
||||
.level = level,
|
||||
.commandBufferCount = static_cast<u32>(num_buffers),
|
||||
};
|
||||
|
||||
std::unique_ptr buffers = std::make_unique<VkCommandBuffer[]>(num_buffers);
|
||||
switch (const VkResult result = dld->vkAllocateCommandBuffers(owner, &ai, buffers.get())) {
|
||||
|
@ -497,17 +501,18 @@ std::vector<VkImage> SwapchainKHR::GetImages() const {
|
|||
Device Device::Create(VkPhysicalDevice physical_device, Span<VkDeviceQueueCreateInfo> queues_ci,
|
||||
Span<const char*> enabled_extensions, const void* next,
|
||||
DeviceDispatch& dld) noexcept {
|
||||
VkDeviceCreateInfo ci;
|
||||
ci.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||
ci.pNext = next;
|
||||
ci.flags = 0;
|
||||
ci.queueCreateInfoCount = queues_ci.size();
|
||||
ci.pQueueCreateInfos = queues_ci.data();
|
||||
ci.enabledLayerCount = 0;
|
||||
ci.ppEnabledLayerNames = nullptr;
|
||||
ci.enabledExtensionCount = enabled_extensions.size();
|
||||
ci.ppEnabledExtensionNames = enabled_extensions.data();
|
||||
ci.pEnabledFeatures = nullptr;
|
||||
const VkDeviceCreateInfo ci{
|
||||
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
||||
.pNext = next,
|
||||
.flags = 0,
|
||||
.queueCreateInfoCount = queues_ci.size(),
|
||||
.pQueueCreateInfos = queues_ci.data(),
|
||||
.enabledLayerCount = 0,
|
||||
.ppEnabledLayerNames = nullptr,
|
||||
.enabledExtensionCount = enabled_extensions.size(),
|
||||
.ppEnabledExtensionNames = enabled_extensions.data(),
|
||||
.pEnabledFeatures = nullptr,
|
||||
};
|
||||
|
||||
VkDevice device;
|
||||
if (dld.vkCreateDevice(physical_device, &ci, nullptr, &device) != VK_SUCCESS) {
|
||||
|
@ -548,10 +553,11 @@ ImageView Device::CreateImageView(const VkImageViewCreateInfo& ci) const {
|
|||
}
|
||||
|
||||
Semaphore Device::CreateSemaphore() const {
|
||||
VkSemaphoreCreateInfo ci;
|
||||
ci.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
||||
ci.pNext = nullptr;
|
||||
ci.flags = 0;
|
||||
static constexpr VkSemaphoreCreateInfo ci{
|
||||
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
};
|
||||
|
||||
VkSemaphore object;
|
||||
Check(dld->vkCreateSemaphore(handle, &ci, nullptr, &object));
|
||||
|
@ -639,10 +645,12 @@ ShaderModule Device::CreateShaderModule(const VkShaderModuleCreateInfo& ci) cons
|
|||
}
|
||||
|
||||
Event Device::CreateEvent() const {
|
||||
VkEventCreateInfo ci;
|
||||
ci.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO;
|
||||
ci.pNext = nullptr;
|
||||
ci.flags = 0;
|
||||
static constexpr VkEventCreateInfo ci{
|
||||
.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
};
|
||||
|
||||
VkEvent object;
|
||||
Check(dld->vkCreateEvent(handle, &ci, nullptr, &object));
|
||||
return Event(object, handle, *dld);
|
||||
|
|
Loading…
Reference in a new issue