Files
Xenia-Canary/src/xenia/gpu/gl4/command_processor.h

313 lines
11 KiB
C++

/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2014 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_GPU_GL4_COMMAND_PROCESSOR_H_
#define XENIA_GPU_GL4_COMMAND_PROCESSOR_H_
#include <atomic>
#include <functional>
#include <memory>
#include <thread>
#include <unordered_map>
#include <vector>
#include <xenia/gpu/gl4/circular_buffer.h>
#include <xenia/gpu/gl4/gl_context.h>
#include <xenia/gpu/gl4/gl4_shader.h>
#include <xenia/gpu/gl4/texture_cache.h>
#include <xenia/gpu/register_file.h>
#include <xenia/gpu/xenos.h>
#include <xenia/memory.h>
namespace xe {
namespace gpu {
namespace gl4 {
class GL4GraphicsSystem;
struct SwapParameters {
uint32_t x;
uint32_t y;
uint32_t width;
uint32_t height;
GLuint framebuffer;
GLenum attachment;
};
// This must match the layout in gl4_shader.cc.
struct UniformDataBlock {
union float4 {
float v[4];
struct {
float x, y, z, w;
};
};
float4 window_offset; // tx,ty,sx,sy
float4 window_scissor; // x0,y0,x1,y1
float4 vtx_fmt;
float4 viewport_offset; // tx,ty,tz,?
float4 viewport_scale; // sx,sy,sz,?
// TODO(benvanik): vertex format xyzw?
float4 alpha_test; // alpha test enable, func, ref, ?
// TODO(benvanik): overlay with fetch_consts below?
uint64_t texture_samplers[32];
// Register data from 0x4000 to 0x4927.
// SHADER_CONSTANT_000_X...
float4 float_consts[512];
// SHADER_CONSTANT_FETCH_00_0...
uint32_t fetch_consts[32 * 6];
// SHADER_CONSTANT_BOOL_000_031...
int32_t bool_consts[8];
// SHADER_CONSTANT_LOOP_00...
int32_t loop_consts[32];
};
static_assert(sizeof(UniformDataBlock) <= 16 * 1024,
"Need <=16k uniform data");
// TODO(benvanik): move more of the enums in here?
struct DrawCommand {
PrimitiveType prim_type;
uint32_t start_index;
uint32_t min_index;
uint32_t max_index;
uint32_t index_count;
uint32_t base_vertex;
// Index buffer, if present.
// If index_count > 0 but buffer is nullptr then auto draw.
struct {
const uint8_t* address;
size_t size;
xenos::Endian endianness;
xenos::IndexFormat format;
size_t buffer_offset;
} index_buffer;
// Texture samplers.
struct SamplerInput {
uint32_t input_index;
// TextureResource* texture;
// SamplerStateResource* sampler_state;
};
SamplerInput vertex_shader_samplers[32];
SamplerInput pixel_shader_samplers[32];
UniformDataBlock* state_data;
};
class CommandProcessor {
public:
CommandProcessor(GL4GraphicsSystem* graphics_system);
~CommandProcessor();
typedef std::function<void(const SwapParameters& params)> SwapHandler;
void set_swap_handler(SwapHandler fn) { swap_handler_ = fn; }
uint64_t QueryTime();
uint32_t counter() const { return counter_; }
void increment_counter() { counter_++; }
bool Initialize(std::unique_ptr<GLContext> context);
void Shutdown();
void InitializeRingBuffer(uint32_t ptr, uint32_t page_count);
void EnableReadPointerWriteBack(uint32_t ptr, uint32_t block_size);
void UpdateWritePointer(uint32_t value);
private:
class RingbufferReader;
struct CachedFramebuffer {
GLuint color_targets[4];
GLuint depth_target;
GLuint framebuffer;
};
struct CachedColorRenderTarget {
uint32_t base;
uint32_t width;
uint32_t height;
xenos::ColorRenderTargetFormat format;
GLuint texture;
};
struct CachedDepthRenderTarget {
uint32_t base;
uint32_t width;
uint32_t height;
xenos::DepthRenderTargetFormat format;
GLuint texture;
};
struct CachedPipeline {
CachedPipeline();
~CachedPipeline();
GLuint vertex_program;
GLuint fragment_program;
struct {
GLuint default_pipeline;
GLuint point_list_pipeline;
GLuint rect_list_pipeline;
GLuint quad_list_pipeline;
// TODO(benvanik): others with geometry shaders.
} handles;
};
void WorkerMain();
bool SetupGL();
void ShutdownGL();
GLuint CreateGeometryProgram(const std::string& source);
void WriteRegister(uint32_t packet_ptr, uint32_t index, uint32_t value);
void MakeCoherent();
void PrepareForWait();
void ReturnFromWait();
void ExecutePrimaryBuffer(uint32_t start_index, uint32_t end_index);
void ExecuteIndirectBuffer(uint32_t ptr, uint32_t length);
bool ExecutePacket(RingbufferReader* reader);
bool ExecutePacketType0(RingbufferReader* reader, uint32_t packet_ptr,
uint32_t packet);
bool ExecutePacketType1(RingbufferReader* reader, uint32_t packet_ptr,
uint32_t packet);
bool ExecutePacketType2(RingbufferReader* reader, uint32_t packet_ptr,
uint32_t packet);
bool ExecutePacketType3(RingbufferReader* reader, uint32_t packet_ptr,
uint32_t packet);
bool ExecutePacketType3_ME_INIT(RingbufferReader* reader, uint32_t packet_ptr,
uint32_t packet, uint32_t count);
bool ExecutePacketType3_NOP(RingbufferReader* reader, uint32_t packet_ptr,
uint32_t packet, uint32_t count);
bool ExecutePacketType3_INTERRUPT(RingbufferReader* reader,
uint32_t packet_ptr, uint32_t packet,
uint32_t count);
bool ExecutePacketType3_XE_SWAP(RingbufferReader* reader, uint32_t packet_ptr,
uint32_t packet, uint32_t count);
bool ExecutePacketType3_INDIRECT_BUFFER(RingbufferReader* reader,
uint32_t packet_ptr, uint32_t packet,
uint32_t count);
bool ExecutePacketType3_WAIT_REG_MEM(RingbufferReader* reader,
uint32_t packet_ptr, uint32_t packet,
uint32_t count);
bool ExecutePacketType3_REG_RMW(RingbufferReader* reader, uint32_t packet_ptr,
uint32_t packet, uint32_t count);
bool ExecutePacketType3_COND_WRITE(RingbufferReader* reader,
uint32_t packet_ptr, uint32_t packet,
uint32_t count);
bool ExecutePacketType3_EVENT_WRITE(RingbufferReader* reader,
uint32_t packet_ptr, uint32_t packet,
uint32_t count);
bool ExecutePacketType3_EVENT_WRITE_SHD(RingbufferReader* reader,
uint32_t packet_ptr, uint32_t packet,
uint32_t count);
bool ExecutePacketType3_DRAW_INDX(RingbufferReader* reader,
uint32_t packet_ptr, uint32_t packet,
uint32_t count);
bool ExecutePacketType3_DRAW_INDX_2(RingbufferReader* reader,
uint32_t packet_ptr, uint32_t packet,
uint32_t count);
bool ExecutePacketType3_SET_CONSTANT(RingbufferReader* reader,
uint32_t packet_ptr, uint32_t packet,
uint32_t count);
bool ExecutePacketType3_LOAD_ALU_CONSTANT(RingbufferReader* reader,
uint32_t packet_ptr,
uint32_t packet, uint32_t count);
bool ExecutePacketType3_IM_LOAD(RingbufferReader* reader, uint32_t packet_ptr,
uint32_t packet, uint32_t count);
bool ExecutePacketType3_IM_LOAD_IMMEDIATE(RingbufferReader* reader,
uint32_t packet_ptr,
uint32_t packet, uint32_t count);
bool ExecutePacketType3_INVALIDATE_STATE(RingbufferReader* reader,
uint32_t packet_ptr, uint32_t packet,
uint32_t count);
bool LoadShader(ShaderType shader_type, const uint32_t* address,
uint32_t dword_count);
void PrepareDraw(DrawCommand* draw_command);
bool IssueDraw(DrawCommand* draw_command);
bool UpdateRenderTargets(DrawCommand* draw_command);
bool UpdateState(DrawCommand* draw_command);
bool UpdateConstants(DrawCommand* draw_command);
bool UpdateShaders(DrawCommand* draw_command);
bool PopulateIndexBuffer(DrawCommand* draw_command);
bool PopulateVertexBuffers(DrawCommand* draw_command);
bool PopulateSamplers(DrawCommand* draw_command);
bool PopulateSampler(DrawCommand* draw_command,
const Shader::SamplerDesc& desc);
bool IssueCopy(DrawCommand* draw_command);
CachedFramebuffer* GetFramebuffer(GLuint color_targets[4],
GLuint depth_target);
GLuint GetColorRenderTarget(uint32_t pitch, xenos::MsaaSamples samples,
uint32_t base,
xenos::ColorRenderTargetFormat format);
GLuint GetDepthRenderTarget(uint32_t pitch, xenos::MsaaSamples samples,
uint32_t base,
xenos::DepthRenderTargetFormat format);
Memory* memory_;
uint8_t* membase_;
GL4GraphicsSystem* graphics_system_;
RegisterFile* register_file_;
std::thread worker_thread_;
std::atomic<bool> worker_running_;
std::unique_ptr<GLContext> context_;
SwapHandler swap_handler_;
uint64_t time_base_;
uint32_t counter_;
uint32_t primary_buffer_ptr_;
uint32_t primary_buffer_size_;
uint32_t read_ptr_index_;
uint32_t read_ptr_update_freq_;
uint32_t read_ptr_writeback_ptr_;
HANDLE write_ptr_index_event_;
std::atomic<uint32_t> write_ptr_index_;
uint64_t bin_select_;
uint64_t bin_mask_;
bool has_bindless_vbos_;
std::vector<std::unique_ptr<GL4Shader>> all_shaders_;
std::unordered_map<uint64_t, GL4Shader*> shader_cache_;
GL4Shader* active_vertex_shader_;
GL4Shader* active_pixel_shader_;
CachedPipeline* active_pipeline_;
CachedFramebuffer* active_framebuffer_;
std::vector<CachedFramebuffer> cached_framebuffers_;
std::vector<CachedColorRenderTarget> cached_color_render_targets_;
std::vector<CachedDepthRenderTarget> cached_depth_render_targets_;
std::vector<std::unique_ptr<CachedPipeline>> all_pipelines_;
std::unordered_map<uint64_t, CachedPipeline*> cached_pipelines_;
GLuint vertex_array_;
GLuint point_list_geometry_program_;
GLuint rect_list_geometry_program_;
GLuint quad_list_geometry_program_;
TextureCache texture_cache_;
CircularBuffer scratch_buffer_;
DrawCommand draw_command_;
};
} // namespace gl4
} // namespace gpu
} // namespace xe
#endif // XENIA_GPU_GL4_COMMAND_PROCESSOR_H_