Skip to content

Commit 3fececc

Browse files
committed
support line strip as vertex output with geometry shaders
1 parent 1fb9cfd commit 3fececc

File tree

4 files changed

+48
-41
lines changed

4 files changed

+48
-41
lines changed

src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitMSL.cpp

+5-1
Original file line numberDiff line numberDiff line change
@@ -4140,7 +4140,11 @@ void LatteDecompiler_emitMSLShader(LatteDecompilerShaderContext* shaderContext,
41404140
if (usesGeometryShader)
41414141
{
41424142
// Calculate the imaginary vertex id
4143-
src->add("uint vid = tig * VERTICES_PER_VERTEX_PRIMITIVE + tid;" _CRLF);
4143+
LattePrimitiveMode vsOutPrimType = shaderContext->contextRegistersNew->VGT_PRIMITIVE_TYPE.get_PRIMITIVE_MODE();
4144+
if (PrimitiveRequiresConnection(vsOutPrimType))
4145+
src->add("uint vid = tig + tid;" _CRLF);
4146+
else
4147+
src->add("uint vid = tig * VERTICES_PER_VERTEX_PRIMITIVE + tid;" _CRLF);
41444148
src->add("uint iid = vid / supportBuffer.verticesPerInstance;" _CRLF);
41454149
src->add("vid %= supportBuffer.verticesPerInstance;" _CRLF);
41464150

src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitMSLHeader.hpp

+4-21
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
#include "Common/precompiled.h"
44
#include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h"
5-
#include "HW/Latte/Core/LatteShader.h"
5+
#include "Cafe/HW/Latte/Core/LatteShader.h"
66

77
namespace LatteDecompiler
88
{
@@ -363,27 +363,10 @@ namespace LatteDecompiler
363363

364364
if ((decompilerContext->options->usesGeometryShader || isRectVertexShader) && (decompilerContext->shaderType == LatteConst::ShaderType::Vertex || decompilerContext->shaderType == LatteConst::ShaderType::Geometry))
365365
{
366-
LattePrimitiveMode vsOutPrimType = static_cast<LattePrimitiveMode>(decompilerContext->contextRegisters[mmVGT_PRIMITIVE_TYPE]);
367-
uint32 gsOutPrimType = decompilerContext->contextRegisters[mmVGT_GS_OUT_PRIM_TYPE];
366+
LattePrimitiveMode vsOutPrimType = decompilerContext->contextRegistersNew->VGT_PRIMITIVE_TYPE.get_PRIMITIVE_MODE();
367+
src->addFmt("#define VERTICES_PER_VERTEX_PRIMITIVE {}" _CRLF, GetVerticesPerPrimitive(vsOutPrimType));
368368

369-
switch (vsOutPrimType)
370-
{
371-
case LattePrimitiveMode::POINTS:
372-
src->add("#define VERTICES_PER_VERTEX_PRIMITIVE 1" _CRLF);
373-
break;
374-
case LattePrimitiveMode::LINES:
375-
src->add("#define VERTICES_PER_VERTEX_PRIMITIVE 2" _CRLF);
376-
break;
377-
case LattePrimitiveMode::TRIANGLES:
378-
src->add("#define VERTICES_PER_VERTEX_PRIMITIVE 3" _CRLF);
379-
break;
380-
case LattePrimitiveMode::RECTS:
381-
src->add("#define VERTICES_PER_VERTEX_PRIMITIVE 3" _CRLF);
382-
break;
383-
default:
384-
cemuLog_log(LogType::Force, "Unknown vertex out primitive type {}", vsOutPrimType);
385-
break;
386-
}
369+
uint32 gsOutPrimType = decompilerContext->contextRegisters[mmVGT_GS_OUT_PRIM_TYPE];
387370
if (decompilerContext->shaderType == LatteConst::ShaderType::Geometry)
388371
{
389372
switch (gsOutPrimType)

src/Cafe/HW/Latte/Renderer/Metal/MetalCommon.h

+31
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ inline bool executeCommand(fmt::format_string<T...> fmt, T&&... args) {
117117
return true;
118118
}
119119

120+
/*
120121
class MemoryMappedFile
121122
{
122123
public:
@@ -179,3 +180,33 @@ class MemoryMappedFile
179180
void* m_data = nullptr;
180181
size_t m_fileSize = 0;
181182
};
183+
*/
184+
185+
inline uint32 GetVerticesPerPrimitive(LattePrimitiveMode primitiveMode)
186+
{
187+
switch (primitiveMode)
188+
{
189+
case LattePrimitiveMode::POINTS:
190+
return 1;
191+
case LattePrimitiveMode::LINES:
192+
return 2;
193+
case LattePrimitiveMode::LINE_STRIP:
194+
// Same as line, but requires connection
195+
return 2;
196+
case LattePrimitiveMode::TRIANGLES:
197+
return 3;
198+
case LattePrimitiveMode::RECTS:
199+
return 3;
200+
default:
201+
cemuLog_log(LogType::Force, "Unimplemented primitive type {}", primitiveMode);
202+
return 0;
203+
}
204+
}
205+
206+
inline bool PrimitiveRequiresConnection(LattePrimitiveMode primitiveMode)
207+
{
208+
if (primitiveMode == LattePrimitiveMode::LINE_STRIP)
209+
return true;
210+
else
211+
return false;
212+
}

src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp

+8-19
Original file line numberDiff line numberDiff line change
@@ -1132,7 +1132,7 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32
11321132
*/
11331133

11341134
// Primitive type
1135-
const LattePrimitiveMode primitiveMode = static_cast<LattePrimitiveMode>(LatteGPUState.contextRegister[mmVGT_PRIMITIVE_TYPE]);
1135+
const LattePrimitiveMode primitiveMode = LatteGPUState.contextNew.VGT_PRIMITIVE_TYPE.get_PRIMITIVE_MODE();
11361136
auto mtlPrimitiveType = GetMtlPrimitiveType(primitiveMode);
11371137
bool isPrimitiveRect = (primitiveMode == Latte::LATTE_VGT_PRIMITIVE_TYPE::E_PRIMITIVE_TYPE::RECTS);
11381138

@@ -1394,25 +1394,14 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32
13941394
renderCommandEncoder->setObjectBytes(&hostIndexTypeU8, sizeof(hostIndexTypeU8), vertexShader->resourceMapping.indexTypeBinding);
13951395
encoderState.m_buffers[METAL_SHADER_TYPE_OBJECT][vertexShader->resourceMapping.indexTypeBinding] = {nullptr};
13961396

1397-
uint32 verticesPerPrimitive = 0;
1398-
switch (primitiveMode)
1399-
{
1400-
case LattePrimitiveMode::POINTS:
1401-
verticesPerPrimitive = 1;
1402-
break;
1403-
case LattePrimitiveMode::LINES:
1404-
verticesPerPrimitive = 2;
1405-
break;
1406-
case LattePrimitiveMode::TRIANGLES:
1407-
case LattePrimitiveMode::RECTS:
1408-
verticesPerPrimitive = 3;
1409-
break;
1410-
default:
1411-
cemuLog_log(LogType::Force, "unimplemented geometry shader primitive mode {}", (uint32)primitiveMode);
1412-
break;
1413-
}
1397+
uint32 verticesPerPrimitive = GetVerticesPerPrimitive(primitiveMode);
1398+
uint32 threadgroupCount = count * instanceCount;
1399+
if (PrimitiveRequiresConnection(primitiveMode))
1400+
threadgroupCount -= verticesPerPrimitive - 1;
1401+
else
1402+
threadgroupCount /= verticesPerPrimitive;
14141403

1415-
renderCommandEncoder->drawMeshThreadgroups(MTL::Size(count * instanceCount / verticesPerPrimitive, 1, 1), MTL::Size(verticesPerPrimitive, 1, 1), MTL::Size(1, 1, 1));
1404+
renderCommandEncoder->drawMeshThreadgroups(MTL::Size(threadgroupCount, 1, 1), MTL::Size(verticesPerPrimitive, 1, 1), MTL::Size(1, 1, 1));
14161405
}
14171406
else
14181407
{

0 commit comments

Comments
 (0)