Merge branch 'master' of https://github.com/xenia-project/xenia into canary_experimental
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
#include "xenia/base/assert.h"
|
||||
#include "xenia/base/math.h"
|
||||
#include "xenia/base/profiling.h"
|
||||
#include "xenia/gpu/gpu_flags.h"
|
||||
#include "xenia/gpu/vulkan/vulkan_command_processor.h"
|
||||
|
||||
namespace xe {
|
||||
@@ -29,12 +30,12 @@ DeferredCommandBuffer::DeferredCommandBuffer(
|
||||
void DeferredCommandBuffer::Reset() { command_stream_.clear(); }
|
||||
|
||||
void DeferredCommandBuffer::Execute(VkCommandBuffer command_buffer) {
|
||||
#if XE_UI_VULKAN_FINE_GRAINED_DRAW_SCOPES
|
||||
#if XE_GPU_FINE_GRAINED_DRAW_SCOPES
|
||||
SCOPE_profile_cpu_f("gpu");
|
||||
#endif // XE_UI_VULKAN_FINE_GRAINED_DRAW_SCOPES
|
||||
#endif // XE_GPU_FINE_GRAINED_DRAW_SCOPES
|
||||
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn =
|
||||
command_processor_.GetVulkanProvider().dfn();
|
||||
const ui::vulkan::VulkanDevice::Functions& dfn =
|
||||
command_processor_.GetVulkanDevice()->functions();
|
||||
const uintmax_t* stream = command_stream_.data();
|
||||
size_t stream_remaining = command_stream_.size();
|
||||
while (stream_remaining) {
|
||||
|
||||
@@ -13,10 +13,11 @@
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
#include "xenia/base/assert.h"
|
||||
#include "xenia/base/math.h"
|
||||
#include "xenia/ui/vulkan/vulkan_provider.h"
|
||||
#include "xenia/ui/vulkan/vulkan_api.h"
|
||||
|
||||
namespace xe {
|
||||
namespace gpu {
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
#include "xenia/kernel/kernel_state.h"
|
||||
#include "xenia/kernel/user_module.h"
|
||||
#include "xenia/ui/vulkan/vulkan_presenter.h"
|
||||
#include "xenia/ui/vulkan/vulkan_provider.h"
|
||||
#include "xenia/ui/vulkan/vulkan_util.h"
|
||||
|
||||
DECLARE_bool(clear_memory_page_state);
|
||||
@@ -72,18 +71,21 @@ VulkanCommandProcessor::VulkanCommandProcessor(
|
||||
: CommandProcessor(graphics_system, kernel_state),
|
||||
deferred_command_buffer_(*this),
|
||||
transient_descriptor_allocator_uniform_buffer_(
|
||||
*static_cast<const ui::vulkan::VulkanProvider*>(
|
||||
graphics_system->provider()),
|
||||
static_cast<const ui::vulkan::VulkanProvider*>(
|
||||
graphics_system->provider())
|
||||
->vulkan_device(),
|
||||
&kDescriptorPoolSizeUniformBuffer, 1,
|
||||
kLinkedTypeDescriptorPoolSetCount),
|
||||
transient_descriptor_allocator_storage_buffer_(
|
||||
*static_cast<const ui::vulkan::VulkanProvider*>(
|
||||
graphics_system->provider()),
|
||||
static_cast<const ui::vulkan::VulkanProvider*>(
|
||||
graphics_system->provider())
|
||||
->vulkan_device(),
|
||||
&kDescriptorPoolSizeStorageBuffer, 1,
|
||||
kLinkedTypeDescriptorPoolSetCount),
|
||||
transient_descriptor_allocator_textures_(
|
||||
*static_cast<const ui::vulkan::VulkanProvider*>(
|
||||
graphics_system->provider()),
|
||||
static_cast<const ui::vulkan::VulkanProvider*>(
|
||||
graphics_system->provider())
|
||||
->vulkan_device(),
|
||||
kDescriptorPoolSizeTextures,
|
||||
uint32_t(xe::countof(kDescriptorPoolSizeTextures)),
|
||||
kLinkedTypeDescriptorPoolSetCount) {}
|
||||
@@ -135,11 +137,11 @@ bool VulkanCommandProcessor::SetupContext() {
|
||||
return false;
|
||||
}
|
||||
|
||||
const ui::vulkan::VulkanProvider& provider = GetVulkanProvider();
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||
VkDevice device = provider.device();
|
||||
const ui::vulkan::VulkanProvider::DeviceInfo& device_info =
|
||||
provider.device_info();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device = GetVulkanDevice();
|
||||
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
|
||||
const VkDevice device = vulkan_device->device();
|
||||
const ui::vulkan::VulkanDevice::Properties& device_properties =
|
||||
vulkan_device->properties();
|
||||
|
||||
// The unconditional inclusion of the vertex shader stage also covers the case
|
||||
// of manual index / factor buffer fetch (the system constants and the shared
|
||||
@@ -148,12 +150,12 @@ bool VulkanCommandProcessor::SetupContext() {
|
||||
guest_shader_pipeline_stages_ = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||
guest_shader_vertex_stages_ = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
if (device_info.tessellationShader) {
|
||||
if (device_properties.tessellationShader) {
|
||||
guest_shader_pipeline_stages_ |=
|
||||
VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT;
|
||||
guest_shader_vertex_stages_ |= VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
|
||||
}
|
||||
if (!device_info.vertexPipelineStoresAndAtomics) {
|
||||
if (!device_properties.vertexPipelineStoresAndAtomics) {
|
||||
// For memory export from vertex shaders converted to compute shaders.
|
||||
guest_shader_pipeline_stages_ |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
|
||||
guest_shader_vertex_stages_ |= VK_SHADER_STAGE_COMPUTE_BIT;
|
||||
@@ -162,10 +164,10 @@ bool VulkanCommandProcessor::SetupContext() {
|
||||
// 16384 is bigger than any single uniform buffer that Xenia needs, but is the
|
||||
// minimum maxUniformBufferRange, thus the safe minimum amount.
|
||||
uniform_buffer_pool_ = std::make_unique<ui::vulkan::VulkanUploadBufferPool>(
|
||||
provider, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
|
||||
vulkan_device, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
|
||||
xe::align(std::max(ui::GraphicsUploadBufferPool::kDefaultPageSize,
|
||||
size_t(16384)),
|
||||
size_t(device_info.minUniformBufferOffsetAlignment)));
|
||||
size_t(device_properties.minUniformBufferOffsetAlignment)));
|
||||
|
||||
// Descriptor set layouts that don't depend on the setup of other subsystems.
|
||||
VkShaderStageFlags guest_shader_stages =
|
||||
@@ -199,9 +201,10 @@ bool VulkanCommandProcessor::SetupContext() {
|
||||
[SpirvShaderTranslator::kConstantBufferSystem]
|
||||
.stageFlags =
|
||||
guest_shader_stages |
|
||||
(device_info.tessellationShader ? VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT
|
||||
: 0) |
|
||||
(device_info.geometryShader ? VK_SHADER_STAGE_GEOMETRY_BIT : 0);
|
||||
(device_properties.tessellationShader
|
||||
? VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT
|
||||
: 0) |
|
||||
(device_properties.geometryShader ? VK_SHADER_STAGE_GEOMETRY_BIT : 0);
|
||||
descriptor_set_layout_bindings_constants
|
||||
[SpirvShaderTranslator::kConstantBufferFloatVertex]
|
||||
.stageFlags = guest_shader_vertex_stages_;
|
||||
@@ -280,7 +283,7 @@ bool VulkanCommandProcessor::SetupContext() {
|
||||
|
||||
uint32_t shared_memory_binding_count_log2 =
|
||||
SpirvShaderTranslator::GetSharedMemoryStorageBufferCountLog2(
|
||||
device_info.maxStorageBufferRange);
|
||||
device_properties.maxStorageBufferRange);
|
||||
uint32_t shared_memory_binding_count = UINT32_C(1)
|
||||
<< shared_memory_binding_count_log2;
|
||||
|
||||
@@ -484,14 +487,14 @@ bool VulkanCommandProcessor::SetupContext() {
|
||||
&gamma_ramp_host_visible_buffer_memory_requirements);
|
||||
uint32_t gamma_ramp_host_visible_buffer_memory_types =
|
||||
gamma_ramp_host_visible_buffer_memory_requirements.memoryTypeBits &
|
||||
(device_info.memory_types_device_local &
|
||||
device_info.memory_types_host_visible);
|
||||
(vulkan_device->memory_types().device_local &
|
||||
vulkan_device->memory_types().host_visible);
|
||||
VkMemoryAllocateInfo gamma_ramp_host_visible_buffer_memory_allocate_info;
|
||||
// Prefer a host-uncached (because it's write-only) memory type, but try a
|
||||
// host-cached host-visible device-local one as well.
|
||||
if (xe::bit_scan_forward(
|
||||
gamma_ramp_host_visible_buffer_memory_types &
|
||||
~device_info.memory_types_host_cached,
|
||||
~vulkan_device->memory_types().host_cached,
|
||||
&(gamma_ramp_host_visible_buffer_memory_allocate_info
|
||||
.memoryTypeIndex)) ||
|
||||
xe::bit_scan_forward(
|
||||
@@ -508,7 +511,7 @@ bool VulkanCommandProcessor::SetupContext() {
|
||||
gamma_ramp_host_visible_buffer_memory_requirements.size;
|
||||
VkMemoryDedicatedAllocateInfo
|
||||
gamma_ramp_host_visible_buffer_memory_dedicated_allocate_info;
|
||||
if (device_info.ext_1_1_VK_KHR_dedicated_allocation) {
|
||||
if (vulkan_device->extensions().ext_1_1_KHR_dedicated_allocation) {
|
||||
gamma_ramp_host_visible_buffer_memory_allocate_info_last->pNext =
|
||||
&gamma_ramp_host_visible_buffer_memory_dedicated_allocate_info;
|
||||
gamma_ramp_host_visible_buffer_memory_allocate_info_last =
|
||||
@@ -555,7 +558,7 @@ bool VulkanCommandProcessor::SetupContext() {
|
||||
if (gamma_ramp_buffer_ == VK_NULL_HANDLE) {
|
||||
// Create separate buffers for the shader and uploading.
|
||||
if (!ui::vulkan::util::CreateDedicatedAllocationBuffer(
|
||||
provider, kGammaRampSize,
|
||||
vulkan_device, kGammaRampSize,
|
||||
VK_BUFFER_USAGE_TRANSFER_DST_BIT |
|
||||
VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT,
|
||||
ui::vulkan::util::MemoryPurpose::kDeviceLocal, gamma_ramp_buffer_,
|
||||
@@ -564,7 +567,7 @@ bool VulkanCommandProcessor::SetupContext() {
|
||||
return false;
|
||||
}
|
||||
if (!ui::vulkan::util::CreateDedicatedAllocationBuffer(
|
||||
provider, kGammaRampSize * kMaxFramesInFlight,
|
||||
vulkan_device, kGammaRampSize * kMaxFramesInFlight,
|
||||
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
||||
ui::vulkan::util::MemoryPurpose::kUpload, gamma_ramp_upload_buffer_,
|
||||
gamma_ramp_upload_buffer_memory_, &gamma_ramp_upload_memory_type_,
|
||||
@@ -854,11 +857,11 @@ bool VulkanCommandProcessor::SetupContext() {
|
||||
bool swap_apply_gamma_pixel_shaders_created =
|
||||
(swap_apply_gamma_pixel_shaders[kSwapApplyGammaPixelShader256EntryTable] =
|
||||
ui::vulkan::util::CreateShaderModule(
|
||||
provider, shaders::apply_gamma_table_ps,
|
||||
vulkan_device, shaders::apply_gamma_table_ps,
|
||||
sizeof(shaders::apply_gamma_table_ps))) != VK_NULL_HANDLE &&
|
||||
(swap_apply_gamma_pixel_shaders[kSwapApplyGammaPixelShaderPWL] =
|
||||
ui::vulkan::util::CreateShaderModule(
|
||||
provider, shaders::apply_gamma_pwl_ps,
|
||||
vulkan_device, shaders::apply_gamma_pwl_ps,
|
||||
sizeof(shaders::apply_gamma_pwl_ps))) != VK_NULL_HANDLE;
|
||||
if (!swap_apply_gamma_pixel_shaders_created) {
|
||||
XELOGE("Failed to create the gamma ramp application pixel shader modules");
|
||||
@@ -879,7 +882,8 @@ bool VulkanCommandProcessor::SetupContext() {
|
||||
swap_apply_gamma_pipeline_stages[0].flags = 0;
|
||||
swap_apply_gamma_pipeline_stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
swap_apply_gamma_pipeline_stages[0].module =
|
||||
ui::vulkan::util::CreateShaderModule(provider, shaders::fullscreen_cw_vs,
|
||||
ui::vulkan::util::CreateShaderModule(vulkan_device,
|
||||
shaders::fullscreen_cw_vs,
|
||||
sizeof(shaders::fullscreen_cw_vs));
|
||||
if (swap_apply_gamma_pipeline_stages[0].module == VK_NULL_HANDLE) {
|
||||
XELOGE("Failed to create the gamma ramp application vertex shader module");
|
||||
@@ -1037,9 +1041,9 @@ bool VulkanCommandProcessor::SetupContext() {
|
||||
void VulkanCommandProcessor::ShutdownContext() {
|
||||
AwaitAllQueueOperationsCompletion();
|
||||
|
||||
const ui::vulkan::VulkanProvider& provider = GetVulkanProvider();
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||
VkDevice device = provider.device();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device = GetVulkanDevice();
|
||||
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
|
||||
const VkDevice device = vulkan_device->device();
|
||||
|
||||
DestroyScratchBuffer();
|
||||
|
||||
@@ -1299,9 +1303,10 @@ void VulkanCommandProcessor::IssueSwap(uint32_t frontbuffer_ptr,
|
||||
context);
|
||||
uint64_t guest_output_image_version = vulkan_context.image_version();
|
||||
|
||||
const ui::vulkan::VulkanProvider& provider = GetVulkanProvider();
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||
VkDevice device = provider.device();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device = GetVulkanDevice();
|
||||
const ui::vulkan::VulkanDevice::Functions& dfn =
|
||||
vulkan_device->functions();
|
||||
const VkDevice device = vulkan_device->device();
|
||||
|
||||
uint32_t swap_frame_index =
|
||||
uint32_t(frame_current_ % kMaxFramesInFlight);
|
||||
@@ -1368,7 +1373,7 @@ void VulkanCommandProcessor::IssueSwap(uint32_t frontbuffer_ptr,
|
||||
bool gamma_ramp_has_upload_buffer =
|
||||
gamma_ramp_upload_buffer_memory_ != VK_NULL_HANDLE;
|
||||
ui::vulkan::util::FlushMappedMemoryRange(
|
||||
provider,
|
||||
vulkan_device,
|
||||
gamma_ramp_has_upload_buffer ? gamma_ramp_upload_buffer_memory_
|
||||
: gamma_ramp_buffer_memory_,
|
||||
gamma_ramp_upload_memory_type_, gamma_ramp_upload_offset,
|
||||
@@ -1826,9 +1831,9 @@ VkDescriptorSet VulkanCommandProcessor::AllocateSingleTransientDescriptor(
|
||||
descriptor_set = transient_descriptors_free.back();
|
||||
transient_descriptors_free.pop_back();
|
||||
} else {
|
||||
const ui::vulkan::VulkanProvider& provider = GetVulkanProvider();
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||
VkDevice device = provider.device();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device = GetVulkanDevice();
|
||||
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
|
||||
const VkDevice device = vulkan_device->device();
|
||||
bool is_storage_buffer =
|
||||
transient_descriptor_layout ==
|
||||
SingleTransientDescriptorLayout::kStorageBufferCompute;
|
||||
@@ -1873,9 +1878,9 @@ VkDescriptorSetLayout VulkanCommandProcessor::GetTextureDescriptorSetLayout(
|
||||
return it_existing->second;
|
||||
}
|
||||
|
||||
const ui::vulkan::VulkanProvider& provider = GetVulkanProvider();
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||
VkDevice device = provider.device();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device = GetVulkanDevice();
|
||||
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
|
||||
const VkDevice device = vulkan_device->device();
|
||||
|
||||
descriptor_set_layout_bindings_.clear();
|
||||
descriptor_set_layout_bindings_.reserve(binding_count);
|
||||
@@ -1969,9 +1974,9 @@ VulkanCommandProcessor::GetPipelineLayout(size_t texture_count_pixel,
|
||||
descriptor_set_layouts[SpirvShaderTranslator::kDescriptorSetTexturesPixel] =
|
||||
descriptor_set_layout_textures_pixel;
|
||||
|
||||
const ui::vulkan::VulkanProvider& provider = GetVulkanProvider();
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||
VkDevice device = provider.device();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device = GetVulkanDevice();
|
||||
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
|
||||
const VkDevice device = vulkan_device->device();
|
||||
|
||||
VkPipelineLayoutCreateInfo pipeline_layout_create_info;
|
||||
pipeline_layout_create_info.sType =
|
||||
@@ -2029,14 +2034,14 @@ VulkanCommandProcessor::AcquireScratchGpuBuffer(
|
||||
|
||||
size = xe::align(size, kScratchBufferSizeIncrement);
|
||||
|
||||
const ui::vulkan::VulkanProvider& provider = GetVulkanProvider();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device = GetVulkanDevice();
|
||||
|
||||
VkDeviceMemory new_scratch_buffer_memory;
|
||||
VkBuffer new_scratch_buffer;
|
||||
// VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT for
|
||||
// texture loading.
|
||||
if (!ui::vulkan::util::CreateDedicatedAllocationBuffer(
|
||||
provider, size,
|
||||
vulkan_device, size,
|
||||
VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
|
||||
ui::vulkan::util::MemoryPurpose::kDeviceLocal, new_scratch_buffer,
|
||||
new_scratch_buffer_memory)) {
|
||||
@@ -2047,8 +2052,8 @@ VulkanCommandProcessor::AcquireScratchGpuBuffer(
|
||||
}
|
||||
|
||||
if (submission_completed_ >= scratch_buffer_last_usage_submission_) {
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||
VkDevice device = provider.device();
|
||||
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
|
||||
const VkDevice device = vulkan_device->device();
|
||||
if (scratch_buffer_ != VK_NULL_HANDLE) {
|
||||
dfn.vkDestroyBuffer(device, scratch_buffer_, nullptr);
|
||||
}
|
||||
@@ -2163,20 +2168,20 @@ bool VulkanCommandProcessor::IssueDraw(xenos::PrimitiveType prim_type,
|
||||
uint32_t index_count,
|
||||
IndexBufferInfo* index_buffer_info,
|
||||
bool major_mode_explicit) {
|
||||
#if XE_UI_VULKAN_FINE_GRAINED_DRAW_SCOPES
|
||||
#if XE_GPU_FINE_GRAINED_DRAW_SCOPES
|
||||
SCOPE_profile_cpu_f("gpu");
|
||||
#endif // XE_UI_VULKAN_FINE_GRAINED_DRAW_SCOPES
|
||||
#endif // XE_GPU_FINE_GRAINED_DRAW_SCOPES
|
||||
|
||||
const RegisterFile& regs = *register_file_;
|
||||
|
||||
xenos::ModeControl edram_mode = regs.Get<reg::RB_MODECONTROL>().edram_mode;
|
||||
if (edram_mode == xenos::ModeControl::kCopy) {
|
||||
xenos::EdramMode edram_mode = regs.Get<reg::RB_MODECONTROL>().edram_mode;
|
||||
if (edram_mode == xenos::EdramMode::kCopy) {
|
||||
// Special copy handling.
|
||||
return IssueCopy();
|
||||
}
|
||||
|
||||
const ui::vulkan::VulkanProvider::DeviceInfo& device_info =
|
||||
GetVulkanProvider().device_info();
|
||||
const ui::vulkan::VulkanDevice::Properties& device_properties =
|
||||
GetVulkanDevice()->properties();
|
||||
|
||||
memexport_ranges_.clear();
|
||||
|
||||
@@ -2192,7 +2197,7 @@ bool VulkanCommandProcessor::IssueDraw(xenos::PrimitiveType prim_type,
|
||||
// to a compute shader and dispatch it after the draw if the draw doesn't use
|
||||
// tessellation.
|
||||
if (vertex_shader->memexport_eM_written() != 0 &&
|
||||
device_info.vertexPipelineStoresAndAtomics) {
|
||||
device_properties.vertexPipelineStoresAndAtomics) {
|
||||
draw_util::AddMemExportRanges(regs, *vertex_shader, memexport_ranges_);
|
||||
}
|
||||
|
||||
@@ -2202,9 +2207,9 @@ bool VulkanCommandProcessor::IssueDraw(xenos::PrimitiveType prim_type,
|
||||
draw_util::IsRasterizationPotentiallyDone(regs, primitive_polygonal);
|
||||
VulkanShader* pixel_shader = nullptr;
|
||||
if (is_rasterization_done) {
|
||||
// See xenos::ModeControl for explanation why the pixel shader is only used
|
||||
// See xenos::EdramMode for explanation why the pixel shader is only used
|
||||
// when it's kColorDepth here.
|
||||
if (edram_mode == xenos::ModeControl::kColorDepth) {
|
||||
if (edram_mode == xenos::EdramMode::kColorDepth) {
|
||||
pixel_shader = static_cast<VulkanShader*>(active_pixel_shader());
|
||||
if (pixel_shader) {
|
||||
pipeline_cache_->AnalyzeShaderUcode(*pixel_shader);
|
||||
@@ -2223,7 +2228,7 @@ bool VulkanCommandProcessor::IssueDraw(xenos::PrimitiveType prim_type,
|
||||
}
|
||||
}
|
||||
if (pixel_shader && pixel_shader->memexport_eM_written() != 0 &&
|
||||
device_info.fragmentStoresAndAtomics) {
|
||||
device_properties.fragmentStoresAndAtomics) {
|
||||
draw_util::AddMemExportRanges(regs, *pixel_shader, memexport_ranges_);
|
||||
}
|
||||
|
||||
@@ -2465,14 +2470,13 @@ bool VulkanCommandProcessor::IssueDraw(xenos::PrimitiveType prim_type,
|
||||
// directly to pixel address and to things like ps_param_gen.
|
||||
draw_util::GetViewportInfoArgs gviargs{};
|
||||
gviargs.Setup(1, 1, divisors::MagicDiv{1}, divisors::MagicDiv{1}, false,
|
||||
device_info.maxViewportDimensions[0],
|
||||
device_info.maxViewportDimensions[1], true,
|
||||
device_properties.maxViewportDimensions[0],
|
||||
device_properties.maxViewportDimensions[1], true,
|
||||
normalized_depth_control, false, host_render_targets_used,
|
||||
pixel_shader && pixel_shader->writes_depth());
|
||||
gviargs.SetupRegisterValues(regs);
|
||||
|
||||
draw_util::GetHostViewportInfo(&gviargs, viewport_info);
|
||||
|
||||
// Update dynamic graphics pipeline state.
|
||||
UpdateDynamicState(viewport_info, primitive_polygonal,
|
||||
normalized_depth_control);
|
||||
@@ -2483,7 +2487,7 @@ bool VulkanCommandProcessor::IssueDraw(xenos::PrimitiveType prim_type,
|
||||
// indirectly in the vertex shader if full 32-bit indices are not supported by
|
||||
// the host.
|
||||
bool shader_32bit_index_dma =
|
||||
!device_info.fullDrawIndexUint32 &&
|
||||
!device_properties.fullDrawIndexUint32 &&
|
||||
primitive_processing_result.index_buffer_type ==
|
||||
PrimitiveProcessor::ProcessedIndexBufferType::kGuestDMA &&
|
||||
vgt_draw_initiator.index_size == xenos::IndexFormat::kInt32 &&
|
||||
@@ -2634,9 +2638,9 @@ bool VulkanCommandProcessor::IssueDraw(xenos::PrimitiveType prim_type,
|
||||
}
|
||||
|
||||
bool VulkanCommandProcessor::IssueCopy() {
|
||||
#if XE_UI_VULKAN_FINE_GRAINED_DRAW_SCOPES
|
||||
#if XE_GPU_FINE_GRAINED_DRAW_SCOPES
|
||||
SCOPE_profile_cpu_f("gpu");
|
||||
#endif // XE_UI_VULKAN_FINE_GRAINED_DRAW_SCOPES
|
||||
#endif // XE_GPU_FINE_GRAINED_DRAW_SCOPES
|
||||
|
||||
if (!BeginSubmission(true)) {
|
||||
return false;
|
||||
@@ -2687,9 +2691,9 @@ void VulkanCommandProcessor::CheckSubmissionFenceAndDeviceLoss(
|
||||
await_submission = GetCurrentSubmission() - 1;
|
||||
}
|
||||
|
||||
const ui::vulkan::VulkanProvider& provider = GetVulkanProvider();
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||
VkDevice device = provider.device();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device = GetVulkanDevice();
|
||||
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
|
||||
const VkDevice device = vulkan_device->device();
|
||||
|
||||
size_t fences_total = submissions_in_flight_fences_.size();
|
||||
size_t fences_awaited = 0;
|
||||
@@ -2802,9 +2806,9 @@ void VulkanCommandProcessor::CheckSubmissionFenceAndDeviceLoss(
|
||||
}
|
||||
|
||||
bool VulkanCommandProcessor::BeginSubmission(bool is_guest_command) {
|
||||
#if XE_UI_VULKAN_FINE_GRAINED_DRAW_SCOPES
|
||||
#if XE_GPU_FINE_GRAINED_DRAW_SCOPES
|
||||
SCOPE_profile_cpu_f("gpu");
|
||||
#endif // XE_UI_VULKAN_FINE_GRAINED_DRAW_SCOPES
|
||||
#endif // XE_GPU_FINE_GRAINED_DRAW_SCOPES
|
||||
|
||||
if (device_lost_) {
|
||||
return false;
|
||||
@@ -2950,9 +2954,9 @@ bool VulkanCommandProcessor::BeginSubmission(bool is_guest_command) {
|
||||
}
|
||||
|
||||
bool VulkanCommandProcessor::EndSubmission(bool is_swap) {
|
||||
ui::vulkan::VulkanProvider& provider = GetVulkanProvider();
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||
VkDevice device = provider.device();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device = GetVulkanDevice();
|
||||
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
|
||||
const VkDevice device = vulkan_device->device();
|
||||
|
||||
// Make sure everything needed for submitting exist.
|
||||
if (submission_open_) {
|
||||
@@ -2992,7 +2996,7 @@ bool VulkanCommandProcessor::EndSubmission(bool is_swap) {
|
||||
command_pool_create_info.pNext = nullptr;
|
||||
command_pool_create_info.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT;
|
||||
command_pool_create_info.queueFamilyIndex =
|
||||
provider.queue_family_graphics_compute();
|
||||
vulkan_device->queue_family_graphics_compute();
|
||||
if (dfn.vkCreateCommandPool(device, &command_pool_create_info, nullptr,
|
||||
&command_buffer.pool) != VK_SUCCESS) {
|
||||
XELOGE("Failed to create a Vulkan command pool");
|
||||
@@ -3068,10 +3072,11 @@ bool VulkanCommandProcessor::EndSubmission(bool is_swap) {
|
||||
bind_sparse_info.pSignalSemaphores = &bind_sparse_semaphore;
|
||||
VkResult bind_sparse_result;
|
||||
{
|
||||
ui::vulkan::VulkanProvider::QueueAcquisition queue_acquisition(
|
||||
provider.AcquireQueue(provider.queue_family_sparse_binding(), 0));
|
||||
ui::vulkan::VulkanDevice::Queue::Acquisition queue_acquisition =
|
||||
vulkan_device->AcquireQueue(
|
||||
vulkan_device->queue_family_sparse_binding(), 0);
|
||||
bind_sparse_result = dfn.vkQueueBindSparse(
|
||||
queue_acquisition.queue, 1, &bind_sparse_info, VK_NULL_HANDLE);
|
||||
queue_acquisition.queue(), 1, &bind_sparse_info, VK_NULL_HANDLE);
|
||||
}
|
||||
if (bind_sparse_result != VK_SUCCESS) {
|
||||
XELOGE("Failed to submit Vulkan sparse binds");
|
||||
@@ -3138,10 +3143,11 @@ bool VulkanCommandProcessor::EndSubmission(bool is_swap) {
|
||||
}
|
||||
VkResult submit_result;
|
||||
{
|
||||
ui::vulkan::VulkanProvider::QueueAcquisition queue_acquisition(
|
||||
provider.AcquireQueue(provider.queue_family_graphics_compute(), 0));
|
||||
ui::vulkan::VulkanDevice::Queue::Acquisition queue_acquisition =
|
||||
vulkan_device->AcquireQueue(
|
||||
vulkan_device->queue_family_graphics_compute(), 0);
|
||||
submit_result =
|
||||
dfn.vkQueueSubmit(queue_acquisition.queue, 1, &submit_info, fence);
|
||||
dfn.vkQueueSubmit(queue_acquisition.queue(), 1, &submit_info, fence);
|
||||
}
|
||||
if (submit_result != VK_SUCCESS) {
|
||||
XELOGE("Failed to submit a Vulkan command buffer");
|
||||
@@ -3254,9 +3260,9 @@ void VulkanCommandProcessor::SplitPendingBarrier() {
|
||||
void VulkanCommandProcessor::DestroyScratchBuffer() {
|
||||
assert_false(scratch_buffer_used_);
|
||||
|
||||
const ui::vulkan::VulkanProvider& provider = GetVulkanProvider();
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||
VkDevice device = provider.device();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device = GetVulkanDevice();
|
||||
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
|
||||
const VkDevice device = vulkan_device->device();
|
||||
|
||||
scratch_buffer_last_usage_submission_ = 0;
|
||||
scratch_buffer_last_access_mask_ = 0;
|
||||
@@ -3271,9 +3277,9 @@ void VulkanCommandProcessor::DestroyScratchBuffer() {
|
||||
void VulkanCommandProcessor::UpdateDynamicState(
|
||||
const draw_util::ViewportInfo& viewport_info, bool primitive_polygonal,
|
||||
reg::RB_DEPTHCONTROL normalized_depth_control) {
|
||||
#if XE_UI_VULKAN_FINE_GRAINED_DRAW_SCOPES
|
||||
#if XE_GPU_FINE_GRAINED_DRAW_SCOPES
|
||||
SCOPE_profile_cpu_f("gpu");
|
||||
#endif // XE_UI_VULKAN_FINE_GRAINED_DRAW_SCOPES
|
||||
#endif // XE_GPU_FINE_GRAINED_DRAW_SCOPES
|
||||
|
||||
const RegisterFile& regs = *register_file_;
|
||||
|
||||
@@ -3377,7 +3383,7 @@ void VulkanCommandProcessor::UpdateDynamicState(
|
||||
if (normalized_depth_control.stencil_enable) {
|
||||
Register stencil_ref_mask_front_reg, stencil_ref_mask_back_reg;
|
||||
if (primitive_polygonal && normalized_depth_control.backface_enable) {
|
||||
if (GetVulkanProvider().device_info().separateStencilMaskRef) {
|
||||
if (GetVulkanDevice()->properties().separateStencilMaskRef) {
|
||||
stencil_ref_mask_front_reg = XE_GPU_REG_RB_STENCILREFMASK;
|
||||
stencil_ref_mask_back_reg = XE_GPU_REG_RB_STENCILREFMASK_BF;
|
||||
} else {
|
||||
@@ -3494,9 +3500,9 @@ void VulkanCommandProcessor::UpdateSystemConstantValues(
|
||||
bool shader_32bit_index_dma, const draw_util::ViewportInfo& viewport_info,
|
||||
uint32_t used_texture_mask, reg::RB_DEPTHCONTROL normalized_depth_control,
|
||||
uint32_t normalized_color_mask) {
|
||||
#if XE_UI_VULKAN_FINE_GRAINED_DRAW_SCOPES
|
||||
#if XE_GPU_FINE_GRAINED_DRAW_SCOPES
|
||||
SCOPE_profile_cpu_f("gpu");
|
||||
#endif // XE_UI_VULKAN_FINE_GRAINED_DRAW_SCOPES
|
||||
#endif // XE_GPU_FINE_GRAINED_DRAW_SCOPES
|
||||
|
||||
const RegisterFile& regs = *register_file_;
|
||||
auto pa_cl_vte_cntl = regs.Get<reg::PA_CL_VTE_CNTL>();
|
||||
@@ -3738,7 +3744,7 @@ void VulkanCommandProcessor::UpdateSystemConstantValues(
|
||||
}
|
||||
|
||||
// Texture host swizzle in the shader.
|
||||
if (!GetVulkanProvider().device_info().imageViewFormatSwizzle) {
|
||||
if (!GetVulkanDevice()->properties().imageViewFormatSwizzle) {
|
||||
uint32_t textures_remaining = used_texture_mask;
|
||||
uint32_t texture_index;
|
||||
while (xe::bit_scan_forward(textures_remaining, &texture_index)) {
|
||||
@@ -3954,15 +3960,15 @@ void VulkanCommandProcessor::UpdateSystemConstantValues(
|
||||
|
||||
bool VulkanCommandProcessor::UpdateBindings(const VulkanShader* vertex_shader,
|
||||
const VulkanShader* pixel_shader) {
|
||||
#if XE_UI_VULKAN_FINE_GRAINED_DRAW_SCOPES
|
||||
#if XE_GPU_FINE_GRAINED_DRAW_SCOPES
|
||||
SCOPE_profile_cpu_f("gpu");
|
||||
#endif // XE_UI_VULKAN_FINE_GRAINED_DRAW_SCOPES
|
||||
#endif // XE_GPU_FINE_GRAINED_DRAW_SCOPES
|
||||
|
||||
const RegisterFile& regs = *register_file_;
|
||||
|
||||
const ui::vulkan::VulkanProvider& provider = GetVulkanProvider();
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||
VkDevice device = provider.device();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device = GetVulkanDevice();
|
||||
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
|
||||
const VkDevice device = vulkan_device->device();
|
||||
|
||||
// Invalidate constant buffers and descriptors for changed data.
|
||||
|
||||
@@ -4021,7 +4027,7 @@ bool VulkanCommandProcessor::UpdateBindings(const VulkanShader* vertex_shader,
|
||||
current_graphics_descriptor_set_values_up_to_date_ &=
|
||||
~(UINT32_C(1) << SpirvShaderTranslator::kDescriptorSetConstants);
|
||||
size_t uniform_buffer_alignment =
|
||||
size_t(provider.device_info().minUniformBufferOffsetAlignment);
|
||||
size_t(vulkan_device->properties().minUniformBufferOffsetAlignment);
|
||||
// System constants.
|
||||
if (!(current_constant_buffers_up_to_date_ &
|
||||
(UINT32_C(1) << SpirvShaderTranslator::kConstantBufferSystem))) {
|
||||
@@ -4395,10 +4401,9 @@ uint8_t* VulkanCommandProcessor::WriteTransientUniformBufferBinding(
|
||||
if (descriptor_set == VK_NULL_HANDLE) {
|
||||
return nullptr;
|
||||
}
|
||||
const ui::vulkan::VulkanProvider& provider = GetVulkanProvider();
|
||||
uint8_t* mapping = uniform_buffer_pool_->Request(
|
||||
frame_current_, size,
|
||||
size_t(provider.device_info().minUniformBufferOffsetAlignment),
|
||||
size_t(GetVulkanDevice()->properties().minUniformBufferOffsetAlignment),
|
||||
descriptor_buffer_info_out.buffer, descriptor_buffer_info_out.offset);
|
||||
if (!mapping) {
|
||||
return nullptr;
|
||||
@@ -4428,9 +4433,9 @@ uint8_t* VulkanCommandProcessor::WriteTransientUniformBufferBinding(
|
||||
if (!mapping) {
|
||||
return nullptr;
|
||||
}
|
||||
const ui::vulkan::VulkanProvider& provider = GetVulkanProvider();
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||
VkDevice device = provider.device();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device = GetVulkanDevice();
|
||||
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
|
||||
const VkDevice device = vulkan_device->device();
|
||||
dfn.vkUpdateDescriptorSets(device, 1, &write_descriptor_set, 0, nullptr);
|
||||
descriptor_set_out = write_descriptor_set.dstSet;
|
||||
return mapping;
|
||||
|
||||
@@ -147,9 +147,10 @@ class VulkanCommandProcessor final : public CommandProcessor {
|
||||
|
||||
void RestoreEdramSnapshot(const void* snapshot) override;
|
||||
|
||||
ui::vulkan::VulkanProvider& GetVulkanProvider() const {
|
||||
return *static_cast<ui::vulkan::VulkanProvider*>(
|
||||
graphics_system_->provider());
|
||||
ui::vulkan::VulkanDevice* GetVulkanDevice() const {
|
||||
return static_cast<const ui::vulkan::VulkanProvider*>(
|
||||
graphics_system_->provider())
|
||||
->vulkan_device();
|
||||
}
|
||||
|
||||
// Returns the deferred drawing command list for the currently open
|
||||
|
||||
@@ -33,10 +33,10 @@ std::string VulkanGraphicsSystem::name() const {
|
||||
X_STATUS VulkanGraphicsSystem::Setup(cpu::Processor* processor,
|
||||
kernel::KernelState* kernel_state,
|
||||
ui::WindowedAppContext* app_context,
|
||||
bool is_surface_required) {
|
||||
provider_ = xe::ui::vulkan::VulkanProvider::Create(is_surface_required);
|
||||
bool with_presentation) {
|
||||
provider_ = xe::ui::vulkan::VulkanProvider::Create(true, with_presentation);
|
||||
return GraphicsSystem::Setup(processor, kernel_state, app_context,
|
||||
is_surface_required);
|
||||
with_presentation);
|
||||
}
|
||||
|
||||
std::unique_ptr<CommandProcessor>
|
||||
|
||||
@@ -30,7 +30,7 @@ class VulkanGraphicsSystem : public GraphicsSystem {
|
||||
|
||||
X_STATUS Setup(cpu::Processor* processor, kernel::KernelState* kernel_state,
|
||||
ui::WindowedAppContext* app_context,
|
||||
bool is_surface_required) override;
|
||||
bool with_presentation) override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<CommandProcessor> CreateCommandProcessor() override;
|
||||
|
||||
@@ -46,15 +46,15 @@ VulkanPipelineCache::VulkanPipelineCache(
|
||||
VulkanPipelineCache::~VulkanPipelineCache() { Shutdown(); }
|
||||
|
||||
bool VulkanPipelineCache::Initialize() {
|
||||
const ui::vulkan::VulkanProvider& provider =
|
||||
command_processor_.GetVulkanProvider();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device =
|
||||
command_processor_.GetVulkanDevice();
|
||||
|
||||
bool edram_fragment_shader_interlock =
|
||||
render_target_cache_.GetPath() ==
|
||||
RenderTargetCache::Path::kPixelShaderInterlock;
|
||||
|
||||
shader_translator_ = std::make_unique<SpirvShaderTranslator>(
|
||||
SpirvShaderTranslator::Features(provider.device_info()),
|
||||
SpirvShaderTranslator::Features(vulkan_device),
|
||||
render_target_cache_.msaa_2x_attachments_supported(),
|
||||
render_target_cache_.msaa_2x_no_attachments_supported(),
|
||||
edram_fragment_shader_interlock);
|
||||
@@ -63,7 +63,7 @@ bool VulkanPipelineCache::Initialize() {
|
||||
std::vector<uint8_t> depth_only_fragment_shader_code =
|
||||
shader_translator_->CreateDepthOnlyFragmentShader();
|
||||
depth_only_fragment_shader_ = ui::vulkan::util::CreateShaderModule(
|
||||
provider,
|
||||
vulkan_device,
|
||||
reinterpret_cast<const uint32_t*>(
|
||||
depth_only_fragment_shader_code.data()),
|
||||
depth_only_fragment_shader_code.size());
|
||||
@@ -80,10 +80,10 @@ bool VulkanPipelineCache::Initialize() {
|
||||
}
|
||||
|
||||
void VulkanPipelineCache::Shutdown() {
|
||||
const ui::vulkan::VulkanProvider& provider =
|
||||
command_processor_.GetVulkanProvider();
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||
VkDevice device = provider.device();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device =
|
||||
command_processor_.GetVulkanDevice();
|
||||
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
|
||||
const VkDevice device = vulkan_device->device();
|
||||
|
||||
// Destroy all pipelines.
|
||||
last_pipeline_ = nullptr;
|
||||
@@ -131,7 +131,7 @@ VulkanShader* VulkanPipelineCache::LoadShader(xenos::ShaderType shader_type,
|
||||
// We need to track it even if it fails translation so we know not to try
|
||||
// again.
|
||||
VulkanShader* shader =
|
||||
new VulkanShader(command_processor_.GetVulkanProvider(), shader_type,
|
||||
new VulkanShader(command_processor_.GetVulkanDevice(), shader_type,
|
||||
data_hash, host_address, dword_count);
|
||||
shaders_.emplace(data_hash, shader);
|
||||
return shader;
|
||||
@@ -263,9 +263,9 @@ bool VulkanPipelineCache::ConfigurePipeline(
|
||||
VulkanRenderTargetCache::RenderPassKey render_pass_key,
|
||||
VkPipeline& pipeline_out,
|
||||
const PipelineLayoutProvider*& pipeline_layout_out) {
|
||||
#if XE_UI_VULKAN_FINE_GRAINED_DRAW_SCOPES
|
||||
#if XE_GPU_FINE_GRAINED_DRAW_SCOPES
|
||||
SCOPE_profile_cpu_f("gpu");
|
||||
#endif // XE_UI_VULKAN_FINE_GRAINED_DRAW_SCOPES
|
||||
#endif // XE_GPU_FINE_GRAINED_DRAW_SCOPES
|
||||
|
||||
// Ensure shaders are translated - needed now for GetCurrentStateDescription.
|
||||
if (!EnsureShadersTranslated(vertex_shader, pixel_shader)) {
|
||||
@@ -466,8 +466,8 @@ void VulkanPipelineCache::WritePipelineRenderTargetDescription(
|
||||
render_target_out.dst_alpha_blend_factor =
|
||||
kBlendFactorMap[uint32_t(blend_control.alpha_destblend)];
|
||||
render_target_out.alpha_blend_op = blend_control.alpha_comb_fcn;
|
||||
if (!command_processor_.GetVulkanProvider()
|
||||
.device_info()
|
||||
if (!command_processor_.GetVulkanDevice()
|
||||
->properties()
|
||||
.constantAlphaColorBlendFactors) {
|
||||
if (blend_control.color_srcblend == xenos::BlendFactor::kConstantAlpha) {
|
||||
render_target_out.src_color_blend_factor =
|
||||
@@ -507,8 +507,8 @@ bool VulkanPipelineCache::GetCurrentStateDescription(
|
||||
PipelineDescription& description_out) const {
|
||||
description_out.Reset();
|
||||
|
||||
const ui::vulkan::VulkanProvider::DeviceInfo& device_info =
|
||||
command_processor_.GetVulkanProvider().device_info();
|
||||
const ui::vulkan::VulkanDevice::Properties& device_properties =
|
||||
command_processor_.GetVulkanDevice()->properties();
|
||||
|
||||
const RegisterFile& regs = register_file_;
|
||||
auto pa_su_sc_mode_cntl = regs.Get<reg::PA_SU_SC_MODE_CNTL>();
|
||||
@@ -543,7 +543,7 @@ bool VulkanPipelineCache::GetCurrentStateDescription(
|
||||
break;
|
||||
case xenos::PrimitiveType::kTriangleFan:
|
||||
// The check should be performed at primitive processing time.
|
||||
assert_true(device_info.triangleFans);
|
||||
assert_true(device_properties.triangleFans);
|
||||
primitive_topology = PipelinePrimitiveTopology::kTriangleFan;
|
||||
break;
|
||||
case xenos::PrimitiveType::kTriangleStrip:
|
||||
@@ -567,7 +567,8 @@ bool VulkanPipelineCache::GetCurrentStateDescription(
|
||||
primitive_processing_result.host_primitive_reset_enabled;
|
||||
|
||||
description_out.depth_clamp_enable =
|
||||
device_info.depthClamp && regs.Get<reg::PA_CL_CLIP_CNTL>().clip_disable;
|
||||
device_properties.depthClamp &&
|
||||
regs.Get<reg::PA_CL_CLIP_CNTL>().clip_disable;
|
||||
|
||||
// TODO(Triang3l): Tessellation.
|
||||
bool primitive_polygonal = draw_util::IsPrimitivePolygonal(regs);
|
||||
@@ -582,7 +583,7 @@ bool VulkanPipelineCache::GetCurrentStateDescription(
|
||||
bool cull_back = pa_su_sc_mode_cntl.cull_back;
|
||||
description_out.cull_front = cull_front;
|
||||
description_out.cull_back = cull_back;
|
||||
if (device_info.fillModeNonSolid) {
|
||||
if (device_properties.fillModeNonSolid) {
|
||||
xenos::PolygonType polygon_type = xenos::PolygonType::kTriangles;
|
||||
if (!cull_front) {
|
||||
polygon_type =
|
||||
@@ -599,7 +600,7 @@ bool VulkanPipelineCache::GetCurrentStateDescription(
|
||||
case xenos::PolygonType::kPoints:
|
||||
// When points are not supported, use lines instead, preserving
|
||||
// debug-like purpose.
|
||||
description_out.polygon_mode = device_info.pointPolygons
|
||||
description_out.polygon_mode = device_properties.pointPolygons
|
||||
? PipelinePolygonMode::kPoint
|
||||
: PipelinePolygonMode::kLine;
|
||||
break;
|
||||
@@ -666,83 +667,17 @@ bool VulkanPipelineCache::GetCurrentStateDescription(
|
||||
// Color blending and write masks (filled only for the attachments present
|
||||
// in the render pass object).
|
||||
uint32_t render_pass_color_rts = render_pass_key.depth_and_color_used >> 1;
|
||||
if (device_info.independentBlend) {
|
||||
uint32_t render_pass_color_rts_remaining = render_pass_color_rts;
|
||||
uint32_t color_rt_index;
|
||||
while (xe::bit_scan_forward(render_pass_color_rts_remaining,
|
||||
&color_rt_index)) {
|
||||
render_pass_color_rts_remaining &= ~(uint32_t(1) << color_rt_index);
|
||||
WritePipelineRenderTargetDescription(
|
||||
regs.Get<reg::RB_BLENDCONTROL>(
|
||||
reg::RB_BLENDCONTROL::rt_register_indices[color_rt_index]),
|
||||
(normalized_color_mask >> (color_rt_index * 4)) & 0b1111,
|
||||
description_out.render_targets[color_rt_index]);
|
||||
}
|
||||
} else {
|
||||
// Take the blend control for the first render target that the guest wants
|
||||
// to write to (consider it the most important) and use it for all render
|
||||
// targets, if any.
|
||||
// TODO(Triang3l): Implement an option for independent blending via
|
||||
// replaying the render pass for each set of render targets with unique
|
||||
// blending parameters, with depth / stencil saved before the first and
|
||||
// restored before each of the rest maybe? Though independent blending
|
||||
// support is pretty wide, with a quite prominent exception of Adreno 4xx
|
||||
// apparently.
|
||||
uint32_t render_pass_color_rts_remaining = render_pass_color_rts;
|
||||
uint32_t render_pass_first_color_rt_index;
|
||||
if (xe::bit_scan_forward(render_pass_color_rts_remaining,
|
||||
&render_pass_first_color_rt_index)) {
|
||||
render_pass_color_rts_remaining &=
|
||||
~(uint32_t(1) << render_pass_first_color_rt_index);
|
||||
PipelineRenderTarget& render_pass_first_color_rt =
|
||||
description_out.render_targets[render_pass_first_color_rt_index];
|
||||
uint32_t common_blend_rt_index;
|
||||
if (xe::bit_scan_forward(normalized_color_mask,
|
||||
&common_blend_rt_index)) {
|
||||
common_blend_rt_index >>= 2;
|
||||
// If a common write mask will be used for multiple render targets,
|
||||
// use the original RB_COLOR_MASK instead of the normalized color mask
|
||||
// as the normalized color mask has non-existent components forced to
|
||||
// written (don't need reading to be preserved), while the number of
|
||||
// components may vary between render targets. The attachments in the
|
||||
// pass that must not be written to at all will be excluded via a
|
||||
// shader modification.
|
||||
WritePipelineRenderTargetDescription(
|
||||
regs.Get<reg::RB_BLENDCONTROL>(
|
||||
reg::RB_BLENDCONTROL::rt_register_indices
|
||||
[common_blend_rt_index]),
|
||||
(((normalized_color_mask &
|
||||
~(uint32_t(0b1111) << (4 * common_blend_rt_index)))
|
||||
? regs[XE_GPU_REG_RB_COLOR_MASK]
|
||||
: normalized_color_mask) >>
|
||||
(4 * common_blend_rt_index)) &
|
||||
0b1111,
|
||||
render_pass_first_color_rt);
|
||||
} else {
|
||||
// No render targets are written to, though the render pass still may
|
||||
// contain color attachments - set them to not written and not
|
||||
// blending.
|
||||
render_pass_first_color_rt.src_color_blend_factor =
|
||||
PipelineBlendFactor::kOne;
|
||||
render_pass_first_color_rt.dst_color_blend_factor =
|
||||
PipelineBlendFactor::kZero;
|
||||
render_pass_first_color_rt.color_blend_op = xenos::BlendOp::kAdd;
|
||||
render_pass_first_color_rt.src_alpha_blend_factor =
|
||||
PipelineBlendFactor::kOne;
|
||||
render_pass_first_color_rt.dst_alpha_blend_factor =
|
||||
PipelineBlendFactor::kZero;
|
||||
render_pass_first_color_rt.alpha_blend_op = xenos::BlendOp::kAdd;
|
||||
}
|
||||
// Reuse the same blending settings for all render targets in the pass,
|
||||
// for description consistency.
|
||||
uint32_t color_rt_index;
|
||||
while (xe::bit_scan_forward(render_pass_color_rts_remaining,
|
||||
&color_rt_index)) {
|
||||
render_pass_color_rts_remaining &= ~(uint32_t(1) << color_rt_index);
|
||||
description_out.render_targets[color_rt_index] =
|
||||
render_pass_first_color_rt;
|
||||
}
|
||||
}
|
||||
assert_true(device_properties.independentBlend);
|
||||
uint32_t render_pass_color_rts_remaining = render_pass_color_rts;
|
||||
uint32_t color_rt_index;
|
||||
while (xe::bit_scan_forward(render_pass_color_rts_remaining,
|
||||
&color_rt_index)) {
|
||||
render_pass_color_rts_remaining &= ~(uint32_t(1) << color_rt_index);
|
||||
WritePipelineRenderTargetDescription(
|
||||
regs.Get<reg::RB_BLENDCONTROL>(
|
||||
reg::RB_BLENDCONTROL::rt_register_indices[color_rt_index]),
|
||||
(normalized_color_mask >> (color_rt_index * 4)) & 0b1111,
|
||||
description_out.render_targets[color_rt_index]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -762,65 +697,37 @@ bool VulkanPipelineCache::ArePipelineRequirementsMet(
|
||||
return false;
|
||||
}
|
||||
|
||||
const ui::vulkan::VulkanProvider::DeviceInfo& device_info =
|
||||
command_processor_.GetVulkanProvider().device_info();
|
||||
const ui::vulkan::VulkanDevice::Properties& device_properties =
|
||||
command_processor_.GetVulkanDevice()->properties();
|
||||
|
||||
if (!device_info.geometryShader &&
|
||||
if (!device_properties.geometryShader &&
|
||||
description.geometry_shader != PipelineGeometryShader::kNone) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!device_info.triangleFans &&
|
||||
if (!device_properties.triangleFans &&
|
||||
description.primitive_topology ==
|
||||
PipelinePrimitiveTopology::kTriangleFan) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!device_info.depthClamp && description.depth_clamp_enable) {
|
||||
if (!device_properties.depthClamp && description.depth_clamp_enable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!device_info.pointPolygons &&
|
||||
if (!device_properties.pointPolygons &&
|
||||
description.polygon_mode == PipelinePolygonMode::kPoint) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!device_info.fillModeNonSolid &&
|
||||
if (!device_properties.fillModeNonSolid &&
|
||||
description.polygon_mode != PipelinePolygonMode::kFill) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!device_info.independentBlend) {
|
||||
uint32_t color_rts_remaining =
|
||||
description.render_pass_key.depth_and_color_used >> 1;
|
||||
uint32_t first_color_rt_index;
|
||||
if (xe::bit_scan_forward(color_rts_remaining, &first_color_rt_index)) {
|
||||
color_rts_remaining &= ~(uint32_t(1) << first_color_rt_index);
|
||||
const PipelineRenderTarget& first_color_rt =
|
||||
description.render_targets[first_color_rt_index];
|
||||
uint32_t color_rt_index;
|
||||
while (xe::bit_scan_forward(color_rts_remaining, &color_rt_index)) {
|
||||
color_rts_remaining &= ~(uint32_t(1) << color_rt_index);
|
||||
const PipelineRenderTarget& color_rt =
|
||||
description.render_targets[color_rt_index];
|
||||
if (color_rt.src_color_blend_factor !=
|
||||
first_color_rt.src_color_blend_factor ||
|
||||
color_rt.dst_color_blend_factor !=
|
||||
first_color_rt.dst_color_blend_factor ||
|
||||
color_rt.color_blend_op != first_color_rt.color_blend_op ||
|
||||
color_rt.src_alpha_blend_factor !=
|
||||
first_color_rt.src_alpha_blend_factor ||
|
||||
color_rt.dst_alpha_blend_factor !=
|
||||
first_color_rt.dst_alpha_blend_factor ||
|
||||
color_rt.alpha_blend_op != first_color_rt.alpha_blend_op ||
|
||||
color_rt.color_write_mask != first_color_rt.color_write_mask) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
assert_true(device_properties.independentBlend);
|
||||
|
||||
if (!device_info.constantAlphaColorBlendFactors) {
|
||||
if (!device_properties.constantAlphaColorBlendFactors) {
|
||||
uint32_t color_rts_remaining =
|
||||
description.render_pass_key.depth_and_color_used >> 1;
|
||||
uint32_t color_rt_index;
|
||||
@@ -1844,10 +1751,9 @@ VkShaderModule VulkanPipelineCache::GetGeometryShader(GeometryShaderKey key) {
|
||||
|
||||
// Create the shader module, and store the handle even if creation fails not
|
||||
// to try to create it again later.
|
||||
const ui::vulkan::VulkanProvider& provider =
|
||||
command_processor_.GetVulkanProvider();
|
||||
VkShaderModule shader_module = ui::vulkan::util::CreateShaderModule(
|
||||
provider, reinterpret_cast<const uint32_t*>(shader_code.data()),
|
||||
command_processor_.GetVulkanDevice(),
|
||||
reinterpret_cast<const uint32_t*>(shader_code.data()),
|
||||
sizeof(uint32_t) * shader_code.size());
|
||||
if (shader_module == VK_NULL_HANDLE) {
|
||||
XELOGE(
|
||||
@@ -1887,10 +1793,8 @@ bool VulkanPipelineCache::EnsurePipelineCreated(
|
||||
return false;
|
||||
}
|
||||
|
||||
const ui::vulkan::VulkanProvider& provider =
|
||||
command_processor_.GetVulkanProvider();
|
||||
const ui::vulkan::VulkanProvider::DeviceInfo& device_info =
|
||||
provider.device_info();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device =
|
||||
command_processor_.GetVulkanDevice();
|
||||
|
||||
bool edram_fragment_shader_interlock =
|
||||
render_target_cache_.GetPath() ==
|
||||
@@ -2199,28 +2103,10 @@ bool VulkanPipelineCache::EnsurePipelineCreated(
|
||||
}
|
||||
color_blend_attachment.colorWriteMask =
|
||||
VkColorComponentFlags(color_rt.color_write_mask);
|
||||
if (!device_info.independentBlend) {
|
||||
// For non-independent blend, the pAttachments element for the first
|
||||
// actually used color will be replicated into all.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
color_blend_state.attachmentCount = 32 - xe::lzcnt(color_rts_used);
|
||||
color_blend_state.pAttachments = color_blend_attachments;
|
||||
if (color_rts_used && !device_info.independentBlend) {
|
||||
// "If the independent blending feature is not enabled, all elements of
|
||||
// pAttachments must be identical."
|
||||
uint32_t first_color_rt_index;
|
||||
xe::bit_scan_forward(color_rts_used, &first_color_rt_index);
|
||||
for (uint32_t i = 0; i < color_blend_state.attachmentCount; ++i) {
|
||||
if (i == first_color_rt_index) {
|
||||
continue;
|
||||
}
|
||||
color_blend_attachments[i] =
|
||||
color_blend_attachments[first_color_rt_index];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::array<VkDynamicState, 7> dynamic_states;
|
||||
@@ -2271,8 +2157,8 @@ bool VulkanPipelineCache::EnsurePipelineCreated(
|
||||
pipeline_create_info.basePipelineHandle = VK_NULL_HANDLE;
|
||||
pipeline_create_info.basePipelineIndex = -1;
|
||||
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||
VkDevice device = provider.device();
|
||||
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
|
||||
const VkDevice device = vulkan_device->device();
|
||||
VkPipeline pipeline;
|
||||
if (dfn.vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1,
|
||||
&pipeline_create_info, nullptr,
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#include "xenia/gpu/vulkan/vulkan_render_target_cache.h"
|
||||
#include "xenia/gpu/vulkan/vulkan_shader.h"
|
||||
#include "xenia/gpu/xenos.h"
|
||||
#include "xenia/ui/vulkan/vulkan_provider.h"
|
||||
#include "xenia/ui/vulkan/vulkan_api.h"
|
||||
|
||||
namespace xe {
|
||||
namespace gpu {
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/gpu/vulkan/deferred_command_buffer.h"
|
||||
#include "xenia/gpu/vulkan/vulkan_command_processor.h"
|
||||
#include "xenia/ui/vulkan/vulkan_provider.h"
|
||||
#include "xenia/ui/vulkan/vulkan_util.h"
|
||||
|
||||
namespace xe {
|
||||
@@ -25,29 +24,30 @@ namespace vulkan {
|
||||
VulkanPrimitiveProcessor::~VulkanPrimitiveProcessor() { Shutdown(true); }
|
||||
|
||||
bool VulkanPrimitiveProcessor::Initialize() {
|
||||
const ui::vulkan::VulkanProvider::DeviceInfo& device_info =
|
||||
command_processor_.GetVulkanProvider().device_info();
|
||||
if (!InitializeCommon(device_info.fullDrawIndexUint32,
|
||||
device_info.triangleFans, false,
|
||||
device_info.geometryShader, device_info.geometryShader,
|
||||
device_info.geometryShader)) {
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device =
|
||||
command_processor_.GetVulkanDevice();
|
||||
const ui::vulkan::VulkanDevice::Properties& device_properties =
|
||||
vulkan_device->properties();
|
||||
if (!InitializeCommon(
|
||||
device_properties.fullDrawIndexUint32, device_properties.triangleFans,
|
||||
false, device_properties.geometryShader,
|
||||
device_properties.geometryShader, device_properties.geometryShader)) {
|
||||
Shutdown();
|
||||
return false;
|
||||
}
|
||||
frame_index_buffer_pool_ =
|
||||
std::make_unique<ui::vulkan::VulkanUploadBufferPool>(
|
||||
command_processor_.GetVulkanProvider(),
|
||||
VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
|
||||
vulkan_device, VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
|
||||
std::max(size_t(kMinRequiredConvertedIndexBufferSize),
|
||||
ui::GraphicsUploadBufferPool::kDefaultPageSize));
|
||||
return true;
|
||||
}
|
||||
|
||||
void VulkanPrimitiveProcessor::Shutdown(bool from_destructor) {
|
||||
const ui::vulkan::VulkanProvider& provider =
|
||||
command_processor_.GetVulkanProvider();
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||
VkDevice device = provider.device();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device =
|
||||
command_processor_.GetVulkanDevice();
|
||||
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
|
||||
const VkDevice device = vulkan_device->device();
|
||||
|
||||
frame_index_buffers_.clear();
|
||||
frame_index_buffer_pool_.reset();
|
||||
@@ -69,10 +69,10 @@ void VulkanPrimitiveProcessor::CompletedSubmissionUpdated() {
|
||||
if (builtin_index_buffer_upload_ != VK_NULL_HANDLE &&
|
||||
command_processor_.GetCompletedSubmission() >=
|
||||
builtin_index_buffer_upload_submission_) {
|
||||
const ui::vulkan::VulkanProvider& provider =
|
||||
command_processor_.GetVulkanProvider();
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||
VkDevice device = provider.device();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device =
|
||||
command_processor_.GetVulkanDevice();
|
||||
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
|
||||
const VkDevice device = vulkan_device->device();
|
||||
ui::vulkan::util::DestroyAndNullHandle(dfn.vkDestroyBuffer, device,
|
||||
builtin_index_buffer_upload_);
|
||||
ui::vulkan::util::DestroyAndNullHandle(dfn.vkFreeMemory, device,
|
||||
@@ -129,14 +129,14 @@ bool VulkanPrimitiveProcessor::InitializeBuiltinIndexBuffer(
|
||||
assert_true(builtin_index_buffer_upload_ == VK_NULL_HANDLE);
|
||||
assert_true(builtin_index_buffer_upload_memory_ == VK_NULL_HANDLE);
|
||||
|
||||
const ui::vulkan::VulkanProvider& provider =
|
||||
command_processor_.GetVulkanProvider();
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||
VkDevice device = provider.device();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device =
|
||||
command_processor_.GetVulkanDevice();
|
||||
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
|
||||
const VkDevice device = vulkan_device->device();
|
||||
|
||||
builtin_index_buffer_size_ = VkDeviceSize(size_bytes);
|
||||
if (!ui::vulkan::util::CreateDedicatedAllocationBuffer(
|
||||
provider, builtin_index_buffer_size_,
|
||||
vulkan_device, builtin_index_buffer_size_,
|
||||
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
|
||||
ui::vulkan::util::MemoryPurpose::kDeviceLocal, builtin_index_buffer_,
|
||||
builtin_index_buffer_memory_)) {
|
||||
@@ -148,7 +148,7 @@ bool VulkanPrimitiveProcessor::InitializeBuiltinIndexBuffer(
|
||||
}
|
||||
uint32_t upload_memory_type;
|
||||
if (!ui::vulkan::util::CreateDedicatedAllocationBuffer(
|
||||
provider, builtin_index_buffer_size_,
|
||||
vulkan_device, builtin_index_buffer_size_,
|
||||
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
||||
ui::vulkan::util::MemoryPurpose::kUpload,
|
||||
builtin_index_buffer_upload_, builtin_index_buffer_upload_memory_,
|
||||
@@ -183,7 +183,7 @@ bool VulkanPrimitiveProcessor::InitializeBuiltinIndexBuffer(
|
||||
}
|
||||
fill_callback(mapping);
|
||||
ui::vulkan::util::FlushMappedMemoryRange(
|
||||
provider, builtin_index_buffer_memory_, upload_memory_type);
|
||||
vulkan_device, builtin_index_buffer_memory_, upload_memory_type);
|
||||
dfn.vkUnmapMemory(device, builtin_index_buffer_upload_memory_);
|
||||
|
||||
// Schedule uploading in the first submission.
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
|
||||
#include "xenia/base/assert.h"
|
||||
#include "xenia/gpu/primitive_processor.h"
|
||||
#include "xenia/ui/vulkan/vulkan_provider.h"
|
||||
#include "xenia/ui/vulkan/vulkan_upload_buffer_pool.h"
|
||||
|
||||
namespace xe {
|
||||
|
||||
@@ -201,14 +201,15 @@ VulkanRenderTargetCache::VulkanRenderTargetCache(
|
||||
VulkanRenderTargetCache::~VulkanRenderTargetCache() { Shutdown(true); }
|
||||
|
||||
bool VulkanRenderTargetCache::Initialize(uint32_t shared_memory_binding_count) {
|
||||
const ui::vulkan::VulkanProvider& provider =
|
||||
command_processor_.GetVulkanProvider();
|
||||
const ui::vulkan::VulkanProvider::InstanceFunctions& ifn = provider.ifn();
|
||||
VkPhysicalDevice physical_device = provider.physical_device();
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||
VkDevice device = provider.device();
|
||||
const ui::vulkan::VulkanProvider::DeviceInfo& device_info =
|
||||
provider.device_info();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device =
|
||||
command_processor_.GetVulkanDevice();
|
||||
const ui::vulkan::VulkanInstance::Functions& ifn =
|
||||
vulkan_device->vulkan_instance()->functions();
|
||||
const VkPhysicalDevice physical_device = vulkan_device->physical_device();
|
||||
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
|
||||
const VkDevice device = vulkan_device->device();
|
||||
const ui::vulkan::VulkanDevice::Properties& device_properties =
|
||||
vulkan_device->properties();
|
||||
|
||||
if (cvars::render_target_path_vulkan == "fsi") {
|
||||
path_ = Path::kPixelShaderInterlock;
|
||||
@@ -237,13 +238,13 @@ bool VulkanRenderTargetCache::Initialize(uint32_t shared_memory_binding_count) {
|
||||
// between, for instance, the ability to vfetch and memexport in fragment
|
||||
// shaders, and the usage of fragment shader interlock, prefer the former
|
||||
// for simplicity.
|
||||
if (!(device_info.fragmentShaderSampleInterlock ||
|
||||
device_info.fragmentShaderPixelInterlock) ||
|
||||
!device_info.fragmentStoresAndAtomics ||
|
||||
!device_info.sampleRateShading ||
|
||||
!device_info.standardSampleLocations ||
|
||||
if (!(device_properties.fragmentShaderSampleInterlock ||
|
||||
device_properties.fragmentShaderPixelInterlock) ||
|
||||
!device_properties.fragmentStoresAndAtomics ||
|
||||
!device_properties.sampleRateShading ||
|
||||
!device_properties.standardSampleLocations ||
|
||||
shared_memory_binding_count >=
|
||||
device_info.maxPerStageDescriptorStorageBuffers) {
|
||||
device_properties.maxPerStageDescriptorStorageBuffers) {
|
||||
path_ = Path::kHostRenderTargets;
|
||||
}
|
||||
}
|
||||
@@ -265,17 +266,18 @@ bool VulkanRenderTargetCache::Initialize(uint32_t shared_memory_binding_count) {
|
||||
if (cvars::native_2x_msaa) {
|
||||
// Multisampled integer sampled images are optional in Vulkan and in Xenia.
|
||||
msaa_2x_attachments_supported_ =
|
||||
(device_info.framebufferColorSampleCounts &
|
||||
device_info.framebufferDepthSampleCounts &
|
||||
device_info.framebufferStencilSampleCounts &
|
||||
device_info.sampledImageColorSampleCounts &
|
||||
device_info.sampledImageDepthSampleCounts &
|
||||
device_info.sampledImageStencilSampleCounts & VK_SAMPLE_COUNT_2_BIT) &&
|
||||
(device_info.sampledImageIntegerSampleCounts &
|
||||
(device_properties.framebufferColorSampleCounts &
|
||||
device_properties.framebufferDepthSampleCounts &
|
||||
device_properties.framebufferStencilSampleCounts &
|
||||
device_properties.sampledImageColorSampleCounts &
|
||||
device_properties.sampledImageDepthSampleCounts &
|
||||
device_properties.sampledImageStencilSampleCounts &
|
||||
VK_SAMPLE_COUNT_2_BIT) &&
|
||||
(device_properties.sampledImageIntegerSampleCounts &
|
||||
(VK_SAMPLE_COUNT_2_BIT | VK_SAMPLE_COUNT_4_BIT)) !=
|
||||
VK_SAMPLE_COUNT_4_BIT;
|
||||
msaa_2x_no_attachments_supported_ =
|
||||
(device_info.framebufferNoAttachmentsSampleCounts &
|
||||
(device_properties.framebufferNoAttachmentsSampleCounts &
|
||||
VK_SAMPLE_COUNT_2_BIT) != 0;
|
||||
} else {
|
||||
msaa_2x_attachments_supported_ = false;
|
||||
@@ -343,19 +345,19 @@ bool VulkanRenderTargetCache::Initialize(uint32_t shared_memory_binding_count) {
|
||||
descriptor_set_layout_size.descriptorCount = 1;
|
||||
descriptor_set_pool_sampled_image_ =
|
||||
std::make_unique<ui::vulkan::SingleLayoutDescriptorSetPool>(
|
||||
provider, 256, 1, &descriptor_set_layout_size,
|
||||
vulkan_device, 256, 1, &descriptor_set_layout_size,
|
||||
descriptor_set_layout_sampled_image_);
|
||||
descriptor_set_layout_size.descriptorCount = 2;
|
||||
descriptor_set_pool_sampled_image_x2_ =
|
||||
std::make_unique<ui::vulkan::SingleLayoutDescriptorSetPool>(
|
||||
provider, 256, 1, &descriptor_set_layout_size,
|
||||
vulkan_device, 256, 1, &descriptor_set_layout_size,
|
||||
descriptor_set_layout_sampled_image_x2_);
|
||||
|
||||
// EDRAM contents reinterpretation buffer.
|
||||
// 90 MB with 9x resolution scaling - within the minimum
|
||||
// maxStorageBufferRange.
|
||||
if (!ui::vulkan::util::CreateDedicatedAllocationBuffer(
|
||||
provider,
|
||||
vulkan_device,
|
||||
VkDeviceSize(xenos::kEdramSizeBytes *
|
||||
(draw_resolution_scale_x() * draw_resolution_scale_y())),
|
||||
VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
|
||||
@@ -492,7 +494,7 @@ bool VulkanRenderTargetCache::Initialize(uint32_t shared_memory_binding_count) {
|
||||
resolve_copy_shader_code.scaled &&
|
||||
resolve_copy_shader_code.scaled_size_bytes);
|
||||
VkPipeline resolve_copy_pipeline = ui::vulkan::util::CreateComputePipeline(
|
||||
provider, resolve_copy_pipeline_layout_,
|
||||
vulkan_device, resolve_copy_pipeline_layout_,
|
||||
draw_resolution_scaled ? resolve_copy_shader_code.scaled
|
||||
: resolve_copy_shader_code.unscaled,
|
||||
draw_resolution_scaled ? resolve_copy_shader_code.scaled_size_bytes
|
||||
@@ -505,7 +507,7 @@ bool VulkanRenderTargetCache::Initialize(uint32_t shared_memory_binding_count) {
|
||||
Shutdown();
|
||||
return false;
|
||||
}
|
||||
provider.SetDeviceObjectName(VK_OBJECT_TYPE_PIPELINE, resolve_copy_pipeline,
|
||||
vulkan_device->SetObjectName(VK_OBJECT_TYPE_PIPELINE, resolve_copy_pipeline,
|
||||
resolve_copy_shader_info.debug_name);
|
||||
resolve_copy_pipelines_[i] = resolve_copy_pipeline;
|
||||
}
|
||||
@@ -563,7 +565,7 @@ bool VulkanRenderTargetCache::Initialize(uint32_t shared_memory_binding_count) {
|
||||
host_depth_store_shaders[i];
|
||||
VkPipeline host_depth_store_pipeline =
|
||||
ui::vulkan::util::CreateComputePipeline(
|
||||
provider, host_depth_store_pipeline_layout_,
|
||||
vulkan_device, host_depth_store_pipeline_layout_,
|
||||
host_depth_store_shader.first, host_depth_store_shader.second);
|
||||
if (host_depth_store_pipeline == VK_NULL_HANDLE) {
|
||||
XELOGE(
|
||||
@@ -579,7 +581,7 @@ bool VulkanRenderTargetCache::Initialize(uint32_t shared_memory_binding_count) {
|
||||
// Transfer and clear vertex buffer, for quads of up to tile granularity.
|
||||
transfer_vertex_buffer_pool_ =
|
||||
std::make_unique<ui::vulkan::VulkanUploadBufferPool>(
|
||||
provider, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
|
||||
vulkan_device, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
|
||||
std::max(ui::vulkan::VulkanUploadBufferPool::kDefaultPageSize,
|
||||
sizeof(float) * 2 * 6 *
|
||||
Transfer::kMaxCutoutBorderRectangles *
|
||||
@@ -587,7 +589,7 @@ bool VulkanRenderTargetCache::Initialize(uint32_t shared_memory_binding_count) {
|
||||
|
||||
// Transfer vertex shader.
|
||||
transfer_passthrough_vertex_shader_ = ui::vulkan::util::CreateShaderModule(
|
||||
provider, shaders::passthrough_position_xy_vs,
|
||||
vulkan_device, shaders::passthrough_position_xy_vs,
|
||||
sizeof(shaders::passthrough_position_xy_vs));
|
||||
if (transfer_passthrough_vertex_shader_ == VK_NULL_HANDLE) {
|
||||
XELOGE(
|
||||
@@ -751,7 +753,7 @@ bool VulkanRenderTargetCache::Initialize(uint32_t shared_memory_binding_count) {
|
||||
return false;
|
||||
}
|
||||
resolve_fsi_clear_32bpp_pipeline_ = ui::vulkan::util::CreateComputePipeline(
|
||||
provider, resolve_fsi_clear_pipeline_layout_,
|
||||
vulkan_device, resolve_fsi_clear_pipeline_layout_,
|
||||
draw_resolution_scaled ? shaders::resolve_clear_32bpp_scaled_cs
|
||||
: shaders::resolve_clear_32bpp_cs,
|
||||
draw_resolution_scaled ? sizeof(shaders::resolve_clear_32bpp_scaled_cs)
|
||||
@@ -764,7 +766,7 @@ bool VulkanRenderTargetCache::Initialize(uint32_t shared_memory_binding_count) {
|
||||
return false;
|
||||
}
|
||||
resolve_fsi_clear_64bpp_pipeline_ = ui::vulkan::util::CreateComputePipeline(
|
||||
provider, resolve_fsi_clear_pipeline_layout_,
|
||||
vulkan_device, resolve_fsi_clear_pipeline_layout_,
|
||||
draw_resolution_scaled ? shaders::resolve_clear_64bpp_scaled_cs
|
||||
: shaders::resolve_clear_64bpp_cs,
|
||||
draw_resolution_scaled ? sizeof(shaders::resolve_clear_64bpp_scaled_cs)
|
||||
@@ -832,10 +834,10 @@ bool VulkanRenderTargetCache::Initialize(uint32_t shared_memory_binding_count) {
|
||||
fsi_framebuffer_create_info.pAttachments = nullptr;
|
||||
fsi_framebuffer_create_info.width = std::min(
|
||||
xenos::kTexture2DCubeMaxWidthHeight * draw_resolution_scale_x(),
|
||||
device_info.maxFramebufferWidth);
|
||||
device_properties.maxFramebufferWidth);
|
||||
fsi_framebuffer_create_info.height = std::min(
|
||||
xenos::kTexture2DCubeMaxWidthHeight * draw_resolution_scale_y(),
|
||||
device_info.maxFramebufferHeight);
|
||||
device_properties.maxFramebufferHeight);
|
||||
fsi_framebuffer_create_info.layers = 1;
|
||||
if (dfn.vkCreateFramebuffer(device, &fsi_framebuffer_create_info, nullptr,
|
||||
&fsi_framebuffer_.framebuffer) != VK_SUCCESS) {
|
||||
@@ -867,10 +869,10 @@ bool VulkanRenderTargetCache::Initialize(uint32_t shared_memory_binding_count) {
|
||||
}
|
||||
|
||||
void VulkanRenderTargetCache::Shutdown(bool from_destructor) {
|
||||
const ui::vulkan::VulkanProvider& provider =
|
||||
command_processor_.GetVulkanProvider();
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||
VkDevice device = provider.device();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device =
|
||||
command_processor_.GetVulkanDevice();
|
||||
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
|
||||
const VkDevice device = vulkan_device->device();
|
||||
|
||||
// Destroy all render targets before the descriptor set pool is destroyed -
|
||||
// may happen if shutting down the VulkanRenderTargetCache by destroying it,
|
||||
@@ -979,10 +981,10 @@ void VulkanRenderTargetCache::Shutdown(bool from_destructor) {
|
||||
}
|
||||
|
||||
void VulkanRenderTargetCache::ClearCache() {
|
||||
const ui::vulkan::VulkanProvider& provider =
|
||||
command_processor_.GetVulkanProvider();
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||
VkDevice device = provider.device();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device =
|
||||
command_processor_.GetVulkanDevice();
|
||||
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
|
||||
const VkDevice device = vulkan_device->device();
|
||||
|
||||
// Framebuffer objects must be destroyed because they reference views of
|
||||
// attachment images, which may be removed by the common ClearCache.
|
||||
@@ -1038,10 +1040,10 @@ bool VulkanRenderTargetCache::Resolve(const Memory& memory,
|
||||
return true;
|
||||
}
|
||||
|
||||
const ui::vulkan::VulkanProvider& provider =
|
||||
command_processor_.GetVulkanProvider();
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||
VkDevice device = provider.device();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device =
|
||||
command_processor_.GetVulkanDevice();
|
||||
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
|
||||
const VkDevice device = vulkan_device->device();
|
||||
DeferredCommandBuffer& command_buffer =
|
||||
command_processor_.deferred_command_buffer();
|
||||
|
||||
@@ -1548,10 +1550,10 @@ VkRenderPass VulkanRenderTargetCache::GetHostRenderTargetsRenderPass(
|
||||
: 0;
|
||||
render_pass_create_info.pDependencies = subpass_dependencies;
|
||||
|
||||
const ui::vulkan::VulkanProvider& provider =
|
||||
command_processor_.GetVulkanProvider();
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||
VkDevice device = provider.device();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device =
|
||||
command_processor_.GetVulkanDevice();
|
||||
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
|
||||
const VkDevice device = vulkan_device->device();
|
||||
VkRenderPass render_pass;
|
||||
if (dfn.vkCreateRenderPass(device, &render_pass_create_info, nullptr,
|
||||
&render_pass) != VK_SUCCESS) {
|
||||
@@ -1638,10 +1640,10 @@ VkFormat VulkanRenderTargetCache::GetColorOwnershipTransferVulkanFormat(
|
||||
}
|
||||
|
||||
VulkanRenderTargetCache::VulkanRenderTarget::~VulkanRenderTarget() {
|
||||
const ui::vulkan::VulkanProvider& provider =
|
||||
render_target_cache_.command_processor_.GetVulkanProvider();
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||
VkDevice device = provider.device();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device =
|
||||
render_target_cache_.command_processor_.GetVulkanDevice();
|
||||
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
|
||||
const VkDevice device = vulkan_device->device();
|
||||
ui::vulkan::SingleLayoutDescriptorSetPool& descriptor_set_pool =
|
||||
key().is_depth
|
||||
? *render_target_cache_.descriptor_set_pool_sampled_image_x2_
|
||||
@@ -1665,25 +1667,25 @@ VulkanRenderTargetCache::VulkanRenderTarget::~VulkanRenderTarget() {
|
||||
}
|
||||
|
||||
uint32_t VulkanRenderTargetCache::GetMaxRenderTargetWidth() const {
|
||||
const ui::vulkan::VulkanProvider::DeviceInfo& device_info =
|
||||
command_processor_.GetVulkanProvider().device_info();
|
||||
return std::min(device_info.maxFramebufferWidth,
|
||||
device_info.maxImageDimension2D);
|
||||
const ui::vulkan::VulkanDevice::Properties& device_properties =
|
||||
command_processor_.GetVulkanDevice()->properties();
|
||||
return std::min(device_properties.maxFramebufferWidth,
|
||||
device_properties.maxImageDimension2D);
|
||||
}
|
||||
|
||||
uint32_t VulkanRenderTargetCache::GetMaxRenderTargetHeight() const {
|
||||
const ui::vulkan::VulkanProvider::DeviceInfo& device_info =
|
||||
command_processor_.GetVulkanProvider().device_info();
|
||||
return std::min(device_info.maxFramebufferHeight,
|
||||
device_info.maxImageDimension2D);
|
||||
const ui::vulkan::VulkanDevice::Properties& device_properties =
|
||||
command_processor_.GetVulkanDevice()->properties();
|
||||
return std::min(device_properties.maxFramebufferHeight,
|
||||
device_properties.maxImageDimension2D);
|
||||
}
|
||||
|
||||
RenderTargetCache::RenderTarget* VulkanRenderTargetCache::CreateRenderTarget(
|
||||
RenderTargetKey key) {
|
||||
const ui::vulkan::VulkanProvider& provider =
|
||||
command_processor_.GetVulkanProvider();
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||
VkDevice device = provider.device();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device =
|
||||
command_processor_.GetVulkanDevice();
|
||||
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
|
||||
const VkDevice device = vulkan_device->device();
|
||||
|
||||
// Create the image.
|
||||
|
||||
@@ -1739,7 +1741,7 @@ RenderTargetCache::RenderTarget* VulkanRenderTargetCache::CreateRenderTarget(
|
||||
VkImage image;
|
||||
VkDeviceMemory memory;
|
||||
if (!ui::vulkan::util::CreateDedicatedAllocationImage(
|
||||
provider, image_create_info,
|
||||
vulkan_device, image_create_info,
|
||||
ui::vulkan::util::MemoryPurpose::kDeviceLocal, image, memory)) {
|
||||
XELOGE(
|
||||
"VulkanRenderTarget: Failed to create a {}x{} {}xMSAA {} render target "
|
||||
@@ -2065,12 +2067,12 @@ VulkanRenderTargetCache::GetHostRenderTargetsFramebuffer(
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
const ui::vulkan::VulkanProvider& provider =
|
||||
command_processor_.GetVulkanProvider();
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||
VkDevice device = provider.device();
|
||||
const ui::vulkan::VulkanProvider::DeviceInfo& device_info =
|
||||
provider.device_info();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device =
|
||||
command_processor_.GetVulkanDevice();
|
||||
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
|
||||
const VkDevice device = vulkan_device->device();
|
||||
const ui::vulkan::VulkanDevice::Properties& device_properties =
|
||||
vulkan_device->properties();
|
||||
|
||||
VkRenderPass render_pass = GetHostRenderTargetsRenderPass(render_pass_key);
|
||||
if (render_pass == VK_NULL_HANDLE) {
|
||||
@@ -2119,9 +2121,9 @@ VulkanRenderTargetCache::GetHostRenderTargetsFramebuffer(
|
||||
// there's no limit imposed by the sizes of the attachments that have been
|
||||
// created successfully.
|
||||
host_extent.width = std::min(host_extent.width * draw_resolution_scale_x(),
|
||||
device_info.maxFramebufferWidth);
|
||||
device_properties.maxFramebufferWidth);
|
||||
host_extent.height = std::min(host_extent.height * draw_resolution_scale_y(),
|
||||
device_info.maxFramebufferHeight);
|
||||
device_properties.maxFramebufferHeight);
|
||||
framebuffer_create_info.width = host_extent.width;
|
||||
framebuffer_create_info.height = host_extent.height;
|
||||
framebuffer_create_info.layers = 1;
|
||||
@@ -2144,10 +2146,10 @@ VkShaderModule VulkanRenderTargetCache::GetTransferShader(
|
||||
return shader_it->second;
|
||||
}
|
||||
|
||||
const ui::vulkan::VulkanProvider& provider =
|
||||
command_processor_.GetVulkanProvider();
|
||||
const ui::vulkan::VulkanProvider::DeviceInfo& device_info =
|
||||
provider.device_info();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device =
|
||||
command_processor_.GetVulkanDevice();
|
||||
const ui::vulkan::VulkanDevice::Properties& device_properties =
|
||||
vulkan_device->properties();
|
||||
|
||||
std::vector<spv::Id> id_vector_temp;
|
||||
std::vector<unsigned int> uint_vector_temp;
|
||||
@@ -2235,7 +2237,7 @@ VkShaderModule VulkanRenderTargetCache::GetTransferShader(
|
||||
// Outputs.
|
||||
bool shader_uses_stencil_reference_output =
|
||||
mode.output == TransferOutput::kDepth &&
|
||||
provider.device_info().ext_VK_EXT_shader_stencil_export;
|
||||
vulkan_device->extensions().ext_EXT_shader_stencil_export;
|
||||
bool dest_color_is_uint = false;
|
||||
uint32_t dest_color_component_count = 0;
|
||||
spv::Id type_fragment_data_component = spv::NoResult;
|
||||
@@ -2471,7 +2473,7 @@ VkShaderModule VulkanRenderTargetCache::GetTransferShader(
|
||||
spv::Id input_sample_id = spv::NoResult;
|
||||
spv::Id spec_const_sample_id = spv::NoResult;
|
||||
if (key.dest_msaa_samples != xenos::MsaaSamples::k1X) {
|
||||
if (device_info.sampleRateShading) {
|
||||
if (device_properties.sampleRateShading) {
|
||||
// One draw for all samples.
|
||||
builder.addCapability(spv::CapabilitySampleRateShading);
|
||||
input_sample_id = builder.createVariable(
|
||||
@@ -2565,7 +2567,7 @@ VkShaderModule VulkanRenderTargetCache::GetTransferShader(
|
||||
// Load the destination sample index.
|
||||
spv::Id dest_sample_id = spv::NoResult;
|
||||
if (key.dest_msaa_samples != xenos::MsaaSamples::k1X) {
|
||||
if (device_info.sampleRateShading) {
|
||||
if (device_properties.sampleRateShading) {
|
||||
assert_true(input_sample_id != spv::NoResult);
|
||||
dest_sample_id = builder.createUnaryOp(
|
||||
spv::OpBitcast, type_uint,
|
||||
@@ -4188,7 +4190,7 @@ VkShaderModule VulkanRenderTargetCache::GetTransferShader(
|
||||
// Create the shader module, and store the handle even if creation fails not
|
||||
// to try to create it again later.
|
||||
VkShaderModule shader_module = ui::vulkan::util::CreateShaderModule(
|
||||
provider, reinterpret_cast<const uint32_t*>(shader_code.data()),
|
||||
vulkan_device, reinterpret_cast<const uint32_t*>(shader_code.data()),
|
||||
sizeof(uint32_t) * shader_code.size());
|
||||
if (shader_module == VK_NULL_HANDLE) {
|
||||
XELOGE(
|
||||
@@ -4219,17 +4221,17 @@ VkPipeline const* VulkanRenderTargetCache::GetTransferPipelines(
|
||||
|
||||
const TransferModeInfo& mode = kTransferModes[size_t(key.shader_key.mode)];
|
||||
|
||||
const ui::vulkan::VulkanProvider& provider =
|
||||
command_processor_.GetVulkanProvider();
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||
VkDevice device = provider.device();
|
||||
const ui::vulkan::VulkanProvider::DeviceInfo& device_info =
|
||||
provider.device_info();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device =
|
||||
command_processor_.GetVulkanDevice();
|
||||
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
|
||||
const VkDevice device = vulkan_device->device();
|
||||
const ui::vulkan::VulkanDevice::Properties& device_properties =
|
||||
vulkan_device->properties();
|
||||
|
||||
uint32_t dest_sample_count = uint32_t(1)
|
||||
<< uint32_t(key.shader_key.dest_msaa_samples);
|
||||
bool dest_is_masked_sample =
|
||||
dest_sample_count > 1 && !device_info.sampleRateShading;
|
||||
dest_sample_count > 1 && !device_properties.sampleRateShading;
|
||||
|
||||
VkPipelineShaderStageCreateInfo shader_stages[2];
|
||||
shader_stages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||
@@ -4321,7 +4323,7 @@ VkPipeline const* VulkanRenderTargetCache::GetTransferPipelines(
|
||||
? VK_SAMPLE_COUNT_4_BIT
|
||||
: VkSampleCountFlagBits(dest_sample_count);
|
||||
if (dest_sample_count > 1) {
|
||||
if (device_info.sampleRateShading) {
|
||||
if (device_properties.sampleRateShading) {
|
||||
multisample_state.sampleShadingEnable = VK_TRUE;
|
||||
multisample_state.minSampleShading = 1.0f;
|
||||
if (dest_sample_count == 2 && !msaa_2x_attachments_supported_) {
|
||||
@@ -4352,7 +4354,7 @@ VkPipeline const* VulkanRenderTargetCache::GetTransferPipelines(
|
||||
: VK_COMPARE_OP_ALWAYS;
|
||||
}
|
||||
if ((mode.output == TransferOutput::kDepth &&
|
||||
provider.device_info().ext_VK_EXT_shader_stencil_export) ||
|
||||
vulkan_device->extensions().ext_EXT_shader_stencil_export) ||
|
||||
mode.output == TransferOutput::kStencilBit) {
|
||||
depth_stencil_state.stencilTestEnable = VK_TRUE;
|
||||
depth_stencil_state.front.failOp = VK_STENCIL_OP_KEEP;
|
||||
@@ -4380,21 +4382,10 @@ VkPipeline const* VulkanRenderTargetCache::GetTransferPipelines(
|
||||
32 - xe::lzcnt(key.render_pass_key.depth_and_color_used >> 1);
|
||||
color_blend_state.pAttachments = color_blend_attachments;
|
||||
if (mode.output == TransferOutput::kColor) {
|
||||
if (device_info.independentBlend) {
|
||||
// State the intention more explicitly.
|
||||
color_blend_attachments[key.shader_key.dest_color_rt_index]
|
||||
.colorWriteMask = VK_COLOR_COMPONENT_R_BIT |
|
||||
VK_COLOR_COMPONENT_G_BIT |
|
||||
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
|
||||
} else {
|
||||
// The blend state for all attachments must be identical, but other render
|
||||
// targets are not written to by the shader.
|
||||
for (uint32_t i = 0; i < color_blend_state.attachmentCount; ++i) {
|
||||
color_blend_attachments[i].colorWriteMask =
|
||||
VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
|
||||
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
|
||||
}
|
||||
}
|
||||
assert_true(device_properties.independentBlend);
|
||||
color_blend_attachments[key.shader_key.dest_color_rt_index].colorWriteMask =
|
||||
VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
|
||||
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
|
||||
}
|
||||
|
||||
std::array<VkDynamicState, 3> dynamic_states;
|
||||
@@ -4487,8 +4478,8 @@ void VulkanRenderTargetCache::PerformTransfersAndResolveClears(
|
||||
const Transfer::Rectangle* resolve_clear_rectangle) {
|
||||
assert_true(GetPath() == Path::kHostRenderTargets);
|
||||
|
||||
const ui::vulkan::VulkanProvider::DeviceInfo& device_info =
|
||||
command_processor_.GetVulkanProvider().device_info();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device =
|
||||
command_processor_.GetVulkanDevice();
|
||||
uint64_t current_submission = command_processor_.GetCurrentSubmission();
|
||||
DeferredCommandBuffer& command_buffer =
|
||||
command_processor_.deferred_command_buffer();
|
||||
@@ -4803,7 +4794,8 @@ void VulkanRenderTargetCache::PerformTransfersAndResolveClears(
|
||||
// Gather shader keys and sort to reduce pipeline state and binding
|
||||
// switches. Also gather stencil rectangles to clear if needed.
|
||||
bool need_stencil_bit_draws =
|
||||
dest_rt_key.is_depth && !device_info.ext_VK_EXT_shader_stencil_export;
|
||||
dest_rt_key.is_depth &&
|
||||
!vulkan_device->extensions().ext_EXT_shader_stencil_export;
|
||||
current_transfer_invocations_.clear();
|
||||
current_transfer_invocations_.reserve(
|
||||
current_transfers.size() << uint32_t(need_stencil_bit_draws));
|
||||
@@ -4995,10 +4987,10 @@ void VulkanRenderTargetCache::PerformTransfersAndResolveClears(
|
||||
transfer_viewport.y = 0.0f;
|
||||
transfer_viewport.width =
|
||||
float(std::min(xe::next_pow2(transfer_framebuffer->host_extent.width),
|
||||
device_info.maxViewportDimensions[0]));
|
||||
vulkan_device->properties().maxViewportDimensions[0]));
|
||||
transfer_viewport.height = float(
|
||||
std::min(xe::next_pow2(transfer_framebuffer->host_extent.height),
|
||||
device_info.maxViewportDimensions[1]));
|
||||
vulkan_device->properties().maxViewportDimensions[1]));
|
||||
transfer_viewport.minDepth = 0.0f;
|
||||
transfer_viewport.maxDepth = 1.0f;
|
||||
command_processor_.SetViewport(transfer_viewport);
|
||||
@@ -5049,7 +5041,7 @@ void VulkanRenderTargetCache::PerformTransfersAndResolveClears(
|
||||
kTransferPipelineLayoutInfos[size_t(
|
||||
transfer_pipeline_layout_index)];
|
||||
uint32_t transfer_sample_pipeline_count =
|
||||
device_info.sampleRateShading
|
||||
vulkan_device->properties().sampleRateShading
|
||||
? 1
|
||||
: uint32_t(1) << uint32_t(dest_rt_key.msaa_samples);
|
||||
bool transfer_is_stencil_bit =
|
||||
@@ -5916,7 +5908,7 @@ VkPipeline VulkanRenderTargetCache::GetDumpPipeline(DumpPipelineKey key) {
|
||||
// Create the pipeline, and store the handle even if creation fails not to try
|
||||
// to create it again later.
|
||||
VkPipeline pipeline = ui::vulkan::util::CreateComputePipeline(
|
||||
command_processor_.GetVulkanProvider(),
|
||||
command_processor_.GetVulkanDevice(),
|
||||
key.is_depth ? dump_pipeline_layout_depth_ : dump_pipeline_layout_color_,
|
||||
reinterpret_cast<const uint32_t*>(shader_code.data()),
|
||||
sizeof(uint32_t) * shader_code.size());
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include "xenia/gpu/vulkan/vulkan_texture_cache.h"
|
||||
#include "xenia/gpu/xenos.h"
|
||||
#include "xenia/ui/vulkan/single_layout_descriptor_set_pool.h"
|
||||
#include "xenia/ui/vulkan/vulkan_provider.h"
|
||||
#include "xenia/ui/vulkan/vulkan_upload_buffer_pool.h"
|
||||
|
||||
namespace xe {
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
|
||||
#include "xenia/gpu/vulkan/vulkan_shader.h"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "xenia/base/assert.h"
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/ui/vulkan/vulkan_provider.h"
|
||||
|
||||
@@ -18,10 +21,10 @@ namespace vulkan {
|
||||
|
||||
VulkanShader::VulkanTranslation::~VulkanTranslation() {
|
||||
if (shader_module_) {
|
||||
const ui::vulkan::VulkanProvider& provider =
|
||||
static_cast<const VulkanShader&>(shader()).provider_;
|
||||
provider.dfn().vkDestroyShaderModule(provider.device(), shader_module_,
|
||||
nullptr);
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device =
|
||||
static_cast<const VulkanShader&>(shader()).vulkan_device_;
|
||||
vulkan_device->functions().vkDestroyShaderModule(vulkan_device->device(),
|
||||
shader_module_, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,8 +35,8 @@ VkShaderModule VulkanShader::VulkanTranslation::GetOrCreateShaderModule() {
|
||||
if (shader_module_ != VK_NULL_HANDLE) {
|
||||
return shader_module_;
|
||||
}
|
||||
const ui::vulkan::VulkanProvider& provider =
|
||||
static_cast<const VulkanShader&>(shader()).provider_;
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device =
|
||||
static_cast<const VulkanShader&>(shader()).vulkan_device_;
|
||||
VkShaderModuleCreateInfo shader_module_create_info;
|
||||
shader_module_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||
shader_module_create_info.pNext = nullptr;
|
||||
@@ -41,9 +44,9 @@ VkShaderModule VulkanShader::VulkanTranslation::GetOrCreateShaderModule() {
|
||||
shader_module_create_info.codeSize = translated_binary().size();
|
||||
shader_module_create_info.pCode =
|
||||
reinterpret_cast<const uint32_t*>(translated_binary().data());
|
||||
if (provider.dfn().vkCreateShaderModule(provider.device(),
|
||||
&shader_module_create_info, nullptr,
|
||||
&shader_module_) != VK_SUCCESS) {
|
||||
if (vulkan_device->functions().vkCreateShaderModule(
|
||||
vulkan_device->device(), &shader_module_create_info, nullptr,
|
||||
&shader_module_) != VK_SUCCESS) {
|
||||
XELOGE(
|
||||
"VulkanShader::VulkanTranslation: Failed to create a Vulkan shader "
|
||||
"module for shader {:016X} modification {:016X}",
|
||||
@@ -54,15 +57,17 @@ VkShaderModule VulkanShader::VulkanTranslation::GetOrCreateShaderModule() {
|
||||
return shader_module_;
|
||||
}
|
||||
|
||||
VulkanShader::VulkanShader(const ui::vulkan::VulkanProvider& provider,
|
||||
xenos::ShaderType shader_type,
|
||||
uint64_t ucode_data_hash,
|
||||
const uint32_t* ucode_dwords,
|
||||
size_t ucode_dword_count,
|
||||
std::endian ucode_source_endian)
|
||||
VulkanShader::VulkanShader(const ui::vulkan::VulkanDevice* const vulkan_device,
|
||||
const xenos::ShaderType shader_type,
|
||||
const uint64_t ucode_data_hash,
|
||||
const uint32_t* const ucode_dwords,
|
||||
const size_t ucode_dword_count,
|
||||
const std::endian ucode_source_endian)
|
||||
: SpirvShader(shader_type, ucode_data_hash, ucode_dwords, ucode_dword_count,
|
||||
ucode_source_endian),
|
||||
provider_(provider) {}
|
||||
vulkan_device_(vulkan_device) {
|
||||
assert_not_null(vulkan_device);
|
||||
}
|
||||
|
||||
Shader::Translation* VulkanShader::CreateTranslationInstance(
|
||||
uint64_t modification) {
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
#include "xenia/gpu/spirv_shader.h"
|
||||
#include "xenia/gpu/xenos.h"
|
||||
#include "xenia/ui/vulkan/vulkan_provider.h"
|
||||
#include "xenia/ui/vulkan/vulkan_device.h"
|
||||
|
||||
namespace xe {
|
||||
namespace gpu {
|
||||
@@ -35,7 +35,7 @@ class VulkanShader : public SpirvShader {
|
||||
VkShaderModule shader_module_ = VK_NULL_HANDLE;
|
||||
};
|
||||
|
||||
explicit VulkanShader(const ui::vulkan::VulkanProvider& provider,
|
||||
explicit VulkanShader(const ui::vulkan::VulkanDevice* vulkan_device,
|
||||
xenos::ShaderType shader_type, uint64_t ucode_data_hash,
|
||||
const uint32_t* ucode_dwords, size_t ucode_dword_count,
|
||||
std::endian ucode_source_endian = std::endian::big);
|
||||
@@ -67,7 +67,7 @@ class VulkanShader : public SpirvShader {
|
||||
Translation* CreateTranslationInstance(uint64_t modification) override;
|
||||
|
||||
private:
|
||||
const ui::vulkan::VulkanProvider& provider_;
|
||||
const ui::vulkan::VulkanDevice* vulkan_device_;
|
||||
|
||||
std::atomic_flag binding_layout_user_uids_set_up_ = ATOMIC_FLAG_INIT;
|
||||
size_t texture_binding_layout_user_uid_ = 0;
|
||||
|
||||
@@ -44,12 +44,10 @@ VulkanSharedMemory::~VulkanSharedMemory() { Shutdown(true); }
|
||||
bool VulkanSharedMemory::Initialize() {
|
||||
InitializeCommon();
|
||||
|
||||
const ui::vulkan::VulkanProvider& provider =
|
||||
command_processor_.GetVulkanProvider();
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||
VkDevice device = provider.device();
|
||||
const ui::vulkan::VulkanProvider::DeviceInfo& device_info =
|
||||
provider.device_info();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device =
|
||||
command_processor_.GetVulkanDevice();
|
||||
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
|
||||
const VkDevice device = vulkan_device->device();
|
||||
|
||||
const VkBufferCreateFlags sparse_flags =
|
||||
VK_BUFFER_CREATE_SPARSE_BINDING_BIT |
|
||||
@@ -67,14 +65,15 @@ bool VulkanSharedMemory::Initialize() {
|
||||
buffer_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
buffer_create_info.queueFamilyIndexCount = 0;
|
||||
buffer_create_info.pQueueFamilyIndices = nullptr;
|
||||
if (cvars::vulkan_sparse_shared_memory && device_info.sparseResidencyBuffer) {
|
||||
if (cvars::vulkan_sparse_shared_memory &&
|
||||
vulkan_device->properties().sparseResidencyBuffer) {
|
||||
if (dfn.vkCreateBuffer(device, &buffer_create_info, nullptr, &buffer_) ==
|
||||
VK_SUCCESS) {
|
||||
VkMemoryRequirements buffer_memory_requirements;
|
||||
dfn.vkGetBufferMemoryRequirements(device, buffer_,
|
||||
&buffer_memory_requirements);
|
||||
if (xe::bit_scan_forward(buffer_memory_requirements.memoryTypeBits &
|
||||
device_info.memory_types_device_local,
|
||||
vulkan_device->memory_types().device_local,
|
||||
&buffer_memory_type_)) {
|
||||
uint32_t allocation_size_log2;
|
||||
xe::bit_scan_forward(
|
||||
@@ -127,7 +126,7 @@ bool VulkanSharedMemory::Initialize() {
|
||||
dfn.vkGetBufferMemoryRequirements(device, buffer_,
|
||||
&buffer_memory_requirements);
|
||||
if (!xe::bit_scan_forward(buffer_memory_requirements.memoryTypeBits &
|
||||
device_info.memory_types_device_local,
|
||||
vulkan_device->memory_types().device_local,
|
||||
&buffer_memory_type_)) {
|
||||
XELOGE(
|
||||
"Shared memory: Failed to get a device-local Vulkan memory type for "
|
||||
@@ -144,7 +143,7 @@ bool VulkanSharedMemory::Initialize() {
|
||||
buffer_memory_requirements.size;
|
||||
buffer_memory_allocate_info.memoryTypeIndex = buffer_memory_type_;
|
||||
VkMemoryDedicatedAllocateInfo buffer_memory_dedicated_allocate_info;
|
||||
if (provider.device_info().ext_1_1_VK_KHR_dedicated_allocation) {
|
||||
if (vulkan_device->extensions().ext_1_1_KHR_dedicated_allocation) {
|
||||
buffer_memory_allocate_info_last->pNext =
|
||||
&buffer_memory_dedicated_allocate_info;
|
||||
buffer_memory_allocate_info_last =
|
||||
@@ -180,7 +179,7 @@ bool VulkanSharedMemory::Initialize() {
|
||||
last_written_range_ = std::make_pair<uint32_t, uint32_t>(0, 0);
|
||||
|
||||
upload_buffer_pool_ = std::make_unique<ui::vulkan::VulkanUploadBufferPool>(
|
||||
provider, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
||||
vulkan_device, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
||||
xe::align(ui::vulkan::VulkanUploadBufferPool::kDefaultPageSize,
|
||||
size_t(1) << page_size_log2()));
|
||||
|
||||
@@ -192,10 +191,10 @@ void VulkanSharedMemory::Shutdown(bool from_destructor) {
|
||||
|
||||
upload_buffer_pool_.reset();
|
||||
|
||||
const ui::vulkan::VulkanProvider& provider =
|
||||
command_processor_.GetVulkanProvider();
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||
VkDevice device = provider.device();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device =
|
||||
command_processor_.GetVulkanDevice();
|
||||
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
|
||||
const VkDevice device = vulkan_device->device();
|
||||
|
||||
ui::vulkan::util::DestroyAndNullHandle(dfn.vkDestroyBuffer, device, buffer_);
|
||||
for (VkDeviceMemory memory : buffer_memory_) {
|
||||
@@ -257,10 +256,9 @@ bool VulkanSharedMemory::InitializeTraceSubmitDownloads() {
|
||||
return false;
|
||||
}
|
||||
|
||||
const ui::vulkan::VulkanProvider& provider =
|
||||
command_processor_.GetVulkanProvider();
|
||||
if (!ui::vulkan::util::CreateDedicatedAllocationBuffer(
|
||||
provider, download_page_count << page_size_log2(),
|
||||
command_processor_.GetVulkanDevice(),
|
||||
download_page_count << page_size_log2(),
|
||||
VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||
ui::vulkan::util::MemoryPurpose::kReadback, trace_download_buffer_,
|
||||
trace_download_buffer_memory_)) {
|
||||
@@ -303,10 +301,10 @@ void VulkanSharedMemory::InitializeTraceCompleteDownloads() {
|
||||
if (!trace_download_buffer_memory_) {
|
||||
return;
|
||||
}
|
||||
const ui::vulkan::VulkanProvider& provider =
|
||||
command_processor_.GetVulkanProvider();
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||
VkDevice device = provider.device();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device =
|
||||
command_processor_.GetVulkanDevice();
|
||||
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
|
||||
const VkDevice device = vulkan_device->device();
|
||||
void* download_mapping;
|
||||
if (dfn.vkMapMemory(device, trace_download_buffer_memory_, 0, VK_WHOLE_SIZE,
|
||||
0, &download_mapping) == VK_SUCCESS) {
|
||||
@@ -332,10 +330,10 @@ bool VulkanSharedMemory::AllocateSparseHostGpuMemoryRange(
|
||||
return true;
|
||||
}
|
||||
|
||||
const ui::vulkan::VulkanProvider& provider =
|
||||
command_processor_.GetVulkanProvider();
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||
VkDevice device = provider.device();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device =
|
||||
command_processor_.GetVulkanDevice();
|
||||
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
|
||||
const VkDevice device = vulkan_device->device();
|
||||
|
||||
VkMemoryAllocateInfo memory_allocate_info;
|
||||
memory_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
@@ -362,7 +360,7 @@ bool VulkanSharedMemory::AllocateSparseHostGpuMemoryRange(
|
||||
VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||
if (provider.device_info().tessellationShader) {
|
||||
if (vulkan_device->properties().tessellationShader) {
|
||||
bind_wait_stage_mask |=
|
||||
VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT;
|
||||
}
|
||||
@@ -484,10 +482,10 @@ void VulkanSharedMemory::GetUsageMasks(Usage usage,
|
||||
}
|
||||
|
||||
void VulkanSharedMemory::ResetTraceDownload() {
|
||||
const ui::vulkan::VulkanProvider& provider =
|
||||
command_processor_.GetVulkanProvider();
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||
VkDevice device = provider.device();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device =
|
||||
command_processor_.GetVulkanDevice();
|
||||
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
|
||||
const VkDevice device = vulkan_device->device();
|
||||
ui::vulkan::util::DestroyAndNullHandle(dfn.vkDestroyBuffer, device,
|
||||
trace_download_buffer_);
|
||||
ui::vulkan::util::DestroyAndNullHandle(dfn.vkFreeMemory, device,
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#include "xenia/gpu/shared_memory.h"
|
||||
#include "xenia/gpu/trace_writer.h"
|
||||
#include "xenia/memory.h"
|
||||
#include "xenia/ui/vulkan/vulkan_provider.h"
|
||||
#include "xenia/ui/vulkan/vulkan_upload_buffer_pool.h"
|
||||
|
||||
namespace xe {
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "xenia/gpu/texture_util.h"
|
||||
#include "xenia/gpu/vulkan/deferred_command_buffer.h"
|
||||
#include "xenia/gpu/vulkan/vulkan_command_processor.h"
|
||||
#include "xenia/ui/vulkan/ui_samplers.h"
|
||||
#include "xenia/ui/vulkan/vulkan_mem_alloc.h"
|
||||
#include "xenia/ui/vulkan/vulkan_util.h"
|
||||
|
||||
@@ -419,10 +420,10 @@ constexpr VulkanTextureCache::HostFormatPair
|
||||
true};
|
||||
|
||||
VulkanTextureCache::~VulkanTextureCache() {
|
||||
const ui::vulkan::VulkanProvider& provider =
|
||||
command_processor_.GetVulkanProvider();
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||
VkDevice device = provider.device();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device =
|
||||
command_processor_.GetVulkanDevice();
|
||||
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
|
||||
const VkDevice device = vulkan_device->device();
|
||||
|
||||
for (const std::pair<const SamplerParameters, Sampler>& sampler_pair :
|
||||
samplers_) {
|
||||
@@ -519,9 +520,9 @@ void VulkanTextureCache::BeginSubmission(uint64_t new_submission_index) {
|
||||
}
|
||||
|
||||
void VulkanTextureCache::RequestTextures(uint32_t used_texture_mask) {
|
||||
#if XE_UI_VULKAN_FINE_GRAINED_DRAW_SCOPES
|
||||
#if XE_GPU_FINE_GRAINED_DRAW_SCOPES
|
||||
SCOPE_profile_cpu_f("gpu");
|
||||
#endif // XE_UI_VULKAN_FINE_GRAINED_DRAW_SCOPES
|
||||
#endif // XE_GPU_FINE_GRAINED_DRAW_SCOPES
|
||||
|
||||
TextureCache::RequestTextures(used_texture_mask);
|
||||
|
||||
@@ -714,10 +715,10 @@ VkSampler VulkanTextureCache::UseSampler(SamplerParameters parameters,
|
||||
return sampler.second.sampler;
|
||||
}
|
||||
|
||||
const ui::vulkan::VulkanProvider& provider =
|
||||
command_processor_.GetVulkanProvider();
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||
VkDevice device = provider.device();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device =
|
||||
command_processor_.GetVulkanDevice();
|
||||
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
|
||||
const VkDevice device = vulkan_device->device();
|
||||
|
||||
// See if an existing sampler can be destroyed to create space for the new
|
||||
// one.
|
||||
@@ -757,7 +758,7 @@ VkSampler VulkanTextureCache::UseSampler(SamplerParameters parameters,
|
||||
// GetSamplerParameters.
|
||||
VkSamplerCreateInfo sampler_create_info = {};
|
||||
sampler_create_info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
|
||||
if (provider.device_info().nonSeamlessCubeMap &&
|
||||
if (vulkan_device->properties().nonSeamlessCubeMap &&
|
||||
cvars::non_seamless_cube_map) {
|
||||
sampler_create_info.flags |=
|
||||
VK_SAMPLER_CREATE_NON_SEAMLESS_CUBE_MAP_BIT_EXT;
|
||||
@@ -936,17 +937,17 @@ uint32_t VulkanTextureCache::GetHostFormatSwizzle(TextureKey key) const {
|
||||
|
||||
uint32_t VulkanTextureCache::GetMaxHostTextureWidthHeight(
|
||||
xenos::DataDimension dimension) const {
|
||||
const ui::vulkan::VulkanProvider::DeviceInfo& device_info =
|
||||
command_processor_.GetVulkanProvider().device_info();
|
||||
const ui::vulkan::VulkanDevice::Properties& device_properties =
|
||||
command_processor_.GetVulkanDevice()->properties();
|
||||
switch (dimension) {
|
||||
case xenos::DataDimension::k1D:
|
||||
case xenos::DataDimension::k2DOrStacked:
|
||||
// 1D and 2D are emulated as 2D arrays.
|
||||
return device_info.maxImageDimension2D;
|
||||
return device_properties.maxImageDimension2D;
|
||||
case xenos::DataDimension::k3D:
|
||||
return device_info.maxImageDimension3D;
|
||||
return device_properties.maxImageDimension3D;
|
||||
case xenos::DataDimension::kCube:
|
||||
return device_info.maxImageDimensionCube;
|
||||
return device_properties.maxImageDimensionCube;
|
||||
default:
|
||||
assert_unhandled_case(dimension);
|
||||
return 0;
|
||||
@@ -955,15 +956,15 @@ uint32_t VulkanTextureCache::GetMaxHostTextureWidthHeight(
|
||||
|
||||
uint32_t VulkanTextureCache::GetMaxHostTextureDepthOrArraySize(
|
||||
xenos::DataDimension dimension) const {
|
||||
const ui::vulkan::VulkanProvider::DeviceInfo& device_info =
|
||||
command_processor_.GetVulkanProvider().device_info();
|
||||
const ui::vulkan::VulkanDevice::Properties& device_properties =
|
||||
command_processor_.GetVulkanDevice()->properties();
|
||||
switch (dimension) {
|
||||
case xenos::DataDimension::k1D:
|
||||
case xenos::DataDimension::k2DOrStacked:
|
||||
// 1D and 2D are emulated as 2D arrays.
|
||||
return device_info.maxImageArrayLayers;
|
||||
return device_properties.maxImageArrayLayers;
|
||||
case xenos::DataDimension::k3D:
|
||||
return device_info.maxImageDimension3D;
|
||||
return device_properties.maxImageDimension3D;
|
||||
case xenos::DataDimension::kCube:
|
||||
// Not requesting the imageCubeArray feature, and the Xenos doesn't
|
||||
// support cube map arrays.
|
||||
@@ -1005,10 +1006,10 @@ std::unique_ptr<TextureCache::Texture> VulkanTextureCache::CreateTexture(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const ui::vulkan::VulkanProvider& provider =
|
||||
command_processor_.GetVulkanProvider();
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||
VkDevice device = provider.device();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device =
|
||||
command_processor_.GetVulkanDevice();
|
||||
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
|
||||
const VkDevice device = vulkan_device->device();
|
||||
|
||||
bool is_3d = key.dimension == xenos::DataDimension::k3D;
|
||||
uint32_t depth_or_array_size = key.GetDepthOrArraySize();
|
||||
@@ -1045,7 +1046,7 @@ std::unique_ptr<TextureCache::Texture> VulkanTextureCache::CreateTexture(
|
||||
image_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
VkImageFormatListCreateInfo image_format_list_create_info;
|
||||
if (formats[1] != VK_FORMAT_UNDEFINED &&
|
||||
provider.device_info().ext_1_2_VK_KHR_image_format_list) {
|
||||
vulkan_device->extensions().ext_1_2_KHR_image_format_list) {
|
||||
image_create_info_last->pNext = &image_format_list_create_info;
|
||||
image_create_info_last =
|
||||
reinterpret_cast<VkImageCreateInfo*>(&image_format_list_create_info);
|
||||
@@ -1220,10 +1221,10 @@ bool VulkanTextureCache::LoadTextureDataFromResidentMemoryImpl(Texture& texture,
|
||||
// Begin loading.
|
||||
// TODO(Triang3l): Going from one descriptor to another on per-array-layer
|
||||
// or even per-8-depth-slices level to stay within maxStorageBufferRange.
|
||||
const ui::vulkan::VulkanProvider& provider =
|
||||
command_processor_.GetVulkanProvider();
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||
VkDevice device = provider.device();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device =
|
||||
command_processor_.GetVulkanDevice();
|
||||
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
|
||||
const VkDevice device = vulkan_device->device();
|
||||
VulkanSharedMemory& vulkan_shared_memory =
|
||||
static_cast<VulkanSharedMemory&>(shared_memory());
|
||||
std::array<VkWriteDescriptorSet, 3> write_descriptor_sets;
|
||||
@@ -1586,10 +1587,10 @@ VulkanTextureCache::VulkanTexture::VulkanTexture(
|
||||
VulkanTextureCache::VulkanTexture::~VulkanTexture() {
|
||||
const VulkanTextureCache& vulkan_texture_cache =
|
||||
static_cast<const VulkanTextureCache&>(texture_cache());
|
||||
const ui::vulkan::VulkanProvider& provider =
|
||||
vulkan_texture_cache.command_processor_.GetVulkanProvider();
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||
VkDevice device = provider.device();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device =
|
||||
vulkan_texture_cache.command_processor_.GetVulkanDevice();
|
||||
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
|
||||
const VkDevice device = vulkan_device->device();
|
||||
for (const auto& view_pair : views_) {
|
||||
dfn.vkDestroyImageView(device, view_pair.second, nullptr);
|
||||
}
|
||||
@@ -1627,9 +1628,10 @@ VkImageView VulkanTextureCache::VulkanTexture::GetView(bool is_signed,
|
||||
is_signed && (host_format_pair.format_signed.format !=
|
||||
host_format_pair.format_unsigned.format);
|
||||
|
||||
const ui::vulkan::VulkanProvider& provider =
|
||||
vulkan_texture_cache.command_processor_.GetVulkanProvider();
|
||||
if (!provider.device_info().imageViewFormatSwizzle) {
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device =
|
||||
vulkan_texture_cache.command_processor_.GetVulkanDevice();
|
||||
|
||||
if (!vulkan_device->properties().imageViewFormatSwizzle) {
|
||||
host_swizzle = xenos::XE_GPU_TEXTURE_SWIZZLE_RGBA;
|
||||
}
|
||||
view_key.host_swizzle = host_swizzle;
|
||||
@@ -1643,8 +1645,8 @@ VkImageView VulkanTextureCache::VulkanTexture::GetView(bool is_signed,
|
||||
}
|
||||
|
||||
// Create a new view.
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||
VkDevice device = provider.device();
|
||||
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
|
||||
const VkDevice device = vulkan_device->device();
|
||||
VkImageViewCreateInfo view_create_info;
|
||||
view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
view_create_info.pNext = nullptr;
|
||||
@@ -1700,18 +1702,19 @@ VulkanTextureCache::VulkanTextureCache(
|
||||
}
|
||||
|
||||
bool VulkanTextureCache::Initialize() {
|
||||
const ui::vulkan::VulkanProvider& provider =
|
||||
command_processor_.GetVulkanProvider();
|
||||
const ui::vulkan::VulkanProvider::InstanceFunctions& ifn = provider.ifn();
|
||||
VkPhysicalDevice physical_device = provider.physical_device();
|
||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||
VkDevice device = provider.device();
|
||||
const ui::vulkan::VulkanProvider::DeviceInfo& device_info =
|
||||
provider.device_info();
|
||||
const ui::vulkan::VulkanDevice* const vulkan_device =
|
||||
command_processor_.GetVulkanDevice();
|
||||
const ui::vulkan::VulkanInstance::Functions& ifn =
|
||||
vulkan_device->vulkan_instance()->functions();
|
||||
const VkPhysicalDevice physical_device = vulkan_device->physical_device();
|
||||
const ui::vulkan::VulkanDevice::Functions& dfn = vulkan_device->functions();
|
||||
const VkDevice device = vulkan_device->device();
|
||||
const ui::vulkan::VulkanDevice::Properties& device_properties =
|
||||
vulkan_device->properties();
|
||||
|
||||
// Vulkan Memory Allocator.
|
||||
|
||||
vma_allocator_ = ui::vulkan::CreateVmaAllocator(provider, true);
|
||||
vma_allocator_ = ui::vulkan::CreateVmaAllocator(vulkan_device, true);
|
||||
if (vma_allocator_ == VK_NULL_HANDLE) {
|
||||
return false;
|
||||
}
|
||||
@@ -2319,7 +2322,7 @@ bool VulkanTextureCache::Initialize() {
|
||||
load_shader_code[i];
|
||||
assert_not_null(current_load_shader_code.first);
|
||||
load_pipelines_[i] = ui::vulkan::util::CreateComputePipeline(
|
||||
provider, load_pipeline_layout_, current_load_shader_code.first,
|
||||
vulkan_device, load_pipeline_layout_, current_load_shader_code.first,
|
||||
current_load_shader_code.second);
|
||||
if (load_pipelines_[i] == VK_NULL_HANDLE) {
|
||||
XELOGE(
|
||||
@@ -2333,7 +2336,7 @@ bool VulkanTextureCache::Initialize() {
|
||||
current_load_shader_code_scaled = load_shader_code_scaled[i];
|
||||
if (current_load_shader_code_scaled.first) {
|
||||
load_pipelines_scaled_[i] = ui::vulkan::util::CreateComputePipeline(
|
||||
provider, load_pipeline_layout_,
|
||||
vulkan_device, load_pipeline_layout_,
|
||||
current_load_shader_code_scaled.first,
|
||||
current_load_shader_code_scaled.second);
|
||||
if (load_pipelines_scaled_[i] == VK_NULL_HANDLE) {
|
||||
@@ -2398,7 +2401,7 @@ bool VulkanTextureCache::Initialize() {
|
||||
dfn.vkGetImageMemoryRequirements(device, null_image_3d_,
|
||||
&null_image_memory_requirements_3d_);
|
||||
uint32_t null_image_memory_type_common = ui::vulkan::util::ChooseMemoryType(
|
||||
provider,
|
||||
vulkan_device->memory_types(),
|
||||
null_image_memory_requirements_2d_array_cube_.memoryTypeBits &
|
||||
null_image_memory_requirements_3d_.memoryTypeBits,
|
||||
ui::vulkan::util::MemoryPurpose::kDeviceLocal);
|
||||
@@ -2439,16 +2442,18 @@ bool VulkanTextureCache::Initialize() {
|
||||
}
|
||||
} else {
|
||||
// Place each null image in separate allocations.
|
||||
uint32_t null_image_memory_type_2d_array_cube_ =
|
||||
const uint32_t null_image_memory_type_2d_array_cube =
|
||||
ui::vulkan::util::ChooseMemoryType(
|
||||
provider,
|
||||
vulkan_device->memory_types(),
|
||||
null_image_memory_requirements_2d_array_cube_.memoryTypeBits,
|
||||
ui::vulkan::util::MemoryPurpose::kDeviceLocal);
|
||||
uint32_t null_image_memory_type_3d_ = ui::vulkan::util::ChooseMemoryType(
|
||||
provider, null_image_memory_requirements_3d_.memoryTypeBits,
|
||||
ui::vulkan::util::MemoryPurpose::kDeviceLocal);
|
||||
if (null_image_memory_type_2d_array_cube_ == UINT32_MAX ||
|
||||
null_image_memory_type_3d_ == UINT32_MAX) {
|
||||
const uint32_t null_image_memory_type_3d =
|
||||
ui::vulkan::util::ChooseMemoryType(
|
||||
vulkan_device->memory_types(),
|
||||
null_image_memory_requirements_3d_.memoryTypeBits,
|
||||
ui::vulkan::util::MemoryPurpose::kDeviceLocal);
|
||||
if (null_image_memory_type_2d_array_cube == UINT32_MAX ||
|
||||
null_image_memory_type_3d == UINT32_MAX) {
|
||||
XELOGE(
|
||||
"VulkanTextureCache: Failed to get the memory types for the null "
|
||||
"images");
|
||||
@@ -2464,9 +2469,9 @@ bool VulkanTextureCache::Initialize() {
|
||||
null_image_memory_allocate_info.allocationSize =
|
||||
null_image_memory_requirements_2d_array_cube_.size;
|
||||
null_image_memory_allocate_info.memoryTypeIndex =
|
||||
null_image_memory_type_2d_array_cube_;
|
||||
null_image_memory_type_2d_array_cube;
|
||||
VkMemoryDedicatedAllocateInfo null_image_memory_dedicated_allocate_info;
|
||||
if (device_info.ext_1_1_VK_KHR_dedicated_allocation) {
|
||||
if (vulkan_device->extensions().ext_1_1_KHR_dedicated_allocation) {
|
||||
null_image_memory_allocate_info_last->pNext =
|
||||
&null_image_memory_dedicated_allocate_info;
|
||||
null_image_memory_allocate_info_last =
|
||||
@@ -2496,8 +2501,7 @@ bool VulkanTextureCache::Initialize() {
|
||||
|
||||
null_image_memory_allocate_info.allocationSize =
|
||||
null_image_memory_requirements_3d_.size;
|
||||
null_image_memory_allocate_info.memoryTypeIndex =
|
||||
null_image_memory_type_3d_;
|
||||
null_image_memory_allocate_info.memoryTypeIndex = null_image_memory_type_3d;
|
||||
null_image_memory_dedicated_allocate_info.image = null_image_3d_;
|
||||
if (dfn.vkAllocateMemory(device, &null_image_memory_allocate_info, nullptr,
|
||||
&null_images_memory_[1]) != VK_SUCCESS) {
|
||||
@@ -2527,8 +2531,8 @@ bool VulkanTextureCache::Initialize() {
|
||||
// constant components instead of the real texels. The image will be cleared
|
||||
// to (0, 0, 0, 0) anyway.
|
||||
VkComponentSwizzle null_image_view_swizzle =
|
||||
device_info.imageViewFormatSwizzle ? VK_COMPONENT_SWIZZLE_ZERO
|
||||
: VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
device_properties.imageViewFormatSwizzle ? VK_COMPONENT_SWIZZLE_ZERO
|
||||
: VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
null_image_view_create_info.components.r = null_image_view_swizzle;
|
||||
null_image_view_create_info.components.g = null_image_view_swizzle;
|
||||
null_image_view_create_info.components.b = null_image_view_swizzle;
|
||||
@@ -2567,15 +2571,15 @@ bool VulkanTextureCache::Initialize() {
|
||||
// VkDevice (true in a regular emulation scenario), so taking over all the
|
||||
// allocation slots exclusively.
|
||||
// Also leaving a few slots for use by things like overlay applications.
|
||||
sampler_max_count_ =
|
||||
device_info.maxSamplerAllocationCount -
|
||||
uint32_t(ui::vulkan::VulkanProvider::HostSampler::kCount) - 16;
|
||||
sampler_max_count_ = device_properties.maxSamplerAllocationCount -
|
||||
ui::vulkan::UISamplers::kSamplerCount - 16;
|
||||
|
||||
if (device_info.samplerAnisotropy) {
|
||||
if (device_properties.samplerAnisotropy) {
|
||||
max_anisotropy_ = xenos::AnisoFilter(
|
||||
uint32_t(xenos::AnisoFilter::kMax_1_1) +
|
||||
(31 - xe::lzcnt(uint32_t(std::min(
|
||||
16.0f, std::max(1.0f, device_info.maxSamplerAnisotropy))))));
|
||||
(31 -
|
||||
xe::lzcnt(uint32_t(std::min(
|
||||
16.0f, std::max(1.0f, device_properties.maxSamplerAnisotropy))))));
|
||||
} else {
|
||||
max_anisotropy_ = xenos::AnisoFilter::kDisabled;
|
||||
}
|
||||
@@ -2639,8 +2643,8 @@ xenos::ClampMode VulkanTextureCache::NormalizeClampMode(
|
||||
clamp_mode == xenos::ClampMode::kMirrorClampToHalfway ||
|
||||
clamp_mode == xenos::ClampMode::kMirrorClampToBorder) {
|
||||
// No equivalents for anything other than kMirrorClampToEdge in Vulkan.
|
||||
return command_processor_.GetVulkanProvider()
|
||||
.device_info()
|
||||
return command_processor_.GetVulkanDevice()
|
||||
->properties()
|
||||
.samplerMirrorClampToEdge
|
||||
? xenos::ClampMode::kMirrorClampToEdge
|
||||
: xenos::ClampMode::kMirroredRepeat;
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "xenia/gpu/vulkan/vulkan_shader.h"
|
||||
#include "xenia/gpu/vulkan/vulkan_shared_memory.h"
|
||||
#include "xenia/ui/vulkan/vulkan_mem_alloc.h"
|
||||
#include "xenia/ui/vulkan/vulkan_provider.h"
|
||||
|
||||
namespace xe {
|
||||
namespace gpu {
|
||||
|
||||
@@ -27,24 +27,24 @@ class VulkanTraceDump : public TraceDump {
|
||||
}
|
||||
|
||||
void BeginHostCapture() override {
|
||||
const RENDERDOC_API_1_0_0* renderdoc_api =
|
||||
const ui::RenderDocAPI* const renderdoc_api =
|
||||
static_cast<const ui::vulkan::VulkanProvider*>(
|
||||
graphics_system_->provider())
|
||||
->renderdoc_api()
|
||||
.api_1_0_0();
|
||||
if (renderdoc_api && !renderdoc_api->IsFrameCapturing()) {
|
||||
renderdoc_api->StartFrameCapture(nullptr, nullptr);
|
||||
->vulkan_instance()
|
||||
->renderdoc_api();
|
||||
if (renderdoc_api && !renderdoc_api->api_1_0_0()->IsFrameCapturing()) {
|
||||
renderdoc_api->api_1_0_0()->StartFrameCapture(nullptr, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void EndHostCapture() override {
|
||||
const RENDERDOC_API_1_0_0* renderdoc_api =
|
||||
const ui::RenderDocAPI* const renderdoc_api =
|
||||
static_cast<const ui::vulkan::VulkanProvider*>(
|
||||
graphics_system_->provider())
|
||||
->renderdoc_api()
|
||||
.api_1_0_0();
|
||||
if (renderdoc_api && renderdoc_api->IsFrameCapturing()) {
|
||||
renderdoc_api->EndFrameCapture(nullptr, nullptr);
|
||||
->vulkan_instance()
|
||||
->renderdoc_api();
|
||||
if (renderdoc_api && renderdoc_api->api_1_0_0()->IsFrameCapturing()) {
|
||||
renderdoc_api->api_1_0_0()->EndFrameCapture(nullptr, nullptr);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user