Merge branch 'master' into vulkan

This commit is contained in:
Triang3l 2022-05-15 16:18:41 +03:00
commit 05adfbc58d
10 changed files with 125 additions and 76 deletions

View File

@ -862,6 +862,13 @@ bool D3D12CommandProcessor::SetupContext() {
draw_resolution_scale_x, draw_resolution_scale_y); draw_resolution_scale_x, draw_resolution_scale_y);
} }
shared_memory_ =
std::make_unique<D3D12SharedMemory>(*this, *memory_, trace_writer_);
if (!shared_memory_->Initialize()) {
XELOGE("Failed to initialize shared memory");
return false;
}
// Initialize the render target cache before configuring binding - need to // Initialize the render target cache before configuring binding - need to
// know if using rasterizer-ordered views for the bindless root signature. // know if using rasterizer-ordered views for the bindless root signature.
render_target_cache_ = std::make_unique<D3D12RenderTargetCache>( render_target_cache_ = std::make_unique<D3D12RenderTargetCache>(
@ -1144,13 +1151,6 @@ bool D3D12CommandProcessor::SetupContext() {
} }
} }
shared_memory_ =
std::make_unique<D3D12SharedMemory>(*this, *memory_, trace_writer_);
if (!shared_memory_->Initialize()) {
XELOGE("Failed to initialize shared memory");
return false;
}
primitive_processor_ = std::make_unique<D3D12PrimitiveProcessor>( primitive_processor_ = std::make_unique<D3D12PrimitiveProcessor>(
*register_file_, *memory_, trace_writer_, *shared_memory_, *this); *register_file_, *memory_, trace_writer_, *shared_memory_, *this);
if (!primitive_processor_->Initialize()) { if (!primitive_processor_->Initialize()) {
@ -1615,13 +1615,11 @@ void D3D12CommandProcessor::ShutdownContext() {
gamma_ramp_upload_buffer_.Reset(); gamma_ramp_upload_buffer_.Reset();
gamma_ramp_buffer_.Reset(); gamma_ramp_buffer_.Reset();
pipeline_cache_.reset();
texture_cache_.reset(); texture_cache_.reset();
primitive_processor_.reset(); pipeline_cache_.reset();
shared_memory_.reset(); primitive_processor_.reset();
// Shut down binding - bindless descriptors may be owned by subsystems like // Shut down binding - bindless descriptors may be owned by subsystems like
// the texture cache. // the texture cache.
@ -1654,6 +1652,8 @@ void D3D12CommandProcessor::ShutdownContext() {
render_target_cache_.reset(); render_target_cache_.reset();
shared_memory_.reset();
deferred_command_list_.Reset(); deferred_command_list_.Reset();
ui::d3d12::util::ReleaseAndNull(command_list_1_); ui::d3d12::util::ReleaseAndNull(command_list_1_);
ui::d3d12::util::ReleaseAndNull(command_list_); ui::d3d12::util::ReleaseAndNull(command_list_);
@ -2787,10 +2787,10 @@ void D3D12CommandProcessor::CheckSubmissionFence(uint64_t await_submission) {
shared_memory_->CompletedSubmissionUpdated(); shared_memory_->CompletedSubmissionUpdated();
primitive_processor_->CompletedSubmissionUpdated();
render_target_cache_->CompletedSubmissionUpdated(); render_target_cache_->CompletedSubmissionUpdated();
primitive_processor_->CompletedSubmissionUpdated();
texture_cache_->CompletedSubmissionUpdated(submission_completed_); texture_cache_->CompletedSubmissionUpdated(submission_completed_);
} }
@ -2870,10 +2870,10 @@ bool D3D12CommandProcessor::BeginSubmission(bool is_guest_command) {
} }
primitive_topology_ = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; primitive_topology_ = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
primitive_processor_->BeginSubmission();
render_target_cache_->BeginSubmission(); render_target_cache_->BeginSubmission();
primitive_processor_->BeginSubmission();
texture_cache_->BeginSubmission(submission_current_); texture_cache_->BeginSubmission(submission_current_);
} }
@ -3043,12 +3043,10 @@ bool D3D12CommandProcessor::EndSubmission(bool is_swap) {
} }
constant_buffer_pool_->ClearCache(); constant_buffer_pool_->ClearCache();
pipeline_cache_->ClearCache();
render_target_cache_->ClearCache();
texture_cache_->ClearCache(); texture_cache_->ClearCache();
pipeline_cache_->ClearCache();
for (auto it : root_signatures_bindful_) { for (auto it : root_signatures_bindful_) {
it.second->Release(); it.second->Release();
} }
@ -3056,6 +3054,8 @@ bool D3D12CommandProcessor::EndSubmission(bool is_swap) {
primitive_processor_->ClearCache(); primitive_processor_->ClearCache();
render_target_cache_->ClearCache();
shared_memory_->ClearCache(); shared_memory_->ClearCache();
} }
} }

View File

@ -427,6 +427,8 @@ class D3D12CommandProcessor : public CommandProcessor {
// of UpdateBindings time, and that's outside the emulator's control even). // of UpdateBindings time, and that's outside the emulator's control even).
bool bindless_resources_used_ = false; bool bindless_resources_used_ = false;
std::unique_ptr<D3D12SharedMemory> shared_memory_;
std::unique_ptr<D3D12RenderTargetCache> render_target_cache_; std::unique_ptr<D3D12RenderTargetCache> render_target_cache_;
std::unique_ptr<ui::d3d12::D3D12UploadBufferPool> constant_buffer_pool_; std::unique_ptr<ui::d3d12::D3D12UploadBufferPool> constant_buffer_pool_;
@ -491,8 +493,6 @@ class D3D12CommandProcessor : public CommandProcessor {
ID3D12RootSignature* root_signature_bindless_vs_ = nullptr; ID3D12RootSignature* root_signature_bindless_vs_ = nullptr;
ID3D12RootSignature* root_signature_bindless_ds_ = nullptr; ID3D12RootSignature* root_signature_bindless_ds_ = nullptr;
std::unique_ptr<D3D12SharedMemory> shared_memory_;
std::unique_ptr<D3D12PrimitiveProcessor> primitive_processor_; std::unique_ptr<D3D12PrimitiveProcessor> primitive_processor_;
std::unique_ptr<PipelineCache> pipeline_cache_; std::unique_ptr<PipelineCache> pipeline_cache_;

View File

@ -1955,7 +1955,9 @@ void D3D12TextureCache::UpdateTextureBindingsImpl(
uint32_t D3D12TextureCache::FindOrCreateTextureDescriptor( uint32_t D3D12TextureCache::FindOrCreateTextureDescriptor(
D3D12Texture& texture, bool is_signed, uint32_t host_swizzle) { D3D12Texture& texture, bool is_signed, uint32_t host_swizzle) {
uint32_t descriptor_key = uint32_t(is_signed) | (host_swizzle << 1); D3D12Texture::SRVDescriptorKey descriptor_key;
descriptor_key.is_signed = uint32_t(is_signed);
descriptor_key.host_swizzle = host_swizzle;
// Try to find an existing descriptor. // Try to find an existing descriptor.
uint32_t existing_descriptor_index = uint32_t existing_descriptor_index =

View File

@ -11,6 +11,7 @@
#define XENIA_GPU_D3D12_D3D12_TEXTURE_CACHE_H_ #define XENIA_GPU_D3D12_D3D12_TEXTURE_CACHE_H_
#include <array> #include <array>
#include <functional>
#include <memory> #include <memory>
#include <unordered_map> #include <unordered_map>
#include <utility> #include <utility>
@ -268,9 +269,31 @@ class D3D12TextureCache final : public TextureCache {
class D3D12Texture final : public Texture { class D3D12Texture final : public Texture {
public: public:
D3D12Texture(D3D12TextureCache& texture_cache, const TextureKey& key, union SRVDescriptorKey {
ID3D12Resource* resource, uint32_t key;
D3D12_RESOURCE_STATES resource_state); struct {
uint32_t is_signed : 1;
uint32_t host_swizzle : 12;
};
SRVDescriptorKey() : key(0) { static_assert_size(*this, sizeof(key)); }
struct Hasher {
size_t operator()(const SRVDescriptorKey& key) const {
return std::hash<decltype(key.key)>{}(key.key);
}
};
bool operator==(const SRVDescriptorKey& other_key) const {
return key == other_key.key;
}
bool operator!=(const SRVDescriptorKey& other_key) const {
return !(*this == other_key);
}
};
explicit D3D12Texture(D3D12TextureCache& texture_cache,
const TextureKey& key, ID3D12Resource* resource,
D3D12_RESOURCE_STATES resource_state);
~D3D12Texture(); ~D3D12Texture();
ID3D12Resource* resource() const { return resource_.Get(); } ID3D12Resource* resource() const { return resource_.Get(); }
@ -281,12 +304,12 @@ class D3D12TextureCache final : public TextureCache {
return old_state; return old_state;
} }
uint32_t GetSRVDescriptorIndex(uint32_t descriptor_key) const { uint32_t GetSRVDescriptorIndex(SRVDescriptorKey descriptor_key) const {
auto it = srv_descriptors_.find(descriptor_key); auto it = srv_descriptors_.find(descriptor_key);
return it != srv_descriptors_.cend() ? it->second : UINT32_MAX; return it != srv_descriptors_.cend() ? it->second : UINT32_MAX;
} }
void AddSRVDescriptorIndex(uint32_t descriptor_key, void AddSRVDescriptorIndex(SRVDescriptorKey descriptor_key,
uint32_t descriptor_index) { uint32_t descriptor_index) {
srv_descriptors_.emplace(descriptor_key, descriptor_index); srv_descriptors_.emplace(descriptor_key, descriptor_index);
} }
@ -299,7 +322,8 @@ class D3D12TextureCache final : public TextureCache {
// copying to the shader-visible heap (much faster than recreating, which, // copying to the shader-visible heap (much faster than recreating, which,
// according to profiling, was often a bottleneck in many games). // according to profiling, was often a bottleneck in many games).
// For bindless - indices in the global shader-visible descriptor heap. // For bindless - indices in the global shader-visible descriptor heap.
std::unordered_map<uint32_t, uint32_t> srv_descriptors_; std::unordered_map<SRVDescriptorKey, uint32_t, SRVDescriptorKey::Hasher>
srv_descriptors_;
}; };
static constexpr uint32_t kSRVDescriptorCachePageSize = 65536; static constexpr uint32_t kSRVDescriptorCachePageSize = 65536;
@ -346,8 +370,8 @@ class D3D12TextureCache final : public TextureCache {
class ScaledResolveVirtualBuffer { class ScaledResolveVirtualBuffer {
public: public:
ScaledResolveVirtualBuffer(ID3D12Resource* resource, explicit ScaledResolveVirtualBuffer(ID3D12Resource* resource,
D3D12_RESOURCE_STATES resource_state) D3D12_RESOURCE_STATES resource_state)
: resource_(resource), resource_state_(resource_state) {} : resource_(resource), resource_state_(resource_state) {}
ID3D12Resource* resource() const { return resource_.Get(); } ID3D12Resource* resource() const { return resource_.Get(); }
D3D12_RESOURCE_STATES SetResourceState(D3D12_RESOURCE_STATES new_state) { D3D12_RESOURCE_STATES SetResourceState(D3D12_RESOURCE_STATES new_state) {
@ -373,12 +397,12 @@ class D3D12TextureCache final : public TextureCache {
bool uav_barrier_pending_ = false; bool uav_barrier_pending_ = false;
}; };
D3D12TextureCache(const RegisterFile& register_file, explicit D3D12TextureCache(const RegisterFile& register_file,
D3D12SharedMemory& shared_memory, D3D12SharedMemory& shared_memory,
uint32_t draw_resolution_scale_x, uint32_t draw_resolution_scale_x,
uint32_t draw_resolution_scale_y, uint32_t draw_resolution_scale_y,
D3D12CommandProcessor& command_processor, D3D12CommandProcessor& command_processor,
bool bindless_resources_used); bool bindless_resources_used);
bool Initialize(); bool Initialize();

View File

@ -685,10 +685,10 @@ void PipelineCache::InitializeShaderStorage(
pipeline_runtime_description.root_signature = pipeline_runtime_description.root_signature =
command_processor_.GetRootSignature( command_processor_.GetRootSignature(
vertex_shader, pixel_shader, vertex_shader, pixel_shader,
DxbcShaderTranslator::Modification( Shader::IsHostVertexShaderTypeDomain(
pipeline_description.vertex_shader_modification) DxbcShaderTranslator::Modification(
.vertex.host_vertex_shader_type != pipeline_description.vertex_shader_modification)
Shader::HostVertexShaderType::kVertex); .vertex.host_vertex_shader_type));
if (!pipeline_runtime_description.root_signature) { if (!pipeline_runtime_description.root_signature) {
continue; continue;
} }
@ -2834,30 +2834,7 @@ ID3D12PipelineState* PipelineCache::CreateD3D12Pipeline(
DxbcShaderTranslator::Modification( DxbcShaderTranslator::Modification(
runtime_description.vertex_shader->modification()) runtime_description.vertex_shader->modification())
.vertex.host_vertex_shader_type; .vertex.host_vertex_shader_type;
if (host_vertex_shader_type == Shader::HostVertexShaderType::kVertex) { if (Shader::IsHostVertexShaderTypeDomain(host_vertex_shader_type)) {
state_desc.VS.pShaderBytecode =
runtime_description.vertex_shader->translated_binary().data();
state_desc.VS.BytecodeLength =
runtime_description.vertex_shader->translated_binary().size();
PipelinePrimitiveTopologyType primitive_topology_type =
PipelinePrimitiveTopologyType(
description.primitive_topology_type_or_tessellation_mode);
switch (primitive_topology_type) {
case PipelinePrimitiveTopologyType::kPoint:
state_desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT;
break;
case PipelinePrimitiveTopologyType::kLine:
state_desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE;
break;
case PipelinePrimitiveTopologyType::kTriangle:
state_desc.PrimitiveTopologyType =
D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
break;
default:
assert_unhandled_case(primitive_topology_type);
return nullptr;
}
} else {
state_desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_PATCH; state_desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_PATCH;
xenos::TessellationMode tessellation_mode = xenos::TessellationMode( xenos::TessellationMode tessellation_mode = xenos::TessellationMode(
description.primitive_topology_type_or_tessellation_mode); description.primitive_topology_type_or_tessellation_mode);
@ -2929,6 +2906,35 @@ ID3D12PipelineState* PipelineCache::CreateD3D12Pipeline(
runtime_description.vertex_shader->translated_binary().data(); runtime_description.vertex_shader->translated_binary().data();
state_desc.DS.BytecodeLength = state_desc.DS.BytecodeLength =
runtime_description.vertex_shader->translated_binary().size(); runtime_description.vertex_shader->translated_binary().size();
} else {
assert_true(host_vertex_shader_type ==
Shader::HostVertexShaderType::kVertex);
if (host_vertex_shader_type != Shader::HostVertexShaderType::kVertex) {
// Fallback vertex shaders are not needed on Direct3D 12.
return nullptr;
}
state_desc.VS.pShaderBytecode =
runtime_description.vertex_shader->translated_binary().data();
state_desc.VS.BytecodeLength =
runtime_description.vertex_shader->translated_binary().size();
PipelinePrimitiveTopologyType primitive_topology_type =
PipelinePrimitiveTopologyType(
description.primitive_topology_type_or_tessellation_mode);
switch (primitive_topology_type) {
case PipelinePrimitiveTopologyType::kPoint:
state_desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT;
break;
case PipelinePrimitiveTopologyType::kLine:
state_desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE;
break;
case PipelinePrimitiveTopologyType::kTriangle:
state_desc.PrimitiveTopologyType =
D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
break;
default:
assert_unhandled_case(primitive_topology_type);
return nullptr;
}
} }
// Pixel shader. // Pixel shader.

View File

@ -646,13 +646,13 @@ class DxbcShaderTranslator : public ShaderTranslator {
bool IsDxbcVertexShader() const { bool IsDxbcVertexShader() const {
return is_vertex_shader() && return is_vertex_shader() &&
GetDxbcShaderModification().vertex.host_vertex_shader_type == !Shader::IsHostVertexShaderTypeDomain(
Shader::HostVertexShaderType::kVertex; GetDxbcShaderModification().vertex.host_vertex_shader_type);
} }
bool IsDxbcDomainShader() const { bool IsDxbcDomainShader() const {
return is_vertex_shader() && return is_vertex_shader() &&
GetDxbcShaderModification().vertex.host_vertex_shader_type != Shader::IsHostVertexShaderTypeDomain(
Shader::HostVertexShaderType::kVertex; GetDxbcShaderModification().vertex.host_vertex_shader_type);
} }
// Whether to use switch-case rather than if (pc >= label) for control flow. // Whether to use switch-case rather than if (pc >= label) for control flow.

View File

@ -145,7 +145,7 @@ class PrimitiveProcessor {
// only valid for index_buffer_type kHostConverted and kHostBuiltin. // only valid for index_buffer_type kHostConverted and kHostBuiltin.
size_t host_index_buffer_handle; size_t host_index_buffer_handle;
bool IsTessellated() const { bool IsTessellated() const {
return host_vertex_shader_type != Shader::HostVertexShaderType::kVertex; return Shader::IsHostVertexShaderTypeDomain(host_vertex_shader_type);
} }
}; };

View File

@ -659,16 +659,25 @@ class Shader {
// packed. This is : uint32_t for simplicity of packing in bit fields. // packed. This is : uint32_t for simplicity of packing in bit fields.
enum class HostVertexShaderType : uint32_t { enum class HostVertexShaderType : uint32_t {
kVertex, kVertex,
kLineDomainCPIndexed,
kDomainStart,
kLineDomainCPIndexed = kDomainStart,
kLineDomainPatchIndexed, kLineDomainPatchIndexed,
kTriangleDomainCPIndexed, kTriangleDomainCPIndexed,
kTriangleDomainPatchIndexed, kTriangleDomainPatchIndexed,
kQuadDomainCPIndexed, kQuadDomainCPIndexed,
kQuadDomainPatchIndexed, kQuadDomainPatchIndexed,
kDomainEnd,
}; };
// For packing HostVertexShaderType in bit fields. // For packing HostVertexShaderType in bit fields.
static constexpr uint32_t kHostVertexShaderTypeBitCount = 3; static constexpr uint32_t kHostVertexShaderTypeBitCount = 3;
static constexpr bool IsHostVertexShaderTypeDomain(
HostVertexShaderType host_vertex_shader_type) {
return host_vertex_shader_type >= HostVertexShaderType::kDomainStart &&
host_vertex_shader_type < HostVertexShaderType::kDomainEnd;
}
struct Error { struct Error {
bool is_fatal = false; bool is_fatal = false;
std::string message; std::string message;

View File

@ -248,7 +248,7 @@ class TextureCache {
void LogAction(const char* action) const; void LogAction(const char* action) const;
protected: protected:
Texture(TextureCache& texture_cache, const TextureKey& key); explicit Texture(TextureCache& texture_cache, const TextureKey& key);
void SetHostMemoryUsage(uint64_t new_host_memory_usage) { void SetHostMemoryUsage(uint64_t new_host_memory_usage) {
texture_cache_.UpdateTexturesTotalHostMemoryUsage(new_host_memory_usage, texture_cache_.UpdateTexturesTotalHostMemoryUsage(new_host_memory_usage,
@ -420,9 +420,10 @@ class TextureCache {
} }
}; };
TextureCache(const RegisterFile& register_file, SharedMemory& shared_memory, explicit TextureCache(const RegisterFile& register_file,
uint32_t draw_resolution_scale_x, SharedMemory& shared_memory,
uint32_t draw_resolution_scale_y); uint32_t draw_resolution_scale_x,
uint32_t draw_resolution_scale_y);
const RegisterFile& register_file() const { return register_file_; } const RegisterFile& register_file() const { return register_file_; }
SharedMemory& shared_memory() const { return shared_memory_; } SharedMemory& shared_memory() const { return shared_memory_; }

View File

@ -866,6 +866,9 @@ bool VulkanImmediateDrawer::CreateTextureResource(
size_t& pending_upload_index_out) { size_t& pending_upload_index_out) {
const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); const VulkanProvider::DeviceFunctions& dfn = provider_.dfn();
VkDevice device = provider_.device(); VkDevice device = provider_.device();
const VkPhysicalDevicePortabilitySubsetFeaturesKHR*
device_portability_subset_features =
provider_.device_portability_subset_features();
// Create the image and the descriptor. // Create the image and the descriptor.
@ -907,9 +910,13 @@ bool VulkanImmediateDrawer::CreateTextureResource(
image_view_create_info.image = image; image_view_create_info.image = image;
image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
image_view_create_info.format = VK_FORMAT_R8G8B8A8_UNORM; image_view_create_info.format = VK_FORMAT_R8G8B8A8_UNORM;
// data == nullptr is a special case for (1, 1, 1, 1). // data == nullptr is a special case for (1, 1, 1, 1), though the image will
// be cleared to (1, 1, 1, 1) anyway, just a micro-optimization.
VkComponentSwizzle swizzle = VkComponentSwizzle swizzle =
data ? VK_COMPONENT_SWIZZLE_IDENTITY : VK_COMPONENT_SWIZZLE_ONE; (data || (device_portability_subset_features &&
!device_portability_subset_features->imageViewFormatSwizzle))
? VK_COMPONENT_SWIZZLE_IDENTITY
: VK_COMPONENT_SWIZZLE_ONE;
image_view_create_info.components.r = swizzle; image_view_create_info.components.r = swizzle;
image_view_create_info.components.g = swizzle; image_view_create_info.components.g = swizzle;
image_view_create_info.components.b = swizzle; image_view_create_info.components.b = swizzle;