Merge branch 'master' into vulkan
This commit is contained in:
commit
05adfbc58d
|
@ -862,6 +862,13 @@ bool D3D12CommandProcessor::SetupContext() {
|
|||
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
|
||||
// know if using rasterizer-ordered views for the bindless root signature.
|
||||
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>(
|
||||
*register_file_, *memory_, trace_writer_, *shared_memory_, *this);
|
||||
if (!primitive_processor_->Initialize()) {
|
||||
|
@ -1615,13 +1615,11 @@ void D3D12CommandProcessor::ShutdownContext() {
|
|||
gamma_ramp_upload_buffer_.Reset();
|
||||
gamma_ramp_buffer_.Reset();
|
||||
|
||||
pipeline_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
|
||||
// the texture cache.
|
||||
|
@ -1654,6 +1652,8 @@ void D3D12CommandProcessor::ShutdownContext() {
|
|||
|
||||
render_target_cache_.reset();
|
||||
|
||||
shared_memory_.reset();
|
||||
|
||||
deferred_command_list_.Reset();
|
||||
ui::d3d12::util::ReleaseAndNull(command_list_1_);
|
||||
ui::d3d12::util::ReleaseAndNull(command_list_);
|
||||
|
@ -2787,10 +2787,10 @@ void D3D12CommandProcessor::CheckSubmissionFence(uint64_t await_submission) {
|
|||
|
||||
shared_memory_->CompletedSubmissionUpdated();
|
||||
|
||||
primitive_processor_->CompletedSubmissionUpdated();
|
||||
|
||||
render_target_cache_->CompletedSubmissionUpdated();
|
||||
|
||||
primitive_processor_->CompletedSubmissionUpdated();
|
||||
|
||||
texture_cache_->CompletedSubmissionUpdated(submission_completed_);
|
||||
}
|
||||
|
||||
|
@ -2870,10 +2870,10 @@ bool D3D12CommandProcessor::BeginSubmission(bool is_guest_command) {
|
|||
}
|
||||
primitive_topology_ = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
|
||||
|
||||
primitive_processor_->BeginSubmission();
|
||||
|
||||
render_target_cache_->BeginSubmission();
|
||||
|
||||
primitive_processor_->BeginSubmission();
|
||||
|
||||
texture_cache_->BeginSubmission(submission_current_);
|
||||
}
|
||||
|
||||
|
@ -3043,12 +3043,10 @@ bool D3D12CommandProcessor::EndSubmission(bool is_swap) {
|
|||
}
|
||||
constant_buffer_pool_->ClearCache();
|
||||
|
||||
pipeline_cache_->ClearCache();
|
||||
|
||||
render_target_cache_->ClearCache();
|
||||
|
||||
texture_cache_->ClearCache();
|
||||
|
||||
pipeline_cache_->ClearCache();
|
||||
|
||||
for (auto it : root_signatures_bindful_) {
|
||||
it.second->Release();
|
||||
}
|
||||
|
@ -3056,6 +3054,8 @@ bool D3D12CommandProcessor::EndSubmission(bool is_swap) {
|
|||
|
||||
primitive_processor_->ClearCache();
|
||||
|
||||
render_target_cache_->ClearCache();
|
||||
|
||||
shared_memory_->ClearCache();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -427,6 +427,8 @@ class D3D12CommandProcessor : public CommandProcessor {
|
|||
// of UpdateBindings time, and that's outside the emulator's control even).
|
||||
bool bindless_resources_used_ = false;
|
||||
|
||||
std::unique_ptr<D3D12SharedMemory> shared_memory_;
|
||||
|
||||
std::unique_ptr<D3D12RenderTargetCache> render_target_cache_;
|
||||
|
||||
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_ds_ = nullptr;
|
||||
|
||||
std::unique_ptr<D3D12SharedMemory> shared_memory_;
|
||||
|
||||
std::unique_ptr<D3D12PrimitiveProcessor> primitive_processor_;
|
||||
|
||||
std::unique_ptr<PipelineCache> pipeline_cache_;
|
||||
|
|
|
@ -1955,7 +1955,9 @@ void D3D12TextureCache::UpdateTextureBindingsImpl(
|
|||
|
||||
uint32_t D3D12TextureCache::FindOrCreateTextureDescriptor(
|
||||
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.
|
||||
uint32_t existing_descriptor_index =
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#define XENIA_GPU_D3D12_D3D12_TEXTURE_CACHE_H_
|
||||
|
||||
#include <array>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
|
@ -268,9 +269,31 @@ class D3D12TextureCache final : public TextureCache {
|
|||
|
||||
class D3D12Texture final : public Texture {
|
||||
public:
|
||||
D3D12Texture(D3D12TextureCache& texture_cache, const TextureKey& key,
|
||||
ID3D12Resource* resource,
|
||||
D3D12_RESOURCE_STATES resource_state);
|
||||
union SRVDescriptorKey {
|
||||
uint32_t key;
|
||||
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();
|
||||
|
||||
ID3D12Resource* resource() const { return resource_.Get(); }
|
||||
|
@ -281,12 +304,12 @@ class D3D12TextureCache final : public TextureCache {
|
|||
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);
|
||||
return it != srv_descriptors_.cend() ? it->second : UINT32_MAX;
|
||||
}
|
||||
|
||||
void AddSRVDescriptorIndex(uint32_t descriptor_key,
|
||||
void AddSRVDescriptorIndex(SRVDescriptorKey descriptor_key,
|
||||
uint32_t 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,
|
||||
// according to profiling, was often a bottleneck in many games).
|
||||
// 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;
|
||||
|
@ -346,8 +370,8 @@ class D3D12TextureCache final : public TextureCache {
|
|||
|
||||
class ScaledResolveVirtualBuffer {
|
||||
public:
|
||||
ScaledResolveVirtualBuffer(ID3D12Resource* resource,
|
||||
D3D12_RESOURCE_STATES resource_state)
|
||||
explicit ScaledResolveVirtualBuffer(ID3D12Resource* resource,
|
||||
D3D12_RESOURCE_STATES resource_state)
|
||||
: resource_(resource), resource_state_(resource_state) {}
|
||||
ID3D12Resource* resource() const { return resource_.Get(); }
|
||||
D3D12_RESOURCE_STATES SetResourceState(D3D12_RESOURCE_STATES new_state) {
|
||||
|
@ -373,12 +397,12 @@ class D3D12TextureCache final : public TextureCache {
|
|||
bool uav_barrier_pending_ = false;
|
||||
};
|
||||
|
||||
D3D12TextureCache(const RegisterFile& register_file,
|
||||
D3D12SharedMemory& shared_memory,
|
||||
uint32_t draw_resolution_scale_x,
|
||||
uint32_t draw_resolution_scale_y,
|
||||
D3D12CommandProcessor& command_processor,
|
||||
bool bindless_resources_used);
|
||||
explicit D3D12TextureCache(const RegisterFile& register_file,
|
||||
D3D12SharedMemory& shared_memory,
|
||||
uint32_t draw_resolution_scale_x,
|
||||
uint32_t draw_resolution_scale_y,
|
||||
D3D12CommandProcessor& command_processor,
|
||||
bool bindless_resources_used);
|
||||
|
||||
bool Initialize();
|
||||
|
||||
|
|
|
@ -685,10 +685,10 @@ void PipelineCache::InitializeShaderStorage(
|
|||
pipeline_runtime_description.root_signature =
|
||||
command_processor_.GetRootSignature(
|
||||
vertex_shader, pixel_shader,
|
||||
DxbcShaderTranslator::Modification(
|
||||
pipeline_description.vertex_shader_modification)
|
||||
.vertex.host_vertex_shader_type !=
|
||||
Shader::HostVertexShaderType::kVertex);
|
||||
Shader::IsHostVertexShaderTypeDomain(
|
||||
DxbcShaderTranslator::Modification(
|
||||
pipeline_description.vertex_shader_modification)
|
||||
.vertex.host_vertex_shader_type));
|
||||
if (!pipeline_runtime_description.root_signature) {
|
||||
continue;
|
||||
}
|
||||
|
@ -2834,30 +2834,7 @@ ID3D12PipelineState* PipelineCache::CreateD3D12Pipeline(
|
|||
DxbcShaderTranslator::Modification(
|
||||
runtime_description.vertex_shader->modification())
|
||||
.vertex.host_vertex_shader_type;
|
||||
if (host_vertex_shader_type == Shader::HostVertexShaderType::kVertex) {
|
||||
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 {
|
||||
if (Shader::IsHostVertexShaderTypeDomain(host_vertex_shader_type)) {
|
||||
state_desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_PATCH;
|
||||
xenos::TessellationMode tessellation_mode = xenos::TessellationMode(
|
||||
description.primitive_topology_type_or_tessellation_mode);
|
||||
|
@ -2929,6 +2906,35 @@ ID3D12PipelineState* PipelineCache::CreateD3D12Pipeline(
|
|||
runtime_description.vertex_shader->translated_binary().data();
|
||||
state_desc.DS.BytecodeLength =
|
||||
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.
|
||||
|
|
|
@ -646,13 +646,13 @@ class DxbcShaderTranslator : public ShaderTranslator {
|
|||
|
||||
bool IsDxbcVertexShader() const {
|
||||
return is_vertex_shader() &&
|
||||
GetDxbcShaderModification().vertex.host_vertex_shader_type ==
|
||||
Shader::HostVertexShaderType::kVertex;
|
||||
!Shader::IsHostVertexShaderTypeDomain(
|
||||
GetDxbcShaderModification().vertex.host_vertex_shader_type);
|
||||
}
|
||||
bool IsDxbcDomainShader() const {
|
||||
return is_vertex_shader() &&
|
||||
GetDxbcShaderModification().vertex.host_vertex_shader_type !=
|
||||
Shader::HostVertexShaderType::kVertex;
|
||||
Shader::IsHostVertexShaderTypeDomain(
|
||||
GetDxbcShaderModification().vertex.host_vertex_shader_type);
|
||||
}
|
||||
|
||||
// Whether to use switch-case rather than if (pc >= label) for control flow.
|
||||
|
|
|
@ -145,7 +145,7 @@ class PrimitiveProcessor {
|
|||
// only valid for index_buffer_type kHostConverted and kHostBuiltin.
|
||||
size_t host_index_buffer_handle;
|
||||
bool IsTessellated() const {
|
||||
return host_vertex_shader_type != Shader::HostVertexShaderType::kVertex;
|
||||
return Shader::IsHostVertexShaderTypeDomain(host_vertex_shader_type);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -659,16 +659,25 @@ class Shader {
|
|||
// packed. This is : uint32_t for simplicity of packing in bit fields.
|
||||
enum class HostVertexShaderType : uint32_t {
|
||||
kVertex,
|
||||
kLineDomainCPIndexed,
|
||||
|
||||
kDomainStart,
|
||||
kLineDomainCPIndexed = kDomainStart,
|
||||
kLineDomainPatchIndexed,
|
||||
kTriangleDomainCPIndexed,
|
||||
kTriangleDomainPatchIndexed,
|
||||
kQuadDomainCPIndexed,
|
||||
kQuadDomainPatchIndexed,
|
||||
kDomainEnd,
|
||||
};
|
||||
// For packing HostVertexShaderType in bit fields.
|
||||
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 {
|
||||
bool is_fatal = false;
|
||||
std::string message;
|
||||
|
|
|
@ -248,7 +248,7 @@ class TextureCache {
|
|||
void LogAction(const char* action) const;
|
||||
|
||||
protected:
|
||||
Texture(TextureCache& texture_cache, const TextureKey& key);
|
||||
explicit Texture(TextureCache& texture_cache, const TextureKey& key);
|
||||
|
||||
void SetHostMemoryUsage(uint64_t 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,
|
||||
uint32_t draw_resolution_scale_x,
|
||||
uint32_t draw_resolution_scale_y);
|
||||
explicit TextureCache(const RegisterFile& register_file,
|
||||
SharedMemory& shared_memory,
|
||||
uint32_t draw_resolution_scale_x,
|
||||
uint32_t draw_resolution_scale_y);
|
||||
|
||||
const RegisterFile& register_file() const { return register_file_; }
|
||||
SharedMemory& shared_memory() const { return shared_memory_; }
|
||||
|
|
|
@ -866,6 +866,9 @@ bool VulkanImmediateDrawer::CreateTextureResource(
|
|||
size_t& pending_upload_index_out) {
|
||||
const VulkanProvider::DeviceFunctions& dfn = provider_.dfn();
|
||||
VkDevice device = provider_.device();
|
||||
const VkPhysicalDevicePortabilitySubsetFeaturesKHR*
|
||||
device_portability_subset_features =
|
||||
provider_.device_portability_subset_features();
|
||||
|
||||
// Create the image and the descriptor.
|
||||
|
||||
|
@ -907,9 +910,13 @@ bool VulkanImmediateDrawer::CreateTextureResource(
|
|||
image_view_create_info.image = image;
|
||||
image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
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 =
|
||||
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.g = swizzle;
|
||||
image_view_create_info.components.b = swizzle;
|
||||
|
|
Loading…
Reference in New Issue