9 changed files with 292 additions and 264 deletions
-
1src/video_core/CMakeLists.txt
-
51src/video_core/command_processor.cpp
-
2src/video_core/pica.cpp
-
230src/video_core/pica.h
-
18src/video_core/primitive_assembly.cpp
-
9src/video_core/primitive_assembly.h
-
224src/video_core/regs_pipeline.h
-
15src/video_core/vertex_loader.cpp
-
6src/video_core/vertex_loader.h
@ -0,0 +1,224 @@ |
|||||
|
// Copyright 2017 Citra Emulator Project |
||||
|
// Licensed under GPLv2 or any later version |
||||
|
// Refer to the license.txt file included. |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include <array> |
||||
|
|
||||
|
#include "common/assert.h" |
||||
|
#include "common/bit_field.h" |
||||
|
#include "common/common_funcs.h" |
||||
|
#include "common/common_types.h" |
||||
|
|
||||
|
namespace Pica { |
||||
|
|
||||
|
struct PipelineRegs { |
||||
|
enum class VertexAttributeFormat : u64 { |
||||
|
BYTE = 0, |
||||
|
UBYTE = 1, |
||||
|
SHORT = 2, |
||||
|
FLOAT = 3, |
||||
|
}; |
||||
|
|
||||
|
struct { |
||||
|
BitField<0, 29, u32> base_address; |
||||
|
|
||||
|
PAddr GetPhysicalBaseAddress() const { |
||||
|
return base_address * 8; |
||||
|
} |
||||
|
|
||||
|
// Descriptor for internal vertex attributes |
||||
|
union { |
||||
|
BitField<0, 2, VertexAttributeFormat> format0; // size of one element |
||||
|
BitField<2, 2, u64> size0; // number of elements minus 1 |
||||
|
BitField<4, 2, VertexAttributeFormat> format1; |
||||
|
BitField<6, 2, u64> size1; |
||||
|
BitField<8, 2, VertexAttributeFormat> format2; |
||||
|
BitField<10, 2, u64> size2; |
||||
|
BitField<12, 2, VertexAttributeFormat> format3; |
||||
|
BitField<14, 2, u64> size3; |
||||
|
BitField<16, 2, VertexAttributeFormat> format4; |
||||
|
BitField<18, 2, u64> size4; |
||||
|
BitField<20, 2, VertexAttributeFormat> format5; |
||||
|
BitField<22, 2, u64> size5; |
||||
|
BitField<24, 2, VertexAttributeFormat> format6; |
||||
|
BitField<26, 2, u64> size6; |
||||
|
BitField<28, 2, VertexAttributeFormat> format7; |
||||
|
BitField<30, 2, u64> size7; |
||||
|
BitField<32, 2, VertexAttributeFormat> format8; |
||||
|
BitField<34, 2, u64> size8; |
||||
|
BitField<36, 2, VertexAttributeFormat> format9; |
||||
|
BitField<38, 2, u64> size9; |
||||
|
BitField<40, 2, VertexAttributeFormat> format10; |
||||
|
BitField<42, 2, u64> size10; |
||||
|
BitField<44, 2, VertexAttributeFormat> format11; |
||||
|
BitField<46, 2, u64> size11; |
||||
|
|
||||
|
BitField<48, 12, u64> attribute_mask; |
||||
|
|
||||
|
// number of total attributes minus 1 |
||||
|
BitField<60, 4, u64> max_attribute_index; |
||||
|
}; |
||||
|
|
||||
|
inline VertexAttributeFormat GetFormat(int n) const { |
||||
|
VertexAttributeFormat formats[] = {format0, format1, format2, format3, |
||||
|
format4, format5, format6, format7, |
||||
|
format8, format9, format10, format11}; |
||||
|
return formats[n]; |
||||
|
} |
||||
|
|
||||
|
inline int GetNumElements(int n) const { |
||||
|
u64 sizes[] = {size0, size1, size2, size3, size4, size5, |
||||
|
size6, size7, size8, size9, size10, size11}; |
||||
|
return (int)sizes[n] + 1; |
||||
|
} |
||||
|
|
||||
|
inline int GetElementSizeInBytes(int n) const { |
||||
|
return (GetFormat(n) == VertexAttributeFormat::FLOAT) |
||||
|
? 4 |
||||
|
: (GetFormat(n) == VertexAttributeFormat::SHORT) ? 2 : 1; |
||||
|
} |
||||
|
|
||||
|
inline int GetStride(int n) const { |
||||
|
return GetNumElements(n) * GetElementSizeInBytes(n); |
||||
|
} |
||||
|
|
||||
|
inline bool IsDefaultAttribute(int id) const { |
||||
|
return (id >= 12) || (attribute_mask & (1ULL << id)) != 0; |
||||
|
} |
||||
|
|
||||
|
inline int GetNumTotalAttributes() const { |
||||
|
return (int)max_attribute_index + 1; |
||||
|
} |
||||
|
|
||||
|
// Attribute loaders map the source vertex data to input attributes |
||||
|
// This e.g. allows to load different attributes from different memory locations |
||||
|
struct { |
||||
|
// Source attribute data offset from the base address |
||||
|
u32 data_offset; |
||||
|
|
||||
|
union { |
||||
|
BitField<0, 4, u64> comp0; |
||||
|
BitField<4, 4, u64> comp1; |
||||
|
BitField<8, 4, u64> comp2; |
||||
|
BitField<12, 4, u64> comp3; |
||||
|
BitField<16, 4, u64> comp4; |
||||
|
BitField<20, 4, u64> comp5; |
||||
|
BitField<24, 4, u64> comp6; |
||||
|
BitField<28, 4, u64> comp7; |
||||
|
BitField<32, 4, u64> comp8; |
||||
|
BitField<36, 4, u64> comp9; |
||||
|
BitField<40, 4, u64> comp10; |
||||
|
BitField<44, 4, u64> comp11; |
||||
|
|
||||
|
// bytes for a single vertex in this loader |
||||
|
BitField<48, 8, u64> byte_count; |
||||
|
|
||||
|
BitField<60, 4, u64> component_count; |
||||
|
}; |
||||
|
|
||||
|
inline int GetComponent(int n) const { |
||||
|
u64 components[] = {comp0, comp1, comp2, comp3, comp4, comp5, |
||||
|
comp6, comp7, comp8, comp9, comp10, comp11}; |
||||
|
return (int)components[n]; |
||||
|
} |
||||
|
} attribute_loaders[12]; |
||||
|
} vertex_attributes; |
||||
|
|
||||
|
struct { |
||||
|
enum IndexFormat : u32 { |
||||
|
BYTE = 0, |
||||
|
SHORT = 1, |
||||
|
}; |
||||
|
|
||||
|
union { |
||||
|
BitField<0, 31, u32> offset; // relative to base attribute address |
||||
|
BitField<31, 1, IndexFormat> format; |
||||
|
}; |
||||
|
} index_array; |
||||
|
|
||||
|
// Number of vertices to render |
||||
|
u32 num_vertices; |
||||
|
|
||||
|
INSERT_PADDING_WORDS(0x1); |
||||
|
|
||||
|
// The index of the first vertex to render |
||||
|
u32 vertex_offset; |
||||
|
|
||||
|
INSERT_PADDING_WORDS(0x3); |
||||
|
|
||||
|
// These two trigger rendering of triangles |
||||
|
u32 trigger_draw; |
||||
|
u32 trigger_draw_indexed; |
||||
|
|
||||
|
INSERT_PADDING_WORDS(0x2); |
||||
|
|
||||
|
// These registers are used to setup the default "fall-back" vertex shader attributes |
||||
|
struct { |
||||
|
// Index of the current default attribute |
||||
|
u32 index; |
||||
|
|
||||
|
// Writing to these registers sets the "current" default attribute. |
||||
|
u32 set_value[3]; |
||||
|
} vs_default_attributes_setup; |
||||
|
|
||||
|
INSERT_PADDING_WORDS(0x2); |
||||
|
|
||||
|
struct { |
||||
|
// There are two channels that can be used to configure the next command buffer, which can |
||||
|
// be then executed by writing to the "trigger" registers. There are two reasons why a game |
||||
|
// might use this feature: |
||||
|
// 1) With this, an arbitrary number of additional command buffers may be executed in |
||||
|
// sequence without requiring any intervention of the CPU after the initial one is |
||||
|
// kicked off. |
||||
|
// 2) Games can configure these registers to provide a command list subroutine mechanism. |
||||
|
|
||||
|
BitField<0, 20, u32> size[2]; ///< Size (in bytes / 8) of each channel's command buffer |
||||
|
BitField<0, 28, u32> addr[2]; ///< Physical address / 8 of each channel's command buffer |
||||
|
u32 trigger[2]; ///< Triggers execution of the channel's command buffer when written to |
||||
|
|
||||
|
unsigned GetSize(unsigned index) const { |
||||
|
ASSERT(index < 2); |
||||
|
return 8 * size[index]; |
||||
|
} |
||||
|
|
||||
|
PAddr GetPhysicalAddress(unsigned index) const { |
||||
|
ASSERT(index < 2); |
||||
|
return (PAddr)(8 * addr[index]); |
||||
|
} |
||||
|
} command_buffer; |
||||
|
|
||||
|
INSERT_PADDING_WORDS(4); |
||||
|
|
||||
|
/// Number of input attributes to the vertex shader minus 1 |
||||
|
BitField<0, 4, u32> max_input_attrib_index; |
||||
|
|
||||
|
INSERT_PADDING_WORDS(2); |
||||
|
|
||||
|
enum class GPUMode : u32 { |
||||
|
Drawing = 0, |
||||
|
Configuring = 1, |
||||
|
}; |
||||
|
|
||||
|
GPUMode gpu_mode; |
||||
|
|
||||
|
INSERT_PADDING_WORDS(0x18); |
||||
|
|
||||
|
enum class TriangleTopology : u32 { |
||||
|
List = 0, |
||||
|
Strip = 1, |
||||
|
Fan = 2, |
||||
|
Shader = 3, // Programmable setup unit implemented in a geometry shader |
||||
|
}; |
||||
|
|
||||
|
BitField<8, 2, TriangleTopology> triangle_topology; |
||||
|
|
||||
|
u32 restart_primitive; |
||||
|
|
||||
|
INSERT_PADDING_WORDS(0x20); |
||||
|
}; |
||||
|
|
||||
|
static_assert(sizeof(PipelineRegs) == 0x80 * sizeof(u32), "PipelineRegs struct has incorrect size"); |
||||
|
|
||||
|
} // namespace Pica |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue