aboutsummaryrefslogtreecommitdiff
path: root/src/video_core/shader/shader.cpp
diff options
context:
space:
mode:
authorwwylele <wwylele@gmail.com>2017-07-25 22:30:29 +0300
committerwwylele <wwylele@gmail.com>2017-08-19 10:13:20 +0300
commit46c6973d2bde25a2a8ae9ac434660798fd1dfaee (patch)
tree3910b3b8b95de67f70a482f08351e807c532b784 /src/video_core/shader/shader.cpp
parentdb309b2423a996cb792273080e73906b07f8b45b (diff)
pica/shader: extend UnitState for GS
Among four shader units in pica, a special unit can be configured to run both VS and GS program. GSUnitState represents this unit, which extends UnitState (which represents the other three normal units) with extra state for primitive emitting. It uses lots of raw pointers to represent internal structure in order to keep it standard layout type for JIT to access. This unit doesn't handle triangle winding (inverting) itself; instead, it calls a WindingSetter handler. This will be explained in the following commits
Diffstat (limited to 'src/video_core/shader/shader.cpp')
-rw-r--r--src/video_core/shader/shader.cpp38
1 files changed, 38 insertions, 0 deletions
diff --git a/src/video_core/shader/shader.cpp b/src/video_core/shader/shader.cpp
index 67ed19ba8d..b12468d3a5 100644
--- a/src/video_core/shader/shader.cpp
+++ b/src/video_core/shader/shader.cpp
@@ -82,6 +82,44 @@ void UnitState::WriteOutput(const ShaderRegs& config, AttributeBuffer& output) {
}
}
+UnitState::UnitState(GSEmitter* emitter) : emitter_ptr(emitter) {}
+
+GSEmitter::GSEmitter() {
+ handlers = new Handlers;
+}
+
+GSEmitter::~GSEmitter() {
+ delete handlers;
+}
+
+void GSEmitter::Emit(Math::Vec4<float24> (&vertex)[16]) {
+ ASSERT(vertex_id < 3);
+ std::copy(std::begin(vertex), std::end(vertex), buffer[vertex_id].begin());
+ if (prim_emit) {
+ if (winding)
+ handlers->winding_setter();
+ for (size_t i = 0; i < buffer.size(); ++i) {
+ AttributeBuffer output;
+ unsigned int output_i = 0;
+ for (unsigned int reg : Common::BitSet<u32>(output_mask)) {
+ output.attr[output_i++] = buffer[i][reg];
+ }
+ handlers->vertex_handler(output);
+ }
+ }
+}
+
+GSUnitState::GSUnitState() : UnitState(&emitter) {}
+
+void GSUnitState::SetVertexHandler(VertexHandler vertex_handler, WindingSetter winding_setter) {
+ emitter.handlers->vertex_handler = std::move(vertex_handler);
+ emitter.handlers->winding_setter = std::move(winding_setter);
+}
+
+void GSUnitState::ConfigOutput(const ShaderRegs& config) {
+ emitter.output_mask = config.output_mask;
+}
+
MICROPROFILE_DEFINE(GPU_Shader, "GPU", "Shader", MP_RGB(50, 50, 240));
#ifdef ARCHITECTURE_x86_64