95% of trace viewer now gpu backend agnostic.

This commit is contained in:
Ben Vanik 2015-11-08 14:05:37 -08:00
parent b5a18b5462
commit 9a6c5c5c74
7 changed files with 1660 additions and 1485 deletions

View File

@ -1079,8 +1079,20 @@ bool CommandProcessor::ExecutePacketType3_IM_LOAD(RingbufferReader* reader,
uint32_t size_dwords = start_size & 0xFFFF; // dwords
assert_true(start == 0);
trace_writer_.WriteMemoryRead(CpuToGpu(addr), size_dwords * 4);
LoadShader(shader_type, addr, memory_->TranslatePhysical<uint32_t*>(addr),
size_dwords);
auto shader =
LoadShader(shader_type, addr, memory_->TranslatePhysical<uint32_t*>(addr),
size_dwords);
switch (shader_type) {
case ShaderType::kVertex:
active_vertex_shader_ = shader;
break;
case ShaderType::kPixel:
active_pixel_shader_ = shader;
break;
default:
assert_unhandled_case(shader_type);
return false;
}
return true;
}
@ -1095,8 +1107,20 @@ bool CommandProcessor::ExecutePacketType3_IM_LOAD_IMMEDIATE(
uint32_t size_dwords = start_size & 0xFFFF; // dwords
assert_true(start == 0);
reader->CheckRead(size_dwords);
LoadShader(shader_type, reader->ptr(),
memory_->TranslatePhysical<uint32_t*>(reader->ptr()), size_dwords);
auto shader = LoadShader(shader_type, reader->ptr(),
memory_->TranslatePhysical<uint32_t*>(reader->ptr()),
size_dwords);
switch (shader_type) {
case ShaderType::kVertex:
active_vertex_shader_ = shader;
break;
case ShaderType::kPixel:
active_pixel_shader_ = shader;
break;
default:
assert_unhandled_case(shader_type);
return false;
}
reader->Advance(size_dwords);
return true;
}

View File

@ -31,6 +31,7 @@ namespace xe {
namespace gpu {
class GraphicsSystem;
class Shader;
struct SwapState {
// Lock must be held when changing data in this structure.
@ -60,6 +61,9 @@ class CommandProcessor {
uint32_t counter() const { return counter_; }
void increment_counter() { counter_++; }
Shader* active_vertex_shader() const { return active_vertex_shader_; }
Shader* active_pixel_shader() const { return active_pixel_shader_; }
virtual bool Initialize(std::unique_ptr<xe::ui::GraphicsContext> context);
virtual void Shutdown();
@ -160,9 +164,9 @@ class CommandProcessor {
bool ExecutePacketType3_INVALIDATE_STATE(RingbufferReader* reader,
uint32_t packet, uint32_t count);
virtual bool LoadShader(ShaderType shader_type, uint32_t guest_address,
const uint32_t* host_address,
uint32_t dword_count) = 0;
virtual Shader* LoadShader(ShaderType shader_type, uint32_t guest_address,
const uint32_t* host_address,
uint32_t dword_count) = 0;
virtual bool IssueDraw(PrimitiveType prim_type, uint32_t index_count,
IndexBufferInfo* index_buffer_info) = 0;
@ -205,6 +209,9 @@ class CommandProcessor {
uint64_t bin_select_ = 0xFFFFFFFFull;
uint64_t bin_mask_ = 0xFFFFFFFFull;
Shader* active_vertex_shader_ = nullptr;
Shader* active_pixel_shader_ = nullptr;
};
} // namespace gpu

View File

@ -463,10 +463,10 @@ void GL4CommandProcessor::PerformSwap(uint32_t frontbuffer_ptr,
texture_cache_.Scavenge();
}
bool GL4CommandProcessor::LoadShader(ShaderType shader_type,
uint32_t guest_address,
const uint32_t* host_address,
uint32_t dword_count) {
Shader* GL4CommandProcessor::LoadShader(ShaderType shader_type,
uint32_t guest_address,
const uint32_t* host_address,
uint32_t dword_count) {
// Hash the input memory and lookup the shader.
GL4Shader* shader_ptr = nullptr;
uint64_t hash = XXH64(host_address, dword_count * sizeof(uint32_t), 0);
@ -489,18 +489,7 @@ bool GL4CommandProcessor::LoadShader(ShaderType shader_type,
guest_address, dword_count * 4,
shader_ptr->ucode_disassembly().c_str());
}
switch (shader_type) {
case ShaderType::kVertex:
active_vertex_shader_ = shader_ptr;
break;
case ShaderType::kPixel:
active_pixel_shader_ = shader_ptr;
break;
default:
assert_unhandled_case(shader_type);
return false;
}
return true;
return shader_ptr;
}
bool GL4CommandProcessor::IssueDraw(PrimitiveType prim_type,
@ -622,8 +611,8 @@ GL4CommandProcessor::UpdateStatus GL4CommandProcessor::UpdateShaders(
if (!dirty) {
return UpdateStatus::kCompatible;
}
regs.vertex_shader = active_vertex_shader_;
regs.pixel_shader = active_pixel_shader_;
regs.vertex_shader = static_cast<GL4Shader*>(active_vertex_shader_);
regs.pixel_shader = static_cast<GL4Shader*>(active_pixel_shader_);
regs.prim_type = prim_type;
SCOPE_profile_cpu_f("gpu");
@ -632,30 +621,30 @@ GL4CommandProcessor::UpdateStatus GL4CommandProcessor::UpdateShaders(
xe_gpu_program_cntl_t program_cntl;
program_cntl.dword_0 = regs.sq_program_cntl;
if (!active_vertex_shader_->has_prepared()) {
if (!active_vertex_shader_->PrepareVertexShader(&shader_translator_,
program_cntl)) {
if (!regs.vertex_shader->has_prepared()) {
if (!regs.vertex_shader->PrepareVertexShader(&shader_translator_,
program_cntl)) {
XELOGE("Unable to prepare vertex shader");
return UpdateStatus::kError;
}
} else if (!active_vertex_shader_->is_valid()) {
} else if (!regs.vertex_shader->is_valid()) {
XELOGE("Vertex shader invalid");
return UpdateStatus::kError;
}
if (!active_pixel_shader_->has_prepared()) {
if (!active_pixel_shader_->PreparePixelShader(&shader_translator_,
program_cntl)) {
if (!regs.pixel_shader->has_prepared()) {
if (!regs.pixel_shader->PreparePixelShader(&shader_translator_,
program_cntl)) {
XELOGE("Unable to prepare pixel shader");
return UpdateStatus::kError;
}
} else if (!active_pixel_shader_->is_valid()) {
} else if (!regs.pixel_shader->is_valid()) {
XELOGE("Pixel shader invalid");
return UpdateStatus::kError;
}
GLuint vertex_program = active_vertex_shader_->program();
GLuint fragment_program = active_pixel_shader_->program();
GLuint vertex_program = regs.vertex_shader->program();
GLuint fragment_program = regs.pixel_shader->program();
uint64_t key = (uint64_t(vertex_program) << 32) | fragment_program;
CachedPipeline* cached_pipeline = nullptr;
@ -707,7 +696,7 @@ GL4CommandProcessor::UpdateStatus GL4CommandProcessor::UpdateShaders(
cached_pipeline->handles.line_quad_list_pipeline = pipelines[4];
// This can be set once, as the buffer never changes.
glVertexArrayElementBuffer(active_vertex_shader_->vao(),
glVertexArrayElementBuffer(regs.vertex_shader->vao(),
scratch_buffer_.handle());
}
@ -741,11 +730,11 @@ GL4CommandProcessor::UpdateStatus GL4CommandProcessor::UpdateShaders(
}
}
draw_batcher_.ReconfigurePipeline(active_vertex_shader_, active_pixel_shader_,
draw_batcher_.ReconfigurePipeline(regs.vertex_shader, regs.pixel_shader,
pipeline);
glBindProgramPipeline(pipeline);
glBindVertexArray(active_vertex_shader_->vao());
glBindVertexArray(regs.vertex_shader->vao());
return UpdateStatus::kMismatch;
}
@ -1394,6 +1383,7 @@ GL4CommandProcessor::UpdateStatus GL4CommandProcessor::PopulateVertexBuffers() {
trace_writer_.WriteMemoryRead(fetch->address << 2, valid_range);
auto vertex_shader = static_cast<GL4Shader*>(active_vertex_shader_);
CircularBuffer::Allocation allocation;
if (!scratch_buffer_.AcquireCached(fetch->address << 2, valid_range,
&allocation)) {
@ -1408,7 +1398,7 @@ GL4CommandProcessor::UpdateStatus GL4CommandProcessor::PopulateVertexBuffers() {
// TODO(benvanik): if we could find a way to avoid this, we could use
// multidraw without flushing.
glVertexArrayVertexBuffer(active_vertex_shader_->vao(), buffer_index,
glVertexArrayVertexBuffer(vertex_shader->vao(), buffer_index,
scratch_buffer_.handle(), allocation.offset,
desc.stride_words * 4);
@ -1416,7 +1406,7 @@ GL4CommandProcessor::UpdateStatus GL4CommandProcessor::PopulateVertexBuffers() {
} else {
// TODO(benvanik): if we could find a way to avoid this, we could use
// multidraw without flushing.
glVertexArrayVertexBuffer(active_vertex_shader_->vao(), buffer_index,
glVertexArrayVertexBuffer(vertex_shader->vao(), buffer_index,
scratch_buffer_.handle(), allocation.offset,
desc.stride_words * 4);
}

View File

@ -49,8 +49,6 @@ class GL4CommandProcessor : public CommandProcessor {
// HACK: for debugging; would be good to have this in a base type.
TextureCache* texture_cache() { return &texture_cache_; }
GL4Shader* active_vertex_shader() const { return active_vertex_shader_; }
GL4Shader* active_pixel_shader() const { return active_pixel_shader_; }
GLuint GetColorRenderTarget(uint32_t pitch, xenos::MsaaSamples samples,
uint32_t base,
@ -111,8 +109,9 @@ class GL4CommandProcessor : public CommandProcessor {
void PerformSwap(uint32_t frontbuffer_ptr, uint32_t frontbuffer_width,
uint32_t frontbuffer_height) override;
bool LoadShader(ShaderType shader_type, uint32_t guest_address,
const uint32_t* host_address, uint32_t dword_count) override;
Shader* LoadShader(ShaderType shader_type, uint32_t guest_address,
const uint32_t* host_address,
uint32_t dword_count) override;
bool IssueDraw(PrimitiveType prim_type, uint32_t index_count,
IndexBufferInfo* index_buffer_info) override;
@ -135,8 +134,6 @@ class GL4CommandProcessor : public CommandProcessor {
GL4ShaderTranslator shader_translator_;
std::vector<std::unique_ptr<GL4Shader>> all_shaders_;
std::unordered_map<uint64_t, GL4Shader*> shader_cache_;
GL4Shader* active_vertex_shader_ = nullptr;
GL4Shader* active_pixel_shader_ = nullptr;
CachedFramebuffer* active_framebuffer_ = nullptr;
GLuint last_framebuffer_texture_ = 0;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,97 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_GPU_TRACE_VIEWER_H_
#define XENIA_GPU_TRACE_VIEWER_H_
#include <string>
#include "xenia/emulator.h"
#include "xenia/gpu/shader.h"
#include "xenia/gpu/trace_player.h"
#include "xenia/gpu/trace_protocol.h"
#include "xenia/gpu/xenos.h"
#include "xenia/memory.h"
namespace xe {
namespace ui {
class ImGuiDrawer;
class Loop;
class Window;
} // namespace ui
} // namespace xe
namespace xe {
namespace gpu {
struct SamplerInfo;
struct TextureInfo;
class TraceViewer {
public:
virtual ~TraceViewer();
bool Setup();
bool Load(std::wstring trace_file_path);
void Run();
protected:
TraceViewer();
void DrawMultilineString(const std::string& str);
virtual uintptr_t GetColorRenderTarget(
uint32_t pitch, xenos::MsaaSamples samples, uint32_t base,
xenos::ColorRenderTargetFormat format) = 0;
virtual uintptr_t GetDepthRenderTarget(
uint32_t pitch, xenos::MsaaSamples samples, uint32_t base,
xenos::DepthRenderTargetFormat format) = 0;
virtual uintptr_t GetTextureEntry(const TextureInfo& texture_info,
const SamplerInfo& sampler_info) = 0;
std::unique_ptr<xe::ui::Loop> loop_;
std::unique_ptr<xe::ui::Window> window_;
std::unique_ptr<Emulator> emulator_;
Memory* memory_ = nullptr;
GraphicsSystem* graphics_system_ = nullptr;
std::unique_ptr<TracePlayer> player_;
std::unique_ptr<xe::ui::ImGuiDrawer> imgui_drawer_;
private:
enum class ShaderDisplayType : int {
kUcode,
kTranslated,
kHostDisasm,
};
void DrawUI();
void DrawControllerUI();
void DrawPacketDisassemblerUI();
void DrawCommandListUI();
void DrawStateUI();
ShaderDisplayType DrawShaderTypeUI();
void DrawShaderUI(Shader* shader, ShaderDisplayType display_type);
void DrawBlendMode(uint32_t src_blend, uint32_t dest_blend,
uint32_t blend_op);
void DrawTextureInfo(const Shader::SamplerDesc& desc);
void DrawFailedTextureInfo(const Shader::SamplerDesc& desc,
const char* message);
void DrawVertexFetcher(Shader* shader, const Shader::BufferDesc& desc,
const xenos::xe_gpu_vertex_fetch_t* fetch);
};
} // namespace gpu
} // namespace xe
#endif // XENIA_GPU_TRACE_VIEWER_H_