Merge branch 'master' of https://github.com/xenia-project/xenia into canary_experimental
This commit is contained in:
@@ -748,18 +748,6 @@ void D3D12CommandProcessor::SetPrimitiveTopology(
|
||||
}
|
||||
}
|
||||
|
||||
void D3D12CommandProcessor::NotifyShaderBindingsLayoutUIDsInvalidated() {
|
||||
if (bindless_resources_used_) {
|
||||
cbuffer_binding_descriptor_indices_vertex_.up_to_date = false;
|
||||
cbuffer_binding_descriptor_indices_pixel_.up_to_date = false;
|
||||
} else {
|
||||
bindful_textures_written_vertex_ = false;
|
||||
bindful_textures_written_pixel_ = false;
|
||||
bindful_samplers_written_vertex_ = false;
|
||||
bindful_samplers_written_pixel_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
std::string D3D12CommandProcessor::GetWindowTitleText() const {
|
||||
std::ostringstream title;
|
||||
title << "Direct3D 12";
|
||||
@@ -3052,12 +3040,8 @@ bool D3D12CommandProcessor::EndSubmission(bool is_swap) {
|
||||
|
||||
texture_cache_->ClearCache();
|
||||
|
||||
pipeline_cache_->ClearCache();
|
||||
|
||||
for (auto it : root_signatures_bindful_) {
|
||||
it.second->Release();
|
||||
}
|
||||
root_signatures_bindful_.clear();
|
||||
// Not clearing the root signatures as they're referenced by pipelines,
|
||||
// which are not destroyed.
|
||||
|
||||
primitive_processor_->ClearCache();
|
||||
|
||||
|
||||
@@ -197,9 +197,6 @@ class D3D12CommandProcessor : public CommandProcessor {
|
||||
void SetStencilReference(uint32_t stencil_ref);
|
||||
void SetPrimitiveTopology(D3D12_PRIMITIVE_TOPOLOGY primitive_topology);
|
||||
|
||||
// For the pipeline cache to call when binding layout UIDs may be reused.
|
||||
void NotifyShaderBindingsLayoutUIDsInvalidated();
|
||||
|
||||
// Returns the text to display in the GPU backend name in the window title.
|
||||
std::string GetWindowTitleText() const;
|
||||
|
||||
@@ -565,7 +562,7 @@ class D3D12CommandProcessor : public CommandProcessor {
|
||||
// Unsubmitted barrier batch.
|
||||
std::vector<D3D12_RESOURCE_BARRIER> barriers_;
|
||||
|
||||
// <Resource, submission where requested>, sorted by the submission number.
|
||||
// <Submission where requested, resource>, sorted by the submission number.
|
||||
std::deque<std::pair<uint64_t, ID3D12Resource*>> resources_for_deletion_;
|
||||
|
||||
static constexpr uint32_t kScratchBufferSizeIncrement = 16 * 1024 * 1024;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -176,56 +176,8 @@ class D3D12TextureCache final : public TextureCache {
|
||||
void UpdateTextureBindingsImpl(uint32_t fetch_constant_mask) override;
|
||||
|
||||
private:
|
||||
enum class LoadMode {
|
||||
k8bpb,
|
||||
k16bpb,
|
||||
k32bpb,
|
||||
k64bpb,
|
||||
k128bpb,
|
||||
kR5G5B5A1ToB5G5R5A1,
|
||||
kR5G6B5ToB5G6R5,
|
||||
kR5G5B6ToB5G6R5WithRBGASwizzle,
|
||||
kR4G4B4A4ToB4G4R4A4,
|
||||
kR10G11B11ToRGBA16,
|
||||
kR10G11B11ToRGBA16SNorm,
|
||||
kR11G11B10ToRGBA16,
|
||||
kR11G11B10ToRGBA16SNorm,
|
||||
kDXT1ToRGBA8,
|
||||
kDXT3ToRGBA8,
|
||||
kDXT5ToRGBA8,
|
||||
kDXNToRG8,
|
||||
kDXT3A,
|
||||
kDXT3AAs1111ToBGRA4,
|
||||
kDXT5AToR8,
|
||||
kCTX1,
|
||||
kDepthUnorm,
|
||||
kDepthFloat,
|
||||
|
||||
kCount,
|
||||
|
||||
kUnknown = kCount
|
||||
};
|
||||
|
||||
struct LoadModeInfo {
|
||||
// Shader without resolution scaling.
|
||||
const void* shader;
|
||||
size_t shader_size;
|
||||
// Shader with resolution scaling, if available. These shaders are separate
|
||||
// so the majority of the textures are not affected by the code needed for
|
||||
// resolution scale support, and also to check if the format allows
|
||||
// resolution scaling.
|
||||
const void* shader_scaled;
|
||||
size_t shader_scaled_size;
|
||||
// Log2 of the sizes, in bytes, of the source (guest) SRV and the
|
||||
// destination (host) UAV accessed by the copying shader, since the shader
|
||||
// may copy multiple blocks per one invocation.
|
||||
uint32_t srv_bpe_log2;
|
||||
uint32_t uav_bpe_log2;
|
||||
// Number of host blocks (or texels for uncompressed) along X axis written
|
||||
// by every compute shader thread - rows in the upload buffer are padded to
|
||||
// at least this amount.
|
||||
uint32_t host_x_blocks_per_thread;
|
||||
};
|
||||
static constexpr uint32_t kLoadGuestXThreadsPerGroupLog2 = 2;
|
||||
static constexpr uint32_t kLoadGuestYBlocksPerGroupLog2 = 5;
|
||||
|
||||
struct HostFormat {
|
||||
// Format info for the regular case.
|
||||
@@ -233,17 +185,17 @@ class D3D12TextureCache final : public TextureCache {
|
||||
// is used) for the texture resource.
|
||||
DXGI_FORMAT dxgi_format_resource;
|
||||
// DXGI format for unsigned normalized or unsigned/signed float SRV.
|
||||
DXGI_FORMAT dxgi_format_unorm;
|
||||
// The regular load mode, used when special modes (like signed-specific or
|
||||
// decompressing) aren't needed.
|
||||
LoadMode load_mode;
|
||||
DXGI_FORMAT dxgi_format_unsigned;
|
||||
// The regular load shader, used when special load shaders (like
|
||||
// signed-specific or decompressing) aren't needed.
|
||||
LoadShaderIndex load_shader;
|
||||
// DXGI format for signed normalized or unsigned/signed float SRV.
|
||||
DXGI_FORMAT dxgi_format_snorm;
|
||||
DXGI_FORMAT dxgi_format_signed;
|
||||
// If the signed version needs a different bit representation on the host,
|
||||
// this is the load mode for the signed version. Otherwise the regular
|
||||
// load_mode will be used for the signed version, and a single copy will be
|
||||
// created if both unsigned and signed are used.
|
||||
LoadMode load_mode_snorm;
|
||||
// this is the load shader for the signed version. Otherwise the regular
|
||||
// load_shader will be used for the signed version, and a single copy will
|
||||
// be created if both unsigned and signed are used.
|
||||
LoadShaderIndex load_shader_signed;
|
||||
|
||||
// Do NOT add integer DXGI formats to this - they are not filterable, can
|
||||
// only be read with Load, not Sample! If any game is seen using num_format
|
||||
@@ -252,8 +204,9 @@ class D3D12TextureCache final : public TextureCache {
|
||||
// textures and multiplication to the tfetch implementation.
|
||||
|
||||
// Whether the DXGI format, if not uncompressing the texture, consists of
|
||||
// blocks, thus copy regions must be aligned to block size.
|
||||
bool dxgi_format_block_aligned;
|
||||
// blocks, thus copy regions must be aligned to block size (assuming it's
|
||||
// the same as the guest block size).
|
||||
bool is_block_compressed;
|
||||
// Uncompression info for when the regular host format for this texture is
|
||||
// block-compressed, but the size is not block-aligned, and thus such
|
||||
// texture cannot be created in Direct3D on PC and needs decompression,
|
||||
@@ -261,7 +214,7 @@ class D3D12TextureCache final : public TextureCache {
|
||||
// supports unsigned normalized formats - let's hope GPUSIGN_SIGNED was not
|
||||
// used for DXN and DXT5A.
|
||||
DXGI_FORMAT dxgi_format_uncompressed;
|
||||
LoadMode decompress_mode;
|
||||
LoadShaderIndex load_shader_decompress;
|
||||
|
||||
// Mapping of Xenos swizzle components to DXGI format components.
|
||||
uint32_t swizzle;
|
||||
@@ -425,13 +378,13 @@ class D3D12TextureCache final : public TextureCache {
|
||||
const HostFormat& host_format = host_formats_[uint32_t(format)];
|
||||
return IsDecompressionNeeded(format, width, height)
|
||||
? host_format.dxgi_format_uncompressed
|
||||
: host_format.dxgi_format_unorm;
|
||||
: host_format.dxgi_format_unsigned;
|
||||
}
|
||||
static DXGI_FORMAT GetDXGIUnormFormat(TextureKey key) {
|
||||
return GetDXGIUnormFormat(key.format, key.GetWidth(), key.GetHeight());
|
||||
}
|
||||
|
||||
static LoadMode GetLoadMode(TextureKey key);
|
||||
static LoadShaderIndex GetLoadShaderIndex(TextureKey key);
|
||||
|
||||
static constexpr bool AreDimensionsCompatible(
|
||||
xenos::FetchOpDimension binding_dimension,
|
||||
@@ -513,14 +466,11 @@ class D3D12TextureCache final : public TextureCache {
|
||||
D3D12CommandProcessor& command_processor_;
|
||||
bool bindless_resources_used_;
|
||||
|
||||
static const LoadModeInfo load_mode_info_[];
|
||||
Microsoft::WRL::ComPtr<ID3D12RootSignature> load_root_signature_;
|
||||
std::array<Microsoft::WRL::ComPtr<ID3D12PipelineState>,
|
||||
size_t(LoadMode::kCount)>
|
||||
std::array<Microsoft::WRL::ComPtr<ID3D12PipelineState>, kLoadShaderCount>
|
||||
load_pipelines_;
|
||||
// Load pipelines for resolution-scaled resolve targets.
|
||||
std::array<Microsoft::WRL::ComPtr<ID3D12PipelineState>,
|
||||
size_t(LoadMode::kCount)>
|
||||
std::array<Microsoft::WRL::ComPtr<ID3D12PipelineState>, kLoadShaderCount>
|
||||
load_pipelines_scaled_;
|
||||
|
||||
std::vector<SRVDescriptorCachePage> srv_descriptor_cache_;
|
||||
|
||||
@@ -175,9 +175,8 @@ bool PipelineCache::Initialize() {
|
||||
}
|
||||
|
||||
void PipelineCache::Shutdown() {
|
||||
ClearCache(true);
|
||||
|
||||
// Shut down all threads.
|
||||
// Shut down all threads, before destroying the pipelines since they may be
|
||||
// creating them.
|
||||
if (!creation_threads_.empty()) {
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(creation_request_lock_);
|
||||
@@ -191,44 +190,11 @@ void PipelineCache::Shutdown() {
|
||||
}
|
||||
creation_completion_event_.reset();
|
||||
|
||||
ui::d3d12::util::ReleaseAndNull(dxc_compiler_);
|
||||
ui::d3d12::util::ReleaseAndNull(dxc_utils_);
|
||||
ui::d3d12::util::ReleaseAndNull(dxbc_converter_);
|
||||
}
|
||||
|
||||
void PipelineCache::ClearCache(bool shutting_down) {
|
||||
bool reinitialize_shader_storage =
|
||||
!shutting_down && storage_write_thread_ != nullptr;
|
||||
std::filesystem::path shader_storage_cache_root;
|
||||
uint32_t shader_storage_title_id = shader_storage_title_id_;
|
||||
if (reinitialize_shader_storage) {
|
||||
shader_storage_cache_root = shader_storage_cache_root_;
|
||||
}
|
||||
// Shut down the persistent shader / pipeline storage.
|
||||
ShutdownShaderStorage();
|
||||
|
||||
// Remove references to the current pipeline.
|
||||
current_pipeline_ = nullptr;
|
||||
|
||||
if (!creation_threads_.empty()) {
|
||||
// Empty the pipeline creation queue and make sure there are no threads
|
||||
// currently creating pipelines because pipelines are going to be deleted.
|
||||
bool await_creation_completion_event = false;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(creation_request_lock_);
|
||||
creation_queue_.clear();
|
||||
await_creation_completion_event = creation_threads_busy_ != 0;
|
||||
if (await_creation_completion_event) {
|
||||
creation_completion_event_->Reset();
|
||||
creation_completion_set_event_ = true;
|
||||
}
|
||||
}
|
||||
if (await_creation_completion_event) {
|
||||
creation_request_cond_.notify_one();
|
||||
xe::threading::Wait(creation_completion_event_.get(), false);
|
||||
}
|
||||
}
|
||||
|
||||
// Destroy all pipelines.
|
||||
current_pipeline_ = nullptr;
|
||||
for (auto it : pipelines_) {
|
||||
it.second->state->Release();
|
||||
delete it.second;
|
||||
@@ -237,7 +203,6 @@ void PipelineCache::ClearCache(bool shutting_down) {
|
||||
COUNT_profile_set("gpu/pipeline_cache/pipelines", 0);
|
||||
|
||||
// Destroy all shaders.
|
||||
command_processor_.NotifyShaderBindingsLayoutUIDsInvalidated();
|
||||
if (bindless_resources_used_) {
|
||||
bindless_sampler_layout_map_.clear();
|
||||
bindless_sampler_layouts_.clear();
|
||||
@@ -250,10 +215,10 @@ void PipelineCache::ClearCache(bool shutting_down) {
|
||||
shaders_.clear();
|
||||
shader_storage_index_ = 0;
|
||||
|
||||
if (reinitialize_shader_storage) {
|
||||
InitializeShaderStorage(shader_storage_cache_root, shader_storage_title_id,
|
||||
false);
|
||||
}
|
||||
// Shut down shader translation.
|
||||
ui::d3d12::util::ReleaseAndNull(dxc_compiler_);
|
||||
ui::d3d12::util::ReleaseAndNull(dxc_utils_);
|
||||
ui::d3d12::util::ReleaseAndNull(dxbc_converter_);
|
||||
}
|
||||
|
||||
void PipelineCache::InitializeShaderStorage(
|
||||
|
||||
@@ -55,7 +55,10 @@ class PipelineCache {
|
||||
|
||||
bool Initialize();
|
||||
void Shutdown();
|
||||
void ClearCache(bool shutting_down = false);
|
||||
// No ClearCache because it's undesirable with the persistent shader storage
|
||||
// (if the storage is reloaded, effectively nothing is cleared, while the call
|
||||
// takes a long time, and if it's not, there will be heavy stuttering for the
|
||||
// rest of the execution of the guest).
|
||||
|
||||
void InitializeShaderStorage(const std::filesystem::path& cache_root,
|
||||
uint32_t title_id, bool blocking);
|
||||
|
||||
Reference in New Issue
Block a user