mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-07-06 06:51:18 +12:00
support line strip as vertex output with geometry shaders
This commit is contained in:
parent
1fb9cfd783
commit
3fececc3ba
4 changed files with 48 additions and 41 deletions
|
@ -4140,7 +4140,11 @@ void LatteDecompiler_emitMSLShader(LatteDecompilerShaderContext* shaderContext,
|
||||||
if (usesGeometryShader)
|
if (usesGeometryShader)
|
||||||
{
|
{
|
||||||
// Calculate the imaginary vertex id
|
// Calculate the imaginary vertex id
|
||||||
src->add("uint vid = tig * VERTICES_PER_VERTEX_PRIMITIVE + tid;" _CRLF);
|
LattePrimitiveMode vsOutPrimType = shaderContext->contextRegistersNew->VGT_PRIMITIVE_TYPE.get_PRIMITIVE_MODE();
|
||||||
|
if (PrimitiveRequiresConnection(vsOutPrimType))
|
||||||
|
src->add("uint vid = tig + tid;" _CRLF);
|
||||||
|
else
|
||||||
|
src->add("uint vid = tig * VERTICES_PER_VERTEX_PRIMITIVE + tid;" _CRLF);
|
||||||
src->add("uint iid = vid / supportBuffer.verticesPerInstance;" _CRLF);
|
src->add("uint iid = vid / supportBuffer.verticesPerInstance;" _CRLF);
|
||||||
src->add("vid %= supportBuffer.verticesPerInstance;" _CRLF);
|
src->add("vid %= supportBuffer.verticesPerInstance;" _CRLF);
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include "Common/precompiled.h"
|
#include "Common/precompiled.h"
|
||||||
#include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h"
|
#include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h"
|
||||||
#include "HW/Latte/Core/LatteShader.h"
|
#include "Cafe/HW/Latte/Core/LatteShader.h"
|
||||||
|
|
||||||
namespace LatteDecompiler
|
namespace LatteDecompiler
|
||||||
{
|
{
|
||||||
|
@ -363,27 +363,10 @@ namespace LatteDecompiler
|
||||||
|
|
||||||
if ((decompilerContext->options->usesGeometryShader || isRectVertexShader) && (decompilerContext->shaderType == LatteConst::ShaderType::Vertex || decompilerContext->shaderType == LatteConst::ShaderType::Geometry))
|
if ((decompilerContext->options->usesGeometryShader || isRectVertexShader) && (decompilerContext->shaderType == LatteConst::ShaderType::Vertex || decompilerContext->shaderType == LatteConst::ShaderType::Geometry))
|
||||||
{
|
{
|
||||||
LattePrimitiveMode vsOutPrimType = static_cast<LattePrimitiveMode>(decompilerContext->contextRegisters[mmVGT_PRIMITIVE_TYPE]);
|
LattePrimitiveMode vsOutPrimType = decompilerContext->contextRegistersNew->VGT_PRIMITIVE_TYPE.get_PRIMITIVE_MODE();
|
||||||
uint32 gsOutPrimType = decompilerContext->contextRegisters[mmVGT_GS_OUT_PRIM_TYPE];
|
src->addFmt("#define VERTICES_PER_VERTEX_PRIMITIVE {}" _CRLF, GetVerticesPerPrimitive(vsOutPrimType));
|
||||||
|
|
||||||
switch (vsOutPrimType)
|
uint32 gsOutPrimType = decompilerContext->contextRegisters[mmVGT_GS_OUT_PRIM_TYPE];
|
||||||
{
|
|
||||||
case LattePrimitiveMode::POINTS:
|
|
||||||
src->add("#define VERTICES_PER_VERTEX_PRIMITIVE 1" _CRLF);
|
|
||||||
break;
|
|
||||||
case LattePrimitiveMode::LINES:
|
|
||||||
src->add("#define VERTICES_PER_VERTEX_PRIMITIVE 2" _CRLF);
|
|
||||||
break;
|
|
||||||
case LattePrimitiveMode::TRIANGLES:
|
|
||||||
src->add("#define VERTICES_PER_VERTEX_PRIMITIVE 3" _CRLF);
|
|
||||||
break;
|
|
||||||
case LattePrimitiveMode::RECTS:
|
|
||||||
src->add("#define VERTICES_PER_VERTEX_PRIMITIVE 3" _CRLF);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
cemuLog_log(LogType::Force, "Unknown vertex out primitive type {}", vsOutPrimType);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (decompilerContext->shaderType == LatteConst::ShaderType::Geometry)
|
if (decompilerContext->shaderType == LatteConst::ShaderType::Geometry)
|
||||||
{
|
{
|
||||||
switch (gsOutPrimType)
|
switch (gsOutPrimType)
|
||||||
|
|
|
@ -117,6 +117,7 @@ inline bool executeCommand(fmt::format_string<T...> fmt, T&&... args) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
class MemoryMappedFile
|
class MemoryMappedFile
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -179,3 +180,33 @@ private:
|
||||||
void* m_data = nullptr;
|
void* m_data = nullptr;
|
||||||
size_t m_fileSize = 0;
|
size_t m_fileSize = 0;
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
inline uint32 GetVerticesPerPrimitive(LattePrimitiveMode primitiveMode)
|
||||||
|
{
|
||||||
|
switch (primitiveMode)
|
||||||
|
{
|
||||||
|
case LattePrimitiveMode::POINTS:
|
||||||
|
return 1;
|
||||||
|
case LattePrimitiveMode::LINES:
|
||||||
|
return 2;
|
||||||
|
case LattePrimitiveMode::LINE_STRIP:
|
||||||
|
// Same as line, but requires connection
|
||||||
|
return 2;
|
||||||
|
case LattePrimitiveMode::TRIANGLES:
|
||||||
|
return 3;
|
||||||
|
case LattePrimitiveMode::RECTS:
|
||||||
|
return 3;
|
||||||
|
default:
|
||||||
|
cemuLog_log(LogType::Force, "Unimplemented primitive type {}", primitiveMode);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool PrimitiveRequiresConnection(LattePrimitiveMode primitiveMode)
|
||||||
|
{
|
||||||
|
if (primitiveMode == LattePrimitiveMode::LINE_STRIP)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
@ -1132,7 +1132,7 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Primitive type
|
// Primitive type
|
||||||
const LattePrimitiveMode primitiveMode = static_cast<LattePrimitiveMode>(LatteGPUState.contextRegister[mmVGT_PRIMITIVE_TYPE]);
|
const LattePrimitiveMode primitiveMode = LatteGPUState.contextNew.VGT_PRIMITIVE_TYPE.get_PRIMITIVE_MODE();
|
||||||
auto mtlPrimitiveType = GetMtlPrimitiveType(primitiveMode);
|
auto mtlPrimitiveType = GetMtlPrimitiveType(primitiveMode);
|
||||||
bool isPrimitiveRect = (primitiveMode == Latte::LATTE_VGT_PRIMITIVE_TYPE::E_PRIMITIVE_TYPE::RECTS);
|
bool isPrimitiveRect = (primitiveMode == Latte::LATTE_VGT_PRIMITIVE_TYPE::E_PRIMITIVE_TYPE::RECTS);
|
||||||
|
|
||||||
|
@ -1394,25 +1394,14 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32
|
||||||
renderCommandEncoder->setObjectBytes(&hostIndexTypeU8, sizeof(hostIndexTypeU8), vertexShader->resourceMapping.indexTypeBinding);
|
renderCommandEncoder->setObjectBytes(&hostIndexTypeU8, sizeof(hostIndexTypeU8), vertexShader->resourceMapping.indexTypeBinding);
|
||||||
encoderState.m_buffers[METAL_SHADER_TYPE_OBJECT][vertexShader->resourceMapping.indexTypeBinding] = {nullptr};
|
encoderState.m_buffers[METAL_SHADER_TYPE_OBJECT][vertexShader->resourceMapping.indexTypeBinding] = {nullptr};
|
||||||
|
|
||||||
uint32 verticesPerPrimitive = 0;
|
uint32 verticesPerPrimitive = GetVerticesPerPrimitive(primitiveMode);
|
||||||
switch (primitiveMode)
|
uint32 threadgroupCount = count * instanceCount;
|
||||||
{
|
if (PrimitiveRequiresConnection(primitiveMode))
|
||||||
case LattePrimitiveMode::POINTS:
|
threadgroupCount -= verticesPerPrimitive - 1;
|
||||||
verticesPerPrimitive = 1;
|
else
|
||||||
break;
|
threadgroupCount /= verticesPerPrimitive;
|
||||||
case LattePrimitiveMode::LINES:
|
|
||||||
verticesPerPrimitive = 2;
|
|
||||||
break;
|
|
||||||
case LattePrimitiveMode::TRIANGLES:
|
|
||||||
case LattePrimitiveMode::RECTS:
|
|
||||||
verticesPerPrimitive = 3;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
cemuLog_log(LogType::Force, "unimplemented geometry shader primitive mode {}", (uint32)primitiveMode);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
renderCommandEncoder->drawMeshThreadgroups(MTL::Size(count * instanceCount / verticesPerPrimitive, 1, 1), MTL::Size(verticesPerPrimitive, 1, 1), MTL::Size(1, 1, 1));
|
renderCommandEncoder->drawMeshThreadgroups(MTL::Size(threadgroupCount, 1, 1), MTL::Size(verticesPerPrimitive, 1, 1), MTL::Size(1, 1, 1));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue