[Vulkan] Refactoring and fixes for VulkanProvider and related areas
Enable portability subset physical device enumeration. Don't use Vulkan 1.1+ logical devices on Vulkan 1.0 instances due to the VkApplicationInfo::apiVersion specification. Make sure all extension dependencies are enabled when creating a device. Prefer exposing feature support over extension support via the device interface to avoid causing confusion with regard to promoted extensions (especially those that required some features as extensions, but had those features made optional when they were promoted). Allow creating presentation-only devices, not demanding any optional features beyond the basic Vulkan 1.0, for use cases such as internal tools or CPU rendering. Require the independentBlend feature for GPU emulation as working around is complicated, while support is almost ubiquitous. Move the graphics system initialization fatal error message to xenia_main after attempting to initialize all implementations, for automatic fallback to other implementations in the future. Log Vulkan driver info. Improve Vulkan debug message logging, enabled by default. Refactor code, with simplified logic for enabling extensions and layers.
This commit is contained in:
@@ -16,6 +16,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 {
|
||||
@@ -31,12 +32,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 {
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
#include "xenia/gpu/vulkan/vulkan_shared_memory.h"
|
||||
#include "xenia/gpu/xenos.h"
|
||||
#include "xenia/ui/vulkan/vulkan_presenter.h"
|
||||
#include "xenia/ui/vulkan/vulkan_provider.h"
|
||||
#include "xenia/ui/vulkan/vulkan_util.h"
|
||||
|
||||
namespace xe {
|
||||
@@ -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();
|
||||
|
||||
@@ -1289,9 +1293,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);
|
||||
@@ -1358,7 +1363,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,
|
||||
@@ -1816,9 +1821,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;
|
||||
@@ -1863,9 +1868,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);
|
||||
@@ -1959,9 +1964,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 =
|
||||
@@ -2019,14 +2024,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)) {
|
||||
@@ -2037,8 +2042,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);
|
||||
}
|
||||
@@ -2153,9 +2158,9 @@ 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_;
|
||||
|
||||
@@ -2165,8 +2170,8 @@ bool VulkanCommandProcessor::IssueDraw(xenos::PrimitiveType prim_type,
|
||||
return IssueCopy();
|
||||
}
|
||||
|
||||
const ui::vulkan::VulkanProvider::DeviceInfo& device_info =
|
||||
GetVulkanProvider().device_info();
|
||||
const ui::vulkan::VulkanDevice::Properties& device_properties =
|
||||
GetVulkanDevice()->properties();
|
||||
|
||||
memexport_ranges_.clear();
|
||||
|
||||
@@ -2182,7 +2187,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_);
|
||||
}
|
||||
|
||||
@@ -2213,7 +2218,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_);
|
||||
}
|
||||
|
||||
@@ -2453,9 +2458,9 @@ bool VulkanCommandProcessor::IssueDraw(xenos::PrimitiveType prim_type,
|
||||
// interlocks case completely - apply the viewport and the scissor offset
|
||||
// directly to pixel address and to things like ps_param_gen.
|
||||
draw_util::GetHostViewportInfo(
|
||||
regs, 1, 1, false, device_info.maxViewportDimensions[0],
|
||||
device_info.maxViewportDimensions[1], true, normalized_depth_control,
|
||||
false, host_render_targets_used,
|
||||
regs, 1, 1, false, device_properties.maxViewportDimensions[0],
|
||||
device_properties.maxViewportDimensions[1], true,
|
||||
normalized_depth_control, false, host_render_targets_used,
|
||||
pixel_shader && pixel_shader->writes_depth(), viewport_info);
|
||||
|
||||
// Update dynamic graphics pipeline state.
|
||||
@@ -2468,7 +2473,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 &&
|
||||
@@ -2619,9 +2624,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;
|
||||
@@ -2672,9 +2677,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;
|
||||
@@ -2787,9 +2792,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;
|
||||
@@ -2935,9 +2940,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_) {
|
||||
@@ -2977,7 +2982,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");
|
||||
@@ -3053,10 +3058,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");
|
||||
@@ -3123,10 +3129,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");
|
||||
@@ -3235,9 +3242,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;
|
||||
@@ -3252,9 +3259,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_;
|
||||
|
||||
@@ -3358,7 +3365,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 {
|
||||
@@ -3475,9 +3482,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>();
|
||||
@@ -3719,7 +3726,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)) {
|
||||
@@ -3935,15 +3942,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.
|
||||
|
||||
@@ -4002,7 +4009,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))) {
|
||||
@@ -4376,10 +4383,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;
|
||||
@@ -4409,9 +4415,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;
|
||||
|
||||
@@ -143,9 +143,10 @@ class VulkanCommandProcessor : 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;
|
||||
|
||||
@@ -51,15 +51,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);
|
||||
@@ -68,7 +68,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());
|
||||
@@ -85,10 +85,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;
|
||||
@@ -136,7 +136,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;
|
||||
@@ -268,9 +268,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)) {
|
||||
@@ -471,8 +471,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 =
|
||||
@@ -512,8 +512,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>();
|
||||
@@ -548,7 +548,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:
|
||||
@@ -572,7 +572,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);
|
||||
@@ -587,7 +588,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 =
|
||||
@@ -604,7 +605,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;
|
||||
@@ -671,83 +672,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]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -767,65 +702,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;
|
||||
@@ -1849,10 +1756,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(
|
||||
@@ -1892,10 +1798,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() ==
|
||||
@@ -2174,6 +2078,7 @@ bool VulkanPipelineCache::EnsurePipelineCreated(
|
||||
VK_BLEND_OP_ADD,
|
||||
VK_BLEND_OP_ADD,
|
||||
VK_BLEND_OP_ADD};
|
||||
assert_true(vulkan_device->properties().independentBlend);
|
||||
uint32_t color_rts_remaining = color_rts_used;
|
||||
uint32_t color_rt_index;
|
||||
while (xe::bit_scan_forward(color_rts_remaining, &color_rt_index)) {
|
||||
@@ -2204,28 +2109,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;
|
||||
@@ -2276,8 +2163,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 {
|
||||
|
||||
@@ -17,7 +17,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 {
|
||||
@@ -27,29 +26,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();
|
||||
@@ -71,10 +71,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,
|
||||
@@ -131,14 +131,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_)) {
|
||||
@@ -150,7 +150,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_,
|
||||
@@ -185,7 +185,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 {
|
||||
|
||||
@@ -207,14 +207,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;
|
||||
@@ -243,13 +244,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;
|
||||
}
|
||||
}
|
||||
@@ -271,17 +272,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;
|
||||
@@ -349,19 +351,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 |
|
||||
@@ -498,7 +500,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
|
||||
@@ -511,7 +513,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;
|
||||
}
|
||||
@@ -569,7 +571,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(
|
||||
@@ -585,7 +587,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 *
|
||||
@@ -593,7 +595,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(
|
||||
@@ -757,7 +759,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)
|
||||
@@ -770,7 +772,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)
|
||||
@@ -838,10 +840,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) {
|
||||
@@ -873,10 +875,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,
|
||||
@@ -985,10 +987,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.
|
||||
@@ -1044,10 +1046,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();
|
||||
|
||||
@@ -1554,10 +1556,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) {
|
||||
@@ -1644,10 +1646,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_
|
||||
@@ -1671,25 +1673,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.
|
||||
|
||||
@@ -1745,7 +1747,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 "
|
||||
@@ -2071,12 +2073,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) {
|
||||
@@ -2125,9 +2127,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;
|
||||
@@ -2150,10 +2152,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;
|
||||
@@ -2241,7 +2243,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;
|
||||
@@ -2477,7 +2479,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(
|
||||
@@ -2571,7 +2573,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,
|
||||
@@ -4194,7 +4196,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(
|
||||
@@ -4225,17 +4227,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;
|
||||
@@ -4327,7 +4329,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_) {
|
||||
@@ -4358,7 +4360,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;
|
||||
@@ -4386,21 +4388,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;
|
||||
@@ -4493,8 +4484,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();
|
||||
@@ -4809,7 +4800,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));
|
||||
@@ -5001,10 +4993,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);
|
||||
@@ -5055,7 +5047,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 =
|
||||
@@ -5922,7 +5914,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 {
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "xenia/base/assert.h"
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/ui/vulkan/vulkan_provider.h"
|
||||
|
||||
@@ -20,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,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;
|
||||
@@ -43,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}",
|
||||
@@ -56,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;
|
||||
|
||||
@@ -47,12 +47,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 |
|
||||
@@ -70,14 +68,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(
|
||||
@@ -130,7 +129,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 "
|
||||
@@ -147,7 +146,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 =
|
||||
@@ -183,7 +182,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()));
|
||||
|
||||
@@ -195,10 +194,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_) {
|
||||
@@ -260,10 +259,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_)) {
|
||||
@@ -306,10 +304,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) {
|
||||
@@ -335,10 +333,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;
|
||||
@@ -365,7 +363,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;
|
||||
}
|
||||
@@ -482,10 +480,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 {
|
||||
|
||||
@@ -22,6 +22,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"
|
||||
|
||||
@@ -423,10 +424,10 @@ const 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_) {
|
||||
@@ -523,9 +524,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);
|
||||
|
||||
@@ -718,10 +719,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.
|
||||
@@ -761,7 +762,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;
|
||||
@@ -940,17 +941,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;
|
||||
@@ -959,15 +960,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.
|
||||
@@ -1009,10 +1010,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();
|
||||
@@ -1049,7 +1050,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);
|
||||
@@ -1224,10 +1225,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;
|
||||
@@ -1590,10 +1591,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);
|
||||
}
|
||||
@@ -1631,9 +1632,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;
|
||||
@@ -1647,8 +1649,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;
|
||||
@@ -1704,18 +1706,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;
|
||||
}
|
||||
@@ -2323,7 +2326,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(
|
||||
@@ -2337,7 +2340,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) {
|
||||
@@ -2402,7 +2405,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);
|
||||
@@ -2443,16 +2446,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");
|
||||
@@ -2468,9 +2473,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 =
|
||||
@@ -2500,8 +2505,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) {
|
||||
@@ -2531,8 +2535,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;
|
||||
@@ -2571,15 +2575,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;
|
||||
}
|
||||
@@ -2643,8 +2647,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