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

This commit is contained in:
Gliniak
2022-07-03 13:07:15 +02:00
17 changed files with 124 additions and 119 deletions

View File

@@ -919,9 +919,7 @@ bool CommandProcessor::ExecutePacketType3_XE_SWAP(RingBuffer* reader,
uint32_t frontbuffer_height = reader->ReadAndSwap<uint32_t>();
reader->AdvanceRead((count - 4) * sizeof(uint32_t));
if (!ignore_swap_) {
IssueSwap(frontbuffer_ptr, frontbuffer_width, frontbuffer_height);
}
IssueSwap(frontbuffer_ptr, frontbuffer_width, frontbuffer_height);
++counter_;
return true;

View File

@@ -90,7 +90,6 @@ class CommandProcessor {
virtual void ClearCaches();
void SetIgnoreSwap(bool ignore_swap) { ignore_swap_ = ignore_swap; }
// "Desired" is for the external thread managing the post-processing effect.
SwapPostEffect GetDesiredSwapPostEffect() const {
return swap_post_effect_desired_;
@@ -265,8 +264,6 @@ class CommandProcessor {
std::atomic<bool> worker_running_;
kernel::object_ref<kernel::XHostThread> worker_thread_;
bool ignore_swap_ = false;
std::queue<std::function<void()>> pending_fns_;
// MicroEngine binary from PM4_ME_INIT

View File

@@ -1722,10 +1722,6 @@ void D3D12CommandProcessor::OnGammaRampPWLValueWritten() {
void D3D12CommandProcessor::IssueSwap(uint32_t frontbuffer_ptr,
uint32_t frontbuffer_width,
uint32_t frontbuffer_height) {
// FIXME(Triang3l): frontbuffer_ptr is currently unreliable, in the trace
// player it's set to 0, but it's not needed anyway since the fetch constant
// contains the address.
SCOPE_profile_cpu_f("gpu");
ui::Presenter* presenter = graphics_system_->presenter();
@@ -1749,12 +1745,9 @@ void D3D12CommandProcessor::IssueSwap(uint32_t frontbuffer_ptr,
}
D3D12_RESOURCE_DESC swap_texture_desc = swap_texture_resource->GetDesc();
uint32_t draw_resolution_scale_max =
std::max(texture_cache_->draw_resolution_scale_x(),
texture_cache_->draw_resolution_scale_y());
presenter->RefreshGuestOutput(
uint32_t(swap_texture_desc.Width), uint32_t(swap_texture_desc.Height),
1280 * draw_resolution_scale_max, 720 * draw_resolution_scale_max,
1280, 720,
[this, &swap_texture_srv_desc, frontbuffer_format, swap_texture_resource,
&swap_texture_desc](
ui::Presenter::GuestOutputRefreshContext& context) -> bool {

View File

@@ -1147,7 +1147,8 @@ bool D3D12TextureCache::ClampDrawResolutionScaleToMaxSupported(
}
bool D3D12TextureCache::EnsureScaledResolveMemoryCommitted(
uint32_t start_unscaled, uint32_t length_unscaled) {
uint32_t start_unscaled, uint32_t length_unscaled,
uint32_t length_scaled_alignment_log2) {
assert_true(IsDrawResolutionScaled());
if (length_unscaled == 0) {
@@ -1162,8 +1163,12 @@ bool D3D12TextureCache::EnsureScaledResolveMemoryCommitted(
uint32_t draw_resolution_scale_area =
draw_resolution_scale_x() * draw_resolution_scale_y();
uint64_t first_scaled = uint64_t(start_unscaled) * draw_resolution_scale_area;
uint64_t last_scaled = uint64_t(start_unscaled + (length_unscaled - 1)) *
draw_resolution_scale_area;
uint64_t length_scaled_alignment_bits =
(UINT64_C(1) << length_scaled_alignment_log2) - 1;
uint64_t last_scaled = (uint64_t(start_unscaled + (length_unscaled - 1)) *
draw_resolution_scale_area +
length_scaled_alignment_bits) &
~length_scaled_alignment_bits;
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Provider();
@@ -1273,7 +1278,8 @@ bool D3D12TextureCache::EnsureScaledResolveMemoryCommitted(
}
bool D3D12TextureCache::MakeScaledResolveRangeCurrent(
uint32_t start_unscaled, uint32_t length_unscaled) {
uint32_t start_unscaled, uint32_t length_unscaled,
uint32_t length_scaled_alignment_log2) {
assert_true(IsDrawResolutionScaled());
if (!length_unscaled || start_unscaled >= SharedMemory::kBufferSize ||
@@ -1286,8 +1292,12 @@ bool D3D12TextureCache::MakeScaledResolveRangeCurrent(
uint32_t draw_resolution_scale_area =
draw_resolution_scale_x() * draw_resolution_scale_y();
uint64_t start_scaled = uint64_t(start_unscaled) * draw_resolution_scale_area;
uint64_t length_scaled_alignment_bits =
(UINT64_C(1) << length_scaled_alignment_log2) - 1;
uint64_t length_scaled =
uint64_t(length_unscaled) * draw_resolution_scale_area;
(uint64_t(length_unscaled) * draw_resolution_scale_area +
length_scaled_alignment_bits) &
~length_scaled_alignment_bits;
uint64_t last_scaled = start_scaled + (length_scaled - 1);
// Get one or two buffers that can hold the whole range.
@@ -1855,7 +1865,8 @@ bool D3D12TextureCache::LoadTextureDataFromResidentMemoryImpl(Texture& texture,
if (texture_resolution_scaled && (is_base || !scaled_mips_source_set_up)) {
uint32_t guest_size_unscaled = is_base ? d3d12_texture.GetGuestBaseSize()
: d3d12_texture.GetGuestMipsSize();
if (!MakeScaledResolveRangeCurrent(guest_address, guest_size_unscaled)) {
if (!MakeScaledResolveRangeCurrent(guest_address, guest_size_unscaled,
load_shader_info.source_bpe_log2)) {
command_processor_.ReleaseScratchGPUBuffer(copy_buffer,
copy_buffer_state);
return false;

View File

@@ -130,14 +130,16 @@ class D3D12TextureCache final : public TextureCache {
uint32_t& scale_x, uint32_t& scale_y,
const ui::d3d12::D3D12Provider& provider);
// Ensures the tiles backing the range in the buffers are allocated.
bool EnsureScaledResolveMemoryCommitted(uint32_t start_unscaled,
uint32_t length_unscaled) override;
bool EnsureScaledResolveMemoryCommitted(
uint32_t start_unscaled, uint32_t length_unscaled,
uint32_t length_scaled_alignment_log2 = 0) override;
// Makes the specified range of up to 1-2 GB currently accessible on the GPU.
// One draw call can access only at most one range - the same memory is
// accessible through different buffers based on the range needed, so aliasing
// barriers are required.
bool MakeScaledResolveRangeCurrent(uint32_t start_unscaled,
uint32_t length_unscaled);
uint32_t length_unscaled,
uint32_t length_scaled_alignment_log2 = 0);
// These functions create a view of the range specified in the last successful
// MakeScaledResolveRangeCurrent call because that function must be called
// before this.

View File

@@ -3012,31 +3012,43 @@ void DxbcShaderTranslator::CompletePixelShader() {
// checked, but let's assume this means "always", not "less, equal or
// greater".
// TODO(Triang3l): Check how alpha test works with NaN on Direct3D 9.
a_.OpINE(alpha_test_op_dest, alpha_test_mask_src, dxbc::Src::LU(0b111));
a_.OpINE(alpha_test_op_dest, alpha_test_mask_src,
dxbc::Src::LU(uint32_t(xenos::CompareFunction::kAlways)));
// Don't do the test if the mode is "always".
a_.OpIf(true, alpha_test_op_src);
{
// Do the test. Can't use subtraction and sign because of float specials.
// Do the test.
dxbc::Src alpha_src(
dxbc::Src::R(system_temps_color_[0], dxbc::Src::kWWWW));
dxbc::Src alpha_test_reference_src(LoadSystemConstant(
SystemConstants::Index::kAlphaTestReference,
offsetof(SystemConstants, alpha_test_reference), dxbc::Src::kXXXX));
// Less than.
a_.OpLT(alpha_test_op_dest, alpha_src, alpha_test_reference_src);
a_.OpOr(alpha_test_op_dest, alpha_test_op_src,
dxbc::Src::LU(~uint32_t(1 << 0)));
a_.OpAnd(alpha_test_mask_dest, alpha_test_mask_src, alpha_test_op_src);
// Equals to.
a_.OpEq(alpha_test_op_dest, alpha_src, alpha_test_reference_src);
a_.OpOr(alpha_test_op_dest, alpha_test_op_src,
dxbc::Src::LU(~uint32_t(1 << 1)));
a_.OpAnd(alpha_test_mask_dest, alpha_test_mask_src, alpha_test_op_src);
// Greater than.
a_.OpLT(alpha_test_op_dest, alpha_test_reference_src, alpha_src);
a_.OpOr(alpha_test_op_dest, alpha_test_op_src,
dxbc::Src::LU(~uint32_t(1 << 2)));
a_.OpAnd(alpha_test_mask_dest, alpha_test_mask_src, alpha_test_op_src);
// Handle "not equal" specially (specifically as "not equal" so it's true
// for NaN, not "less or greater" which is false for NaN).
a_.OpIEq(alpha_test_op_dest, alpha_test_mask_src,
dxbc::Src::LU(uint32_t(xenos::CompareFunction::kNotEqual)));
a_.OpIf(true, alpha_test_op_src);
{ a_.OpNE(alpha_test_mask_dest, alpha_src, alpha_test_reference_src); }
a_.OpElse();
{
// Less than.
a_.OpLT(alpha_test_op_dest, alpha_src, alpha_test_reference_src);
a_.OpOr(alpha_test_op_dest, alpha_test_op_src,
dxbc::Src::LU(~uint32_t(1 << 0)));
a_.OpAnd(alpha_test_mask_dest, alpha_test_mask_src, alpha_test_op_src);
// Equals to.
a_.OpEq(alpha_test_op_dest, alpha_src, alpha_test_reference_src);
a_.OpOr(alpha_test_op_dest, alpha_test_op_src,
dxbc::Src::LU(~uint32_t(1 << 1)));
a_.OpAnd(alpha_test_mask_dest, alpha_test_mask_src, alpha_test_op_src);
// Greater than.
a_.OpLT(alpha_test_op_dest, alpha_test_reference_src, alpha_src);
a_.OpOr(alpha_test_op_dest, alpha_test_op_src,
dxbc::Src::LU(~uint32_t(1 << 2)));
a_.OpAnd(alpha_test_mask_dest, alpha_test_mask_src, alpha_test_op_src);
}
// Close the "not equal" check.
a_.OpEndIf();
// Discard the pixel if it has failed the test.
if (edram_rov_used_) {
a_.OpRetC(false, alpha_test_mask_src);

View File

@@ -656,6 +656,13 @@ bool TextureCache::LoadTextureData(Texture& texture) {
TextureKey texture_key = texture.key();
// Implementation may load multiple blocks at once via accesses of up to 128
// bits (R32G32B32A32_UINT), so aligning the size to this value to make sure
// if the texture is small (especially if it's linear), the last blocks won't
// be cut off (hosts may return 0, 0, 0, 0 for the whole R32G32B32A32_UINT
// access for the non-16-aligned tail even if 1...15 bytes are actually
// provided for it).
// Request uploading of the texture data to the shared memory.
// This is also necessary when resolution scaling is used - the texture cache
// relies on shared memory for invalidation of both unscaled and scaled
@@ -666,7 +673,8 @@ bool TextureCache::LoadTextureData(Texture& texture) {
bool base_resolved = texture.GetBaseResolved();
if (base_outdated) {
if (!shared_memory().RequestRange(
texture_key.base_page << 12, texture.GetGuestBaseSize(),
texture_key.base_page << 12,
xe::align(texture.GetGuestBaseSize(), UINT32_C(16)),
texture_key.scaled_resolve ? nullptr : &base_resolved)) {
return false;
}
@@ -674,7 +682,8 @@ bool TextureCache::LoadTextureData(Texture& texture) {
bool mips_resolved = texture.GetMipsResolved();
if (mips_outdated) {
if (!shared_memory().RequestRange(
texture_key.mip_page << 12, texture.GetGuestMipsSize(),
texture_key.mip_page << 12,
xe::align(texture.GetGuestMipsSize(), UINT32_C(16)),
texture_key.scaled_resolve ? nullptr : &mips_resolved)) {
return false;
}
@@ -685,11 +694,11 @@ bool TextureCache::LoadTextureData(Texture& texture) {
// by an actual resolve, but is still included in the texture size, so the
// GPU won't be trying to access unmapped memory.
if (!EnsureScaledResolveMemoryCommitted(texture_key.base_page << 12,
texture.GetGuestBaseSize())) {
texture.GetGuestBaseSize(), 4)) {
return false;
}
if (!EnsureScaledResolveMemoryCommitted(texture_key.mip_page << 12,
texture.GetGuestMipsSize())) {
texture.GetGuestMipsSize(), 4)) {
return false;
}
}

View File

@@ -82,8 +82,9 @@ class TextureCache {
void MarkRangeAsResolved(uint32_t start_unscaled, uint32_t length_unscaled);
// Ensures the memory backing the range in the scaled resolve address space is
// allocated and returns whether it is.
virtual bool EnsureScaledResolveMemoryCommitted(uint32_t start_unscaled,
uint32_t length_unscaled) {
virtual bool EnsureScaledResolveMemoryCommitted(
uint32_t start_unscaled, uint32_t length_unscaled,
uint32_t length_scaled_alignment_log2 = 0) {
return false;
}

View File

@@ -89,19 +89,15 @@ void TracePlayer::PlayTrace(const uint8_t* trace_data, size_t trace_size,
TracePlaybackMode playback_mode,
bool clear_caches) {
playing_trace_ = true;
// Pass a copy of present_last_copy_ to the thread so it's not accessible by
// multiple threads at once.
bool present_last_copy = present_last_copy_;
graphics_system_->command_processor()->CallInThread([=]() {
PlayTraceOnThread(trace_data, trace_size, playback_mode, clear_caches,
present_last_copy);
PlayTraceOnThread(trace_data, trace_size, playback_mode, clear_caches);
});
}
void TracePlayer::PlayTraceOnThread(const uint8_t* trace_data,
size_t trace_size,
TracePlaybackMode playback_mode,
bool clear_caches, bool present_last_copy) {
bool clear_caches) {
auto memory = graphics_system_->memory();
auto command_processor = graphics_system_->command_processor();
@@ -109,10 +105,6 @@ void TracePlayer::PlayTraceOnThread(const uint8_t* trace_data,
command_processor->ClearCaches();
}
if (present_last_copy) {
command_processor->SetIgnoreSwap(true);
}
playback_percent_ = 0;
auto trace_end = trace_data + trace_size;
@@ -252,11 +244,6 @@ void TracePlayer::PlayTraceOnThread(const uint8_t* trace_data,
playing_trace_ = false;
if (present_last_copy) {
command_processor->SetIgnoreSwap(false);
command_processor->IssueSwap(0, 1280, 720);
}
playback_event_->Set();
}

View File

@@ -32,9 +32,6 @@ class TracePlayer : public TraceReader {
TracePlayer(GraphicsSystem* graphics_system);
GraphicsSystem* graphics_system() const { return graphics_system_; }
void SetPresentLastCopy(bool present_last_copy) {
present_last_copy_ = present_last_copy;
}
int current_frame_index() const { return current_frame_index_; }
int current_command_index() const { return current_command_index_; }
bool is_playing_trace() const { return playing_trace_; }
@@ -53,13 +50,9 @@ class TracePlayer : public TraceReader {
void PlayTrace(const uint8_t* trace_data, size_t trace_size,
TracePlaybackMode playback_mode, bool clear_caches);
void PlayTraceOnThread(const uint8_t* trace_data, size_t trace_size,
TracePlaybackMode playback_mode, bool clear_caches,
bool present_last_copy);
TracePlaybackMode playback_mode, bool clear_caches);
GraphicsSystem* graphics_system_;
// Whether to present the results of the latest resolve instead of displaying
// the front buffer from the trace.
bool present_last_copy_ = false;
int current_frame_index_;
int current_command_index_;
bool playing_trace_ = false;

View File

@@ -114,7 +114,7 @@ bool TraceViewer::Setup() {
// Main display window.
assert_true(app_context().IsInUIThread());
window_ = xe::ui::Window::Create(app_context(), "xenia-gpu-trace-viewer",
1920, 1200);
1920, 1080);
window_->AddListener(&window_listener_);
window_->AddInputListener(&window_listener_, kZOrderTraceViewerInput);
if (!window_->Open()) {
@@ -135,28 +135,27 @@ bool TraceViewer::Setup() {
graphics_system_ = emulator_->graphics_system();
player_ = std::make_unique<TracePlayer>(graphics_system_);
player_->SetPresentLastCopy(true);
// Setup drawing to the window.
xe::ui::GraphicsProvider& graphics_provider = *graphics_system_->provider();
presenter_ = graphics_provider.CreatePresenter();
if (!presenter_) {
ui::Presenter* presenter = graphics_system_->presenter();
if (!presenter) {
XELOGE("Failed to initialize the presenter");
return false;
}
xe::ui::GraphicsProvider& graphics_provider = *graphics_system_->provider();
immediate_drawer_ = graphics_provider.CreateImmediateDrawer();
if (!immediate_drawer_) {
XELOGE("Failed to initialize the immediate drawer");
return false;
}
immediate_drawer_->SetPresenter(presenter_.get());
immediate_drawer_->SetPresenter(presenter);
imgui_drawer_ =
std::make_unique<xe::ui::ImGuiDrawer>(window_.get(), kZOrderImGui);
imgui_drawer_->SetPresenterAndImmediateDrawer(presenter_.get(),
imgui_drawer_->SetPresenterAndImmediateDrawer(presenter,
immediate_drawer_.get());
trace_viewer_dialog_ = std::unique_ptr<TraceViewerDialog>(
new TraceViewerDialog(imgui_drawer_.get(), *this));
window_->SetPresenter(presenter_.get());
window_->SetPresenter(presenter);
return true;
}

View File

@@ -21,7 +21,6 @@
#include "xenia/ui/imgui_dialog.h"
#include "xenia/ui/imgui_drawer.h"
#include "xenia/ui/immediate_drawer.h"
#include "xenia/ui/presenter.h"
#include "xenia/ui/window.h"
#include "xenia/ui/window_listener.h"
#include "xenia/ui/windowed_app.h"
@@ -129,7 +128,6 @@ class TraceViewer : public xe::ui::WindowedApp {
GraphicsSystem* graphics_system_ = nullptr;
std::unique_ptr<TracePlayer> player_;
std::unique_ptr<xe::ui::Presenter> presenter_;
std::unique_ptr<xe::ui::ImmediateDrawer> immediate_drawer_;
std::unique_ptr<xe::ui::ImGuiDrawer> imgui_drawer_;
std::unique_ptr<TraceViewerDialog> trace_viewer_dialog_;

View File

@@ -269,11 +269,6 @@ void VulkanCommandProcessor::IssueSwap(uint32_t frontbuffer_ptr,
return;
}
if (!frontbuffer_ptr) {
// Trace viewer does this.
frontbuffer_ptr = last_copy_base_;
}
std::vector<VkCommandBuffer> submit_buffers;
if (frame_open_) {
// TODO(DrChat): If the setup buffer is empty, don't bother queueing it up.
@@ -1108,9 +1103,6 @@ bool VulkanCommandProcessor::IssueCopy() {
texture->in_flight_fence = current_batch_fence_;
// For debugging purposes only (trace viewer)
last_copy_base_ = texture->texture_info.memory.base_address;
if (!frame_open_) {
BeginFrame();
} else if (current_render_state_) {

View File

@@ -106,9 +106,6 @@ class VulkanCommandProcessor : public CommandProcessor {
uint32_t coher_base_vc_ = 0;
uint32_t coher_size_vc_ = 0;
// Last copy base address, for debugging only.
uint32_t last_copy_base_ = 0;
bool capturing_ = false;
bool trace_requested_ = false;
bool cache_clear_requested_ = false;