Merge branch 'master' of https://github.com/xenia-project/xenia into canary_experimental

This commit is contained in:
Gliniak
2022-07-10 10:50:39 +02:00
49 changed files with 2378 additions and 1159 deletions

View File

@@ -497,7 +497,7 @@ class D3D12RenderTargetCache final : public RenderTargetCache {
TransferInvocation(const Transfer& transfer,
const TransferShaderKey& shader_key)
: transfer(transfer), shader_key(shader_key) {}
bool operator<(const TransferInvocation& other_invocation) {
bool operator<(const TransferInvocation& other_invocation) const {
// TODO(Triang3l): See if it may be better to sort by the source in the
// first place, especially when reading the same data multiple times (like
// to write the stencil bits after depth) for better read locality.
@@ -639,7 +639,7 @@ class D3D12RenderTargetCache final : public RenderTargetCache {
DumpInvocation(const ResolveCopyDumpRectangle& rectangle,
const DumpPipelineKey& pipeline_key)
: rectangle(rectangle), pipeline_key(pipeline_key) {}
bool operator<(const DumpInvocation& other_invocation) {
bool operator<(const DumpInvocation& other_invocation) const {
// Sort by the pipeline key primarily to reduce pipeline state (context)
// switches.
if (pipeline_key != other_invocation.pipeline_key) {

View File

@@ -30,7 +30,6 @@ project("xenia-gpu-d3d12-trace-viewer")
"xenia-base",
"xenia-core",
"xenia-cpu",
"xenia-cpu-backend-x64",
"xenia-gpu",
"xenia-gpu-d3d12",
"xenia-hid",
@@ -68,6 +67,11 @@ project("xenia-gpu-d3d12-trace-viewer")
})
end
filter("architecture:x86_64")
links({
"xenia-cpu-backend-x64",
})
group("src")
project("xenia-gpu-d3d12-trace-dump")
uuid("686b859c-0046-44c4-a02c-41fc3fb75698")
@@ -79,7 +83,6 @@ project("xenia-gpu-d3d12-trace-dump")
"xenia-base",
"xenia-core",
"xenia-cpu",
"xenia-cpu-backend-x64",
"xenia-gpu",
"xenia-gpu-d3d12",
"xenia-hid",
@@ -115,3 +118,8 @@ project("xenia-gpu-d3d12-trace-dump")
"1>scratch/stdout-trace-dump.txt",
})
end
filter("architecture:x86_64")
links({
"xenia-cpu-backend-x64",
})

View File

@@ -942,7 +942,7 @@ void PrimitiveProcessor::Get16BitResetIndexUsage(
is_ffff_simd =
_mm_or_si128(is_ffff_simd, _mm_cmpeq_epi16(source_simd, ffff_simd));
#elif XE_ARCH_ARM64
is_reset_simd = vcorrq_u16(
is_reset_simd = vorrq_u16(
is_reset_simd, vceqq_u16(source_simd, reset_index_guest_endian_simd));
is_ffff_simd = vmaxq_u16(is_ffff_simd, source_simd);
#else

View File

@@ -374,8 +374,14 @@ void RenderTargetCache::InitializeCommon() {
RenderTargetKey(), RenderTargetKey()));
}
void RenderTargetCache::ShutdownCommon() {
void RenderTargetCache::DestroyAllRenderTargets(bool shutting_down) {
ownership_ranges_.clear();
if (!shutting_down) {
ownership_ranges_.emplace(
std::piecewise_construct, std::forward_as_tuple(uint32_t(0)),
std::forward_as_tuple(xenos::kEdramTileCount, RenderTargetKey(),
RenderTargetKey(), RenderTargetKey()));
}
for (const auto& render_target_pair : render_targets_) {
if (render_target_pair.second) {
@@ -385,6 +391,8 @@ void RenderTargetCache::ShutdownCommon() {
render_targets_.clear();
}
void RenderTargetCache::ShutdownCommon() { DestroyAllRenderTargets(true); }
void RenderTargetCache::ClearCache() {
// Keep only render targets currently owning any EDRAM data.
if (!render_targets_.empty()) {

View File

@@ -193,6 +193,10 @@ class RenderTargetCache {
// Call last in implementation-specific initialization (when things like path
// are initialized by the implementation).
void InitializeCommon();
// May be called from the destructor, or from the implementation shutdown to
// destroy all render targets before destroying what they depend on in the
// implementation.
void DestroyAllRenderTargets(bool shutting_down);
// Call last in implementation-specific shutdown, also callable from the
// destructor.
void ShutdownCommon();

View File

@@ -75,9 +75,6 @@ SpirvShaderTranslator::Features::Features(
}
}
const std::string SpirvShaderTranslator::kInterpolatorNamePrefix =
"xe_interpolator_";
SpirvShaderTranslator::SpirvShaderTranslator(const Features& features)
: features_(features) {}
@@ -164,6 +161,8 @@ void SpirvShaderTranslator::StartTranslation() {
type_float2_ = builder_->makeVectorType(type_float_, 2);
type_float3_ = builder_->makeVectorType(type_float_, 3);
type_float4_ = builder_->makeVectorType(type_float_, 4);
type_interpolators_ = builder_->makeArrayType(
type_float4_, builder_->makeUintConstant(xenos::kMaxInterpolators), 0);
const_int_0_ = builder_->makeIntConstant(0);
id_vector_temp_.clear();
@@ -257,8 +256,9 @@ void SpirvShaderTranslator::StartTranslation() {
"xe_uniform_system_constants");
builder_->addDecoration(uniform_system_constants_,
spv::DecorationDescriptorSet,
kDescriptorSetSystemConstants);
builder_->addDecoration(uniform_system_constants_, spv::DecorationBinding, 0);
int(kDescriptorSetConstants));
builder_->addDecoration(uniform_system_constants_, spv::DecorationBinding,
int(kConstantBufferSystem));
if (features_.spirv_version >= spv::Spv_1_4) {
main_interface_.push_back(uniform_system_constants_);
}
@@ -285,12 +285,13 @@ void SpirvShaderTranslator::StartTranslation() {
uniform_float_constants_ = builder_->createVariable(
spv::NoPrecision, spv::StorageClassUniform, type_float_constants,
"xe_uniform_float_constants");
builder_->addDecoration(uniform_float_constants_,
spv::DecorationDescriptorSet,
int(kDescriptorSetConstants));
builder_->addDecoration(
uniform_float_constants_, spv::DecorationDescriptorSet,
int(is_pixel_shader() ? kDescriptorSetFloatConstantsPixel
: kDescriptorSetFloatConstantsVertex));
builder_->addDecoration(uniform_float_constants_, spv::DecorationBinding,
0);
uniform_float_constants_, spv::DecorationBinding,
int(is_pixel_shader() ? kConstantBufferFloatPixel
: kConstantBufferFloatVertex));
if (features_.spirv_version >= spv::Spv_1_4) {
main_interface_.push_back(uniform_float_constants_);
}
@@ -326,9 +327,9 @@ void SpirvShaderTranslator::StartTranslation() {
"xe_uniform_bool_loop_constants");
builder_->addDecoration(uniform_bool_loop_constants_,
spv::DecorationDescriptorSet,
int(kDescriptorSetBoolLoopConstants));
int(kDescriptorSetConstants));
builder_->addDecoration(uniform_bool_loop_constants_, spv::DecorationBinding,
0);
int(kConstantBufferBoolLoop));
if (features_.spirv_version >= spv::Spv_1_4) {
main_interface_.push_back(uniform_bool_loop_constants_);
}
@@ -352,8 +353,9 @@ void SpirvShaderTranslator::StartTranslation() {
"xe_uniform_fetch_constants");
builder_->addDecoration(uniform_fetch_constants_,
spv::DecorationDescriptorSet,
int(kDescriptorSetFetchConstants));
builder_->addDecoration(uniform_fetch_constants_, spv::DecorationBinding, 0);
int(kDescriptorSetConstants));
builder_->addDecoration(uniform_fetch_constants_, spv::DecorationBinding,
int(kConstantBufferFetch));
if (features_.spirv_version >= spv::Spv_1_4) {
main_interface_.push_back(uniform_fetch_constants_);
}
@@ -639,6 +641,16 @@ std::vector<uint8_t> SpirvShaderTranslator::CompleteTranslation() {
entry_point->addIdOperand(interface_id);
}
// Specify the binding indices for samplers when the number of textures is
// known, as samplers are located after images in the texture descriptor set.
size_t texture_binding_count = texture_bindings_.size();
size_t sampler_binding_count = sampler_bindings_.size();
for (size_t i = 0; i < sampler_binding_count; ++i) {
builder_->addDecoration(sampler_bindings_[i].variable,
spv::DecorationBinding,
int(texture_binding_count + i));
}
// TODO(Triang3l): Avoid copy?
std::vector<unsigned int> module_uints;
builder_->dump(module_uints);
@@ -1056,17 +1068,15 @@ void SpirvShaderTranslator::StartVertexOrTessEvalShaderBeforeMain() {
main_interface_.push_back(input_vertex_index_);
}
// Create the Xenia-specific outputs.
// TODO(Triang3l): Change to an interpolator array.
for (uint32_t i = 0; i < xenos::kMaxInterpolators; ++i) {
spv::Id interpolator = builder_->createVariable(
spv::NoPrecision, spv::StorageClassOutput, type_float4_,
(kInterpolatorNamePrefix + std::to_string(i)).c_str());
input_output_interpolators_[i] = interpolator;
builder_->addDecoration(interpolator, spv::DecorationLocation, int(i));
builder_->addDecoration(interpolator, spv::DecorationInvariant);
main_interface_.push_back(interpolator);
}
// Create the interpolator output.
input_output_interpolators_ =
builder_->createVariable(spv::NoPrecision, spv::StorageClassOutput,
type_interpolators_, "xe_out_interpolators");
builder_->addDecoration(input_output_interpolators_, spv::DecorationLocation,
0);
builder_->addDecoration(input_output_interpolators_,
spv::DecorationInvariant);
main_interface_.push_back(input_output_interpolators_);
// Create the gl_PerVertex output for used system outputs.
std::vector<spv::Id> struct_per_vertex_members;
@@ -1095,7 +1105,12 @@ void SpirvShaderTranslator::StartVertexOrTessEvalShaderInMain() {
// Zero the interpolators.
for (uint32_t i = 0; i < xenos::kMaxInterpolators; ++i) {
builder_->createStore(const_float4_0_, input_output_interpolators_[i]);
id_vector_temp_.clear();
id_vector_temp_.push_back(builder_->makeIntConstant(int(i)));
builder_->createStore(const_float4_0_,
builder_->createAccessChain(
spv::StorageClassOutput,
input_output_interpolators_, id_vector_temp_));
}
// Load the vertex index or the tessellation parameters.
@@ -1269,17 +1284,13 @@ void SpirvShaderTranslator::CompleteVertexOrTessEvalShaderInMain() {
}
void SpirvShaderTranslator::StartFragmentShaderBeforeMain() {
// Interpolator inputs.
uint32_t interpolator_count =
std::min(xenos::kMaxInterpolators, register_count());
for (uint32_t i = 0; i < interpolator_count; ++i) {
spv::Id interpolator = builder_->createVariable(
spv::NoPrecision, spv::StorageClassInput, type_float4_,
(kInterpolatorNamePrefix + std::to_string(i)).c_str());
input_output_interpolators_[i] = interpolator;
builder_->addDecoration(interpolator, spv::DecorationLocation, int(i));
main_interface_.push_back(interpolator);
}
// Interpolator input.
input_output_interpolators_ =
builder_->createVariable(spv::NoPrecision, spv::StorageClassInput,
type_interpolators_, "xe_in_interpolators");
builder_->addDecoration(input_output_interpolators_, spv::DecorationLocation,
0);
main_interface_.push_back(input_output_interpolators_);
bool param_gen_needed = GetPsParamGenInterpolator() != UINT32_MAX;
@@ -1347,7 +1358,10 @@ void SpirvShaderTranslator::StartFragmentShaderInMain() {
// Register array element.
id_vector_temp_.push_back(builder_->makeIntConstant(int(i)));
builder_->createStore(
builder_->createLoad(input_output_interpolators_[i], spv::NoPrecision),
builder_->createLoad(builder_->createAccessChain(
spv::StorageClassInput,
input_output_interpolators_, id_vector_temp_),
spv::NoPrecision),
builder_->createAccessChain(spv::StorageClassFunction,
var_main_registers_, id_vector_temp_));
}
@@ -1824,7 +1838,12 @@ void SpirvShaderTranslator::StoreResult(const InstructionResult& result,
} break;
case InstructionStorageTarget::kInterpolator:
assert_true(is_vertex_shader());
target_pointer = input_output_interpolators_[result.storage_index];
id_vector_temp_util_.clear();
id_vector_temp_util_.push_back(
builder_->makeIntConstant(int(result.storage_index)));
target_pointer = builder_->createAccessChain(spv::StorageClassOutput,
input_output_interpolators_,
id_vector_temp_util_);
break;
case InstructionStorageTarget::kPosition:
assert_true(is_vertex_shader());

View File

@@ -131,6 +131,16 @@ class SpirvShaderTranslator : public ShaderTranslator {
float color_exp_bias[4];
};
enum ConstantBuffer : uint32_t {
kConstantBufferSystem,
kConstantBufferFloatVertex,
kConstantBufferFloatPixel,
kConstantBufferBoolLoop,
kConstantBufferFetch,
kConstantBufferCount,
};
// The minimum limit for maxPerStageDescriptorStorageBuffers is 4, and for
// maxStorageBufferRange it's 128 MB. These are the values of those limits on
// Arm Mali as of November 2020. Xenia needs 512 MB shared memory to be bound,
@@ -159,31 +169,28 @@ class SpirvShaderTranslator : public ShaderTranslator {
// Never changed.
kDescriptorSetSharedMemoryAndEdram,
// Pretty rarely used and rarely changed - flow control constants.
kDescriptorSetBoolLoopConstants,
// May stay the same across many draws.
kDescriptorSetSystemConstants,
// Less frequently changed (per-material).
kDescriptorSetFloatConstantsPixel,
// Quite frequently changed (for one object drawn multiple times, for
// instance - may contain projection matrices).
kDescriptorSetFloatConstantsVertex,
// Very frequently changed, especially for UI draws, and for models drawn in
// multiple parts - contains vertex and texture fetch constants.
kDescriptorSetFetchConstants,
// Changed in case of changes in the data.
kDescriptorSetConstants,
// Mutable part of the pipeline layout:
kDescriptorSetMutableLayoutsStart,
// Rarely used at all, but may be changed at an unpredictable rate when
// vertex textures are used.
kDescriptorSetSamplersVertex = kDescriptorSetMutableLayoutsStart,
kDescriptorSetTexturesVertex,
// vertex textures are used (for example, for bones of an object, which may
// consist of multiple draw commands with different materials).
kDescriptorSetTexturesVertex = kDescriptorSetMutableLayoutsStart,
// Per-material textures.
kDescriptorSetSamplersPixel,
kDescriptorSetTexturesPixel,
kDescriptorSetCount,
};
static_assert(
kDescriptorSetCount <= 4,
"The number of descriptor sets used by translated shaders must be within "
"the minimum Vulkan maxBoundDescriptorSets requirement of 4, which is "
"the limit on most GPUs used in Android devices - Arm Mali, Imagination "
"PowerVR, Qualcomm Adreno 6xx and older, as well as on old PC Nvidia "
"drivers");
// "Xenia Emulator Microcode Translator".
// https://github.com/KhronosGroup/SPIRV-Headers/blob/c43a43c7cc3af55910b9bec2a71e3e8a622443cf/include/spirv/spir-v.xml#L79
@@ -522,6 +529,8 @@ class SpirvShaderTranslator : public ShaderTranslator {
spv::Id type_float_vectors_[4];
};
spv::Id type_interpolators_;
spv::Id const_int_0_;
spv::Id const_int4_0_;
spv::Id const_uint_0_;
@@ -582,11 +591,12 @@ class SpirvShaderTranslator : public ShaderTranslator {
// PS, only when needed - bool.
spv::Id input_front_facing_;
// In vertex or tessellation evaluation shaders - outputs, always
// xenos::kMaxInterpolators.
// In pixel shaders - inputs, min(xenos::kMaxInterpolators, register_count()).
spv::Id input_output_interpolators_[xenos::kMaxInterpolators];
static const std::string kInterpolatorNamePrefix;
// VS output or PS input, only when needed - type_interpolators_.
// The Qualcomm Adreno driver has strict requirements for stage linkage - if
// this is an array in one stage, it must be an array in the other (in case of
// Xenia, including geometry shaders); it must not be an array in one and just
// elements in consecutive locations in another.
spv::Id input_output_interpolators_;
enum OutputPerVertexMember : unsigned int {
kOutputPerVertexMemberPosition,

View File

@@ -2573,10 +2573,10 @@ size_t SpirvShaderTranslator::FindOrAddSamplerBinding(
builder_->makeSamplerType(), name.str().c_str());
builder_->addDecoration(
new_sampler_binding.variable, spv::DecorationDescriptorSet,
int(is_vertex_shader() ? kDescriptorSetSamplersVertex
: kDescriptorSetSamplersPixel));
builder_->addDecoration(new_sampler_binding.variable, spv::DecorationBinding,
int(new_sampler_binding_index));
int(is_vertex_shader() ? kDescriptorSetTexturesVertex
: kDescriptorSetTexturesPixel));
// The binding indices will be specified later after all textures are added as
// samplers are located after images in the descriptor set.
if (features_.spirv_version >= spv::Spv_1_4) {
main_interface_.push_back(new_sampler_binding.variable);
}

View File

@@ -95,8 +95,8 @@ bool TraceDump::Setup() {
// Create the emulator but don't initialize so we can setup the window.
emulator_ = std::make_unique<Emulator>("", "", "", "");
X_STATUS result = emulator_->Setup(
nullptr, nullptr, nullptr, [this]() { return CreateGraphicsSystem(); },
nullptr);
nullptr, nullptr, false, nullptr,
[this]() { return CreateGraphicsSystem(); }, nullptr);
if (XFAILED(result)) {
XELOGE("Failed to setup emulator: {:08X}", result);
return false;

View File

@@ -125,7 +125,7 @@ bool TraceViewer::Setup() {
// Create the emulator but don't initialize so we can setup the window.
emulator_ = std::make_unique<Emulator>("", "", "", "");
X_STATUS result = emulator_->Setup(
window_.get(), nullptr, nullptr,
window_.get(), nullptr, false, nullptr,
[this]() { return CreateGraphicsSystem(); }, nullptr);
if (XFAILED(result)) {
XELOGE("Failed to setup emulator: {:08X}", result);

View File

@@ -34,7 +34,6 @@ project("xenia-gpu-vulkan-trace-viewer")
"xenia-base",
"xenia-core",
"xenia-cpu",
"xenia-cpu-backend-x64",
"xenia-gpu",
"xenia-gpu-vulkan",
"xenia-hid",
@@ -66,6 +65,11 @@ project("xenia-gpu-vulkan-trace-viewer")
"../../ui/windowed_app_main_"..platform_suffix..".cc",
})
filter("architecture:x86_64")
links({
"xenia-cpu-backend-x64",
})
filter("platforms:Linux")
links({
"X11",
@@ -95,7 +99,6 @@ project("xenia-gpu-vulkan-trace-dump")
"xenia-base",
"xenia-core",
"xenia-cpu",
"xenia-cpu-backend-x64",
"xenia-gpu",
"xenia-gpu-vulkan",
"xenia-hid",
@@ -126,6 +129,11 @@ project("xenia-gpu-vulkan-trace-dump")
"../../base/console_app_main_"..platform_suffix..".cc",
})
filter("architecture:x86_64")
links({
"xenia-cpu-backend-x64",
})
filter("platforms:Linux")
links({
"X11",

File diff suppressed because it is too large Load Diff

View File

@@ -36,7 +36,7 @@
#include "xenia/gpu/vulkan/vulkan_texture_cache.h"
#include "xenia/gpu/xenos.h"
#include "xenia/kernel/kernel_state.h"
#include "xenia/ui/vulkan/single_type_descriptor_set_allocator.h"
#include "xenia/ui/vulkan/linked_type_descriptor_set_allocator.h"
#include "xenia/ui/vulkan/vulkan_presenter.h"
#include "xenia/ui/vulkan/vulkan_provider.h"
#include "xenia/ui/vulkan/vulkan_upload_buffer_pool.h"
@@ -49,10 +49,6 @@ class VulkanCommandProcessor : public CommandProcessor {
public:
// Single-descriptor layouts for use within a single frame.
enum class SingleTransientDescriptorLayout {
kUniformBufferGuestVertex,
kUniformBufferFragment,
kUniformBufferGuestShader,
kUniformBufferSystemConstants,
kUniformBufferCompute,
kStorageBufferCompute,
kCount,
@@ -231,9 +227,9 @@ class VulkanCommandProcessor : public CommandProcessor {
VkDescriptorSet& descriptor_set_out);
// The returned reference is valid until a cache clear.
VkDescriptorSetLayout GetTextureDescriptorSetLayout(bool is_samplers,
bool is_vertex,
size_t binding_count);
VkDescriptorSetLayout GetTextureDescriptorSetLayout(bool is_vertex,
size_t texture_count,
size_t sampler_count);
// The returned reference is valid until a cache clear.
const VulkanPipelineCache::PipelineLayoutProvider* GetPipelineLayout(
size_t texture_count_pixel, size_t sampler_count_pixel,
@@ -298,12 +294,11 @@ class VulkanCommandProcessor : public CommandProcessor {
union TextureDescriptorSetLayoutKey {
uint32_t key;
struct {
// 0 - sampled image descriptors, 1 - sampler descriptors.
uint32_t is_samplers : 1;
// If texture and sampler counts are both 0, use
// descriptor_set_layout_empty_ instead as these are owning references.
uint32_t texture_count : 16;
uint32_t sampler_count : 15;
uint32_t is_vertex : 1;
// For 0, use descriptor_set_layout_empty_ instead as these are owning
// references.
uint32_t binding_count : 30;
};
TextureDescriptorSetLayoutKey() : key(0) {
@@ -354,40 +349,26 @@ class VulkanCommandProcessor : public CommandProcessor {
explicit PipelineLayout(
VkPipelineLayout pipeline_layout,
VkDescriptorSetLayout descriptor_set_layout_textures_vertex_ref,
VkDescriptorSetLayout descriptor_set_layout_samplers_vertex_ref,
VkDescriptorSetLayout descriptor_set_layout_textures_pixel_ref,
VkDescriptorSetLayout descriptor_set_layout_samplers_pixel_ref)
VkDescriptorSetLayout descriptor_set_layout_textures_pixel_ref)
: pipeline_layout_(pipeline_layout),
descriptor_set_layout_textures_vertex_ref_(
descriptor_set_layout_textures_vertex_ref),
descriptor_set_layout_samplers_vertex_ref_(
descriptor_set_layout_samplers_vertex_ref),
descriptor_set_layout_textures_pixel_ref_(
descriptor_set_layout_textures_pixel_ref),
descriptor_set_layout_samplers_pixel_ref_(
descriptor_set_layout_samplers_pixel_ref) {}
descriptor_set_layout_textures_pixel_ref) {}
VkPipelineLayout GetPipelineLayout() const override {
return pipeline_layout_;
}
VkDescriptorSetLayout descriptor_set_layout_textures_vertex_ref() const {
return descriptor_set_layout_textures_vertex_ref_;
}
VkDescriptorSetLayout descriptor_set_layout_samplers_vertex_ref() const {
return descriptor_set_layout_samplers_vertex_ref_;
}
VkDescriptorSetLayout descriptor_set_layout_textures_pixel_ref() const {
return descriptor_set_layout_textures_pixel_ref_;
}
VkDescriptorSetLayout descriptor_set_layout_samplers_pixel_ref() const {
return descriptor_set_layout_samplers_pixel_ref_;
}
private:
VkPipelineLayout pipeline_layout_;
VkDescriptorSetLayout descriptor_set_layout_textures_vertex_ref_;
VkDescriptorSetLayout descriptor_set_layout_samplers_vertex_ref_;
VkDescriptorSetLayout descriptor_set_layout_textures_pixel_ref_;
VkDescriptorSetLayout descriptor_set_layout_samplers_pixel_ref_;
};
struct UsedSingleTransientDescriptor {
@@ -458,16 +439,20 @@ class VulkanCommandProcessor : public CommandProcessor {
uint32_t used_texture_mask);
bool UpdateBindings(const VulkanShader* vertex_shader,
const VulkanShader* pixel_shader);
// Allocates a descriptor set and fills the VkWriteDescriptorSet structure.
// The descriptor set layout must be the one for the given is_samplers,
// is_vertex, binding_count (from GetTextureDescriptorSetLayout - may be
// Allocates a descriptor set and fills one or two VkWriteDescriptorSet
// structure instances (for images and samplers).
// The descriptor set layout must be the one for the given is_vertex,
// texture_count, sampler_count (from GetTextureDescriptorSetLayout - may be
// already available at the moment of the call, no need to locate it again).
// Returns whether the allocation was successful.
bool WriteTransientTextureBindings(
bool is_samplers, bool is_vertex, uint32_t binding_count,
// Returns how many VkWriteDescriptorSet structure instances have been
// written, or 0 if there was a failure to allocate the descriptor set or no
// bindings were requested.
uint32_t WriteTransientTextureBindings(
bool is_vertex, uint32_t texture_count, uint32_t sampler_count,
VkDescriptorSetLayout descriptor_set_layout,
const VkDescriptorImageInfo* image_info,
VkWriteDescriptorSet& write_descriptor_set_out);
const VkDescriptorImageInfo* texture_image_info,
const VkDescriptorImageInfo* sampler_image_info,
VkWriteDescriptorSet* descriptor_set_writes_out);
bool device_lost_ = false;
@@ -530,6 +515,7 @@ class VulkanCommandProcessor : public CommandProcessor {
VkDescriptorSetLayout descriptor_set_layout_empty_ = VK_NULL_HANDLE;
VkDescriptorSetLayout descriptor_set_layout_shared_memory_and_edram_ =
VK_NULL_HANDLE;
VkDescriptorSetLayout descriptor_set_layout_constants_ = VK_NULL_HANDLE;
std::array<VkDescriptorSetLayout,
size_t(SingleTransientDescriptorLayout::kCount)>
descriptor_set_layouts_single_transient_{};
@@ -543,19 +529,27 @@ class VulkanCommandProcessor : public CommandProcessor {
PipelineLayoutKey::Hasher>
pipeline_layouts_;
ui::vulkan::SingleTypeDescriptorSetAllocator
// No specific reason for 32768, just the "too much" descriptor count from
// Direct3D 12 PIX warnings.
static constexpr uint32_t kLinkedTypeDescriptorPoolSetCount = 32768;
static const VkDescriptorPoolSize kDescriptorPoolSizeUniformBuffer;
static const VkDescriptorPoolSize kDescriptorPoolSizeStorageBuffer;
static const VkDescriptorPoolSize kDescriptorPoolSizeTextures[2];
ui::vulkan::LinkedTypeDescriptorSetAllocator
transient_descriptor_allocator_uniform_buffer_;
ui::vulkan::SingleTypeDescriptorSetAllocator
ui::vulkan::LinkedTypeDescriptorSetAllocator
transient_descriptor_allocator_storage_buffer_;
std::deque<UsedSingleTransientDescriptor> single_transient_descriptors_used_;
std::array<std::vector<VkDescriptorSet>,
size_t(SingleTransientDescriptorLayout::kCount)>
single_transient_descriptors_free_;
// <Usage frame, set>.
std::deque<std::pair<uint64_t, VkDescriptorSet>>
constants_transient_descriptors_used_;
std::vector<VkDescriptorSet> constants_transient_descriptors_free_;
ui::vulkan::SingleTypeDescriptorSetAllocator
transient_descriptor_allocator_sampled_image_;
ui::vulkan::SingleTypeDescriptorSetAllocator
transient_descriptor_allocator_sampler_;
ui::vulkan::LinkedTypeDescriptorSetAllocator
transient_descriptor_allocator_textures_;
std::deque<UsedTextureTransientDescriptorSet>
texture_transient_descriptor_sets_used_;
std::unordered_map<TextureDescriptorSetLayoutKey,
@@ -701,6 +695,11 @@ class VulkanCommandProcessor : public CommandProcessor {
// Pipeline layout of the current guest graphics pipeline.
const PipelineLayout* current_guest_graphics_pipeline_layout_;
VkDescriptorBufferInfo current_constant_buffer_infos_
[SpirvShaderTranslator::kConstantBufferCount];
// Whether up-to-date data has been written to constant (uniform) buffers, and
// the buffer infos in current_constant_buffer_infos_ point to them.
uint32_t current_constant_buffers_up_to_date_;
VkDescriptorSet current_graphics_descriptor_sets_
[SpirvShaderTranslator::kDescriptorSetCount];
// Whether descriptor sets in current_graphics_descriptor_sets_ point to

View File

@@ -661,6 +661,12 @@ void VulkanRenderTargetCache::Shutdown(bool from_destructor) {
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
VkDevice device = provider.device();
// Destroy all render targets before the descriptor set pool is destroyed -
// may happen if shutting down the VulkanRenderTargetCache by destroying it,
// so ShutdownCommon is called by the RenderTargetCache destructor, when it's
// already too late.
DestroyAllRenderTargets(true);
for (const auto& dump_pipeline_pair : dump_pipelines_) {
// May be null to prevent recreation attempts.
if (dump_pipeline_pair.second != VK_NULL_HANDLE) {

View File

@@ -647,7 +647,7 @@ class VulkanRenderTargetCache final : public RenderTargetCache {
TransferInvocation(const Transfer& transfer,
const TransferShaderKey& shader_key)
: transfer(transfer), shader_key(shader_key) {}
bool operator<(const TransferInvocation& other_invocation) {
bool operator<(const TransferInvocation& other_invocation) const {
// TODO(Triang3l): See if it may be better to sort by the source in the
// first place, especially when reading the same data multiple times (like
// to write the stencil bits after depth) for better read locality.
@@ -784,7 +784,7 @@ class VulkanRenderTargetCache final : public RenderTargetCache {
DumpInvocation(const ResolveCopyDumpRectangle& rectangle,
const DumpPipelineKey& pipeline_key)
: rectangle(rectangle), pipeline_key(pipeline_key) {}
bool operator<(const DumpInvocation& other_invocation) {
bool operator<(const DumpInvocation& other_invocation) const {
// Sort by the pipeline key primarily to reduce pipeline state (context)
// switches.
if (pipeline_key != other_invocation.pipeline_key) {