mirror of
https://github.com/AlexAltea/nucleus.git
synced 2024-05-31 18:38:01 -04:00
Matrix and GLSL extensions support on gfx::hir
This commit is contained in:
parent
0e0a7f6f0f
commit
8e7c2d98a8
|
@ -1255,7 +1255,7 @@ struct STORE_I16 : Sequence<STORE_I16, I<OPCODE_STORE, VoidOp, PtrOp, I16Op>> {
|
|||
} else {
|
||||
e.mov(e.eax, i.src2);
|
||||
e.xchg(e.ah, e.al);
|
||||
e.mov(e.word[addr], e.eax);
|
||||
e.mov(e.word[addr], e.ax);
|
||||
}
|
||||
} else {
|
||||
if (i.src2.isConstant) {
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
template <typename... Args>
|
||||
std::string format(const char* pattern, Args... args)
|
||||
{
|
||||
char buffer[4096];
|
||||
char buffer[64_KB];
|
||||
snprintf(buffer, sizeof(buffer), pattern, std::forward<Args>(args)...);
|
||||
return std::string(buffer);
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ PGRAPH::PGRAPH(std::shared_ptr<gfx::IBackend> backend, RSX* rsx, mem::Memory* me
|
|||
// Heaps
|
||||
gfx::HeapDesc heapResourcesDesc = {};
|
||||
heapResourcesDesc.type = gfx::HEAP_TYPE_RESOURCE;
|
||||
heapResourcesDesc.size = RSX_MAX_TEXTURES + 1;
|
||||
heapResourcesDesc.size = RSX_MAX_TEXTURES + 2;
|
||||
heapResources = graphics->createHeap(heapResourcesDesc);
|
||||
gfx::HeapDesc heapSamplersDesc = {};
|
||||
heapSamplersDesc.type = gfx::HEAP_TYPE_RESOURCE;
|
||||
|
@ -231,8 +231,6 @@ void PGRAPH::Begin(Primitive primitive) {
|
|||
setSurface();
|
||||
|
||||
// Set viewport
|
||||
viewport.width = 1280; // TODO: Why is this failing?
|
||||
scissor.width = 1280; // TODO: Why is this failing?
|
||||
gfx::Viewport viewportRect = { viewport.x, viewport.y, viewport.width, viewport.height, 0.0f, 1.0f };
|
||||
gfx::Rectangle scissorRect = { scissor.x, scissor.y, scissor.width, scissor.height };
|
||||
cmdBuffer->cmdSetViewports(1, &viewportRect);
|
||||
|
@ -261,7 +259,7 @@ void PGRAPH::Begin(Primitive primitive) {
|
|||
}
|
||||
gfx::PipelineDesc pipelineDesc = {};
|
||||
pipelineDesc.formatDSV = convertFormat(surface.depthFormat);
|
||||
pipelineDesc.numCBVs = 1;
|
||||
pipelineDesc.numCBVs = 2;
|
||||
pipelineDesc.numSRVs = RSX_MAX_TEXTURES;
|
||||
pipelineDesc.vs = cacheVP[vpHash]->shader;
|
||||
pipelineDesc.ps = cacheFP[fpHash]->shader;
|
||||
|
@ -325,12 +323,13 @@ void PGRAPH::Begin(Primitive primitive) {
|
|||
}
|
||||
|
||||
heapResources->reset();
|
||||
heapResources->pushVertexBuffer(vpeConstantMemory);
|
||||
heapResources->pushVertexBuffer(vtxTransform);
|
||||
|
||||
// Upload VPE constants if necessary
|
||||
void* constantsPtr = vpeConstantMemory->map();
|
||||
memcpy(constantsPtr, &vpe.constant, sizeof(vpe.constant));
|
||||
vpeConstantMemory->unmap();
|
||||
heapResources->pushVertexBuffer(vpeConstantMemory);
|
||||
|
||||
// Upload vertex transform matrix if necessary
|
||||
if (vertex_transform_dirty) {
|
||||
|
@ -400,7 +399,7 @@ void PGRAPH::Begin(Primitive primitive) {
|
|||
cmdBuffer->cmdBindPipeline(cachePipeline[pipelineHash].get());
|
||||
cmdBuffer->cmdSetHeaps({ heapResources });
|
||||
cmdBuffer->cmdSetDescriptor(0, heapResources, 0);
|
||||
cmdBuffer->cmdSetDescriptor(1, heapResources, 1);
|
||||
cmdBuffer->cmdSetDescriptor(1, heapResources, 2);
|
||||
cmdBuffer->cmdSetPrimitiveTopology(convertPrimitiveTopology(primitive));
|
||||
}
|
||||
|
||||
|
|
|
@ -164,7 +164,9 @@ void RSXVertexProgram::decompile(const rsx_vp_instruction_t* buffer) {
|
|||
// Basic types
|
||||
Literal floatType = builder.opTypeFloat(32);
|
||||
vecTypeId = builder.opTypeVector(floatType, 4);
|
||||
matTypeId = builder.opTypeMatrix(vecTypeId, 4);
|
||||
constMemoryId = builder.opVariable(STORAGE_CLASS_UNIFORM_CONSTANT, builder.opTypeArray(vecTypeId, 468));
|
||||
transformsId = builder.opVariable(STORAGE_CLASS_UNIFORM_CONSTANT, matTypeId);
|
||||
|
||||
Function* function = new Function(*module.get(), builder.opTypeFunction(builder.opTypeVoid()));
|
||||
Block* block = new Block(*function);
|
||||
|
@ -215,12 +217,12 @@ void RSXVertexProgram::decompile(const rsx_vp_instruction_t* buffer) {
|
|||
setDestVector(builder.opFAdd(builder.opFMul(src0, src1), src2));
|
||||
break;
|
||||
case RSX_VP_OPCODE_VEC_FRC:
|
||||
assert_always("Unimplemented");
|
||||
//source += format("%s = fract(%s)%s;", DST(), SRC(0), get_vp_mask(instr.masc_vec));
|
||||
src0 = getSourceVector(0);
|
||||
setDestVector(builder.opExtFract(src0));
|
||||
break;
|
||||
case RSX_VP_OPCODE_VEC_FLR:
|
||||
assert_always("Unimplemented");
|
||||
//source += format("%s = floor(%s)%s;", DST(), SRC(0), get_vp_mask(instr.masc_vec));
|
||||
src0 = getSourceVector(0);
|
||||
setDestVector(builder.opExtFloor(src0));
|
||||
break;
|
||||
case RSX_VP_OPCODE_VEC_DP4:
|
||||
src0 = getSourceVector(0);
|
||||
|
@ -233,6 +235,13 @@ void RSXVertexProgram::decompile(const rsx_vp_instruction_t* buffer) {
|
|||
}
|
||||
} while (!(buffer++)->end);
|
||||
|
||||
// Transform vertex output
|
||||
Literal position = getOutputReg(0);
|
||||
builder.opStore(position, builder.opMatrixTimesVector(
|
||||
builder.opLoad(transformsId),
|
||||
builder.opLoad(position))
|
||||
);
|
||||
|
||||
// Header
|
||||
builder.addCapability(CAPABILITY_SHADER);
|
||||
builder.addEntryPoint(EXECUTION_MODEL_VERTEX, function, "main", entryPointInterface);
|
||||
|
|
|
@ -141,7 +141,9 @@ private:
|
|||
std::unique_ptr<Module> module;
|
||||
Builder builder;
|
||||
Literal vecTypeId;
|
||||
Literal matTypeId;
|
||||
Literal constMemoryId;
|
||||
Literal transformsId;
|
||||
std::vector<Literal> entryPointInterface;
|
||||
|
||||
// Registers
|
||||
|
|
|
@ -94,9 +94,6 @@ void Direct3D12CommandBuffer::cmdSetHeaps(const std::vector<Heap*>& heaps) {
|
|||
}
|
||||
|
||||
list->SetDescriptorHeaps(d3dHeaps.size(), d3dHeaps.data());
|
||||
for (Size i = 0; i < size; i++) {
|
||||
list->SetGraphicsRootDescriptorTable(i, d3dHeaps[i]->GetGPUDescriptorHandleForHeapStart());
|
||||
}
|
||||
}
|
||||
|
||||
void Direct3D12CommandBuffer::cmdSetDescriptor(Size index, Heap* heap, Size offset) {
|
||||
|
|
|
@ -69,7 +69,7 @@ void Direct3D12Shader::appendUniform(Literal typeId, Literal resultId) {
|
|||
}
|
||||
else {
|
||||
std::string type = getType(underlyingType->resultId);
|
||||
sourceUniforms += format("%s v%d : register(b%d);\n", type.c_str(), resultId, countArbitraryCBV++);
|
||||
sourceUniforms += format("cbuffer C%d : register(b%d) { %s v%d; };\n", resultId, countArbitraryCBV++, type.c_str(), resultId);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -157,6 +157,12 @@ void Direct3D12Shader::appendOutput(Literal typeId, Literal resultId) {
|
|||
}
|
||||
}
|
||||
|
||||
void Direct3D12Shader::appendStatic(hir::Literal typeId, hir::Literal resultId) {
|
||||
// TODO: Value initialization is hardcoded for float4
|
||||
std::string type = getType(typeId);
|
||||
sourceStatics += format("static %s v%d = %s(0.0, 0.0, 0.0, 0.0);\n", type.c_str(), resultId, type.c_str());
|
||||
}
|
||||
|
||||
// Conversion
|
||||
std::string Direct3D12Shader::getType(Literal instrId) {
|
||||
if (!idCache[instrId].empty()) {
|
||||
|
@ -203,6 +209,15 @@ std::string Direct3D12Shader::getType(Literal instrId) {
|
|||
typeName = format("%s%d", componentTypeName.c_str(), componentCount);
|
||||
}
|
||||
|
||||
// Matrices
|
||||
else if (instr->opcode == OP_TYPE_MATRIX) {
|
||||
Literal columnType = instr->operands[0];
|
||||
Literal columnCount = instr->operands[1];
|
||||
assert_true(1 <= columnType && columnType <= 4, "HLSL 5.0 only supports between 1 and 4 matrix columns");
|
||||
std::string componentTypeName = getType(columnType);
|
||||
typeName = format("%sx%d", componentTypeName.c_str(), columnCount);
|
||||
}
|
||||
|
||||
// Arrays
|
||||
else if (instr->opcode == OP_TYPE_ARRAY) {
|
||||
typeName = format("t%d", instr->resultId);
|
||||
|
@ -439,9 +454,34 @@ std::string Direct3D12Shader::emitOpVectorShuffle(hir::Instruction* i) {
|
|||
return format(PADDING "%s v%d = %s(%s);\n", type.c_str(), result, type.c_str(), components.c_str());
|
||||
}
|
||||
|
||||
std::string Direct3D12Shader::emitUnaryOp(hir::Instruction* i, Literal valueId, const char* function) {
|
||||
Literal result = i->resultId;
|
||||
std::string typeStr = getType(i->typeId);
|
||||
return format(PADDING "%s v%d = %s(v%d);\n", typeStr.c_str(), result, function, valueId);
|
||||
}
|
||||
|
||||
std::string Direct3D12Shader::emitOpExtInst(Instruction* i) {
|
||||
std::string source;
|
||||
// TODO: Assuming GLSL extensions
|
||||
Literal instruction = i->operands[1];
|
||||
switch (instruction) {
|
||||
case GLSLstd450FAbs:
|
||||
return emitUnaryOp(i, i->operands[2], "abs");
|
||||
case GLSLstd450Floor:
|
||||
return emitUnaryOp(i, i->operands[2], "floor");
|
||||
case GLSLstd450Fract:
|
||||
return emitUnaryOp(i, i->operands[2], "frac");
|
||||
default:
|
||||
assert_always("Unimplemented");
|
||||
return source;
|
||||
}
|
||||
}
|
||||
|
||||
std::string Direct3D12Shader::compile(Instruction* i) {
|
||||
std::string source;
|
||||
switch (i->opcode) {
|
||||
case OP_FNEGATE:
|
||||
return emitUnaryOp(i, i->operands[0], "-");
|
||||
case OP_FADD:
|
||||
return emitBinaryOp(i, OP_TYPE_FLOAT, '+');
|
||||
case OP_FSUB:
|
||||
|
@ -472,6 +512,8 @@ std::string Direct3D12Shader::compile(Instruction* i) {
|
|||
return emitBinaryOp(i, OP_TYPE_INT, '%'); // TODO: Is this correct?
|
||||
case OP_DOT:
|
||||
return emitBinaryFunctionOp(i, OP_TYPE_FLOAT, "dot");
|
||||
case OP_MATRIX_TIMES_VECTOR:
|
||||
return emitBinaryFunctionOp(i, OP_TYPE_FLOAT, "mul");
|
||||
case OP_VECTOR_SHUFFLE:
|
||||
return emitOpVectorShuffle(i);
|
||||
case OP_COMPOSITE_EXTRACT:
|
||||
|
@ -486,6 +528,8 @@ std::string Direct3D12Shader::compile(Instruction* i) {
|
|||
return emitOpLoad(i);
|
||||
case OP_STORE:
|
||||
return emitOpStore(i);
|
||||
case OP_EXT_INST:
|
||||
return emitOpExtInst(i);
|
||||
}
|
||||
return source;
|
||||
}
|
||||
|
@ -509,7 +553,7 @@ std::string Direct3D12Shader::compile(Function* function) {
|
|||
|
||||
source += idCache[funcId] + " {\n";
|
||||
if (idEntryPoint == funcId) {
|
||||
source += PADDING "TOutput output;\n";
|
||||
source += PADDING "TOutput output = (TOutput)(0);\n";
|
||||
}
|
||||
for (auto* var : function->blocks[0]->variables) {
|
||||
source += emitOpVariable(var);
|
||||
|
@ -587,6 +631,9 @@ std::string Direct3D12Shader::compile(Module* module) {
|
|||
case STORAGE_CLASS_OUTPUT:
|
||||
appendOutput(i->typeId, i->resultId);
|
||||
break;
|
||||
case STORAGE_CLASS_PRIVATE:
|
||||
appendStatic(i->typeId, i->resultId);
|
||||
break;
|
||||
default:
|
||||
assert_always("Unimplemented");
|
||||
}
|
||||
|
@ -600,8 +647,9 @@ std::string Direct3D12Shader::compile(Module* module) {
|
|||
for (const auto& var : userOutputs) {
|
||||
sourceOutput += var;
|
||||
}
|
||||
source = format("%s\nstruct TInput {\n%s};\nstruct TOutput {\n%s};\n%s\n%s\n",
|
||||
sourceTypes.c_str(), sourceInput.c_str(), sourceOutput.c_str(), sourceUniforms.c_str(), sourceConstants.c_str());
|
||||
source = format("%s\nstruct TInput {\n%s};\nstruct TOutput {\n%s};\n%s\n%s\n%s\n",
|
||||
sourceTypes.c_str(), sourceInput.c_str(), sourceOutput.c_str(),
|
||||
sourceUniforms.c_str(), sourceConstants.c_str(), sourceStatics.c_str());
|
||||
|
||||
// Compile functions
|
||||
for (auto* function : module->functions) {
|
||||
|
|
|
@ -49,10 +49,12 @@ class Direct3D12Shader : public Shader {
|
|||
std::string sourceOutput;
|
||||
std::string sourceConstants;
|
||||
std::string sourceUniforms;
|
||||
std::string sourceStatics;
|
||||
|
||||
void appendUniform(hir::Literal typeId, hir::Literal resultId);
|
||||
void appendInput(hir::Literal typeId, hir::Literal resultId);
|
||||
void appendOutput(hir::Literal typeId, hir::Literal resultId);
|
||||
void appendStatic(hir::Literal typeId, hir::Literal resultId);
|
||||
|
||||
// Conversion
|
||||
std::string getType(hir::Literal typeId);
|
||||
|
@ -60,6 +62,7 @@ class Direct3D12Shader : public Shader {
|
|||
std::string getPointer(hir::Literal pointerId);
|
||||
|
||||
// Emitters
|
||||
std::string emitUnaryOp(hir::Instruction* i, hir::Literal value, const char* function);
|
||||
std::string emitBinaryOp(hir::Instruction* i, hir::Opcode type, char symbol);
|
||||
std::string emitBinaryFunctionOp(hir::Instruction* i, hir::Opcode type, const char* function);
|
||||
std::string emitOpCompositeConstruct(hir::Instruction* i);
|
||||
|
@ -69,6 +72,7 @@ class Direct3D12Shader : public Shader {
|
|||
std::string emitOpStore(hir::Instruction* i);
|
||||
std::string emitOpVariable(hir::Instruction* i);
|
||||
std::string emitOpVectorShuffle(hir::Instruction* i);
|
||||
std::string emitOpExtInst(hir::Instruction* i);
|
||||
|
||||
// Compile HIR components into HLSL
|
||||
std::string compile(hir::Instruction* i);
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include "externals/vulkan/vk_platform.h"
|
||||
|
||||
// SPIR-V
|
||||
#include "externals/spirv/GLSL450Lib.h"
|
||||
#include "externals/spirv/GLSL.std.450.h"
|
||||
#include "externals/spirv/spirv.hpp"
|
||||
|
||||
namespace gfx {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
#include "nucleus/common.h"
|
||||
|
||||
#include "externals/spirv/GLSL450Lib.h"
|
||||
#include "externals/spirv/GLSL.std.450.h"
|
||||
#include "externals/spirv/spirv.hpp"
|
||||
|
||||
namespace gfx {
|
||||
|
|
|
@ -390,6 +390,16 @@ Literal Builder::opDot(Literal lhs, Literal rhs) {
|
|||
Literal Builder::opFNegate(Literal value) {
|
||||
Instruction* i = createInstr(OP_FNEGATE, true);
|
||||
i->typeId = getType(value);
|
||||
i->addOperandLiteral(value);
|
||||
curBlock->instructions.push_back(i);
|
||||
return i->resultId;
|
||||
}
|
||||
|
||||
Literal Builder::opMatrixTimesVector(Literal matrix, Literal vector) {
|
||||
Instruction* i = createInstr(OP_MATRIX_TIMES_VECTOR, true);
|
||||
i->typeId = getContainedType(getType(matrix));
|
||||
i->addOperandLiteral(matrix);
|
||||
i->addOperandLiteral(vector);
|
||||
curBlock->instructions.push_back(i);
|
||||
return i->resultId;
|
||||
}
|
||||
|
@ -467,9 +477,13 @@ Literal Builder::opVectorShuffle(Literal resType, Literal vec1, Literal vec2, co
|
|||
}
|
||||
|
||||
// GLSL extensions
|
||||
Literal Builder::opExtFAbs(Literal value) {
|
||||
assert_always("Unimplemented");
|
||||
Instruction* i = createInstr(OP_NOP, true);
|
||||
Literal Builder::emitGlslUnaryOp(Literal instruction, Literal value) {
|
||||
Instruction* i = createInstr(OP_EXT_INST, true);
|
||||
i->typeId = getType(value);
|
||||
i->addOperandLiteral(0); // TODO: Use GLSL's OpExtInstImport result ID
|
||||
i->addOperandLiteral(instruction);
|
||||
i->addOperandLiteral(value);
|
||||
curBlock->instructions.push_back(i);
|
||||
return i->resultId;
|
||||
}
|
||||
|
||||
|
|
|
@ -133,6 +133,7 @@ public:
|
|||
Literal opFDiv(Literal lhs, Literal rhs) { return emitBinaryOp(OP_FDIV, lhs, rhs); }
|
||||
Literal opDot(Literal lhs, Literal rhs);
|
||||
Literal opFNegate(Literal value);
|
||||
Literal opMatrixTimesVector(Literal matrix, Literal vector);
|
||||
|
||||
// TODO: Auto-deduce typeId from image type
|
||||
Literal opImageSampleImplicitLod(Literal typeId, Literal image, Literal coordinate);
|
||||
|
@ -144,7 +145,11 @@ public:
|
|||
Literal opVectorShuffle(Literal resType, Literal vec1, Literal vec2, const std::vector<Literal>& components);
|
||||
|
||||
// GLSL extensions
|
||||
Literal opExtFAbs(Literal value);
|
||||
Literal emitGlslUnaryOp(Literal instruction, Literal value);
|
||||
Literal emitGlslBinaryOp(Literal instruction, Literal value);
|
||||
Literal opExtFAbs(Literal value) { return emitGlslUnaryOp(GLSLstd450FAbs, value); }
|
||||
Literal opExtFloor(Literal value) { return emitGlslUnaryOp(GLSLstd450Floor, value); }
|
||||
Literal opExtFract(Literal value) { return emitGlslUnaryOp(GLSLstd450Fract, value); }
|
||||
};
|
||||
|
||||
} // namespace hir
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
#include "nucleus/common.h"
|
||||
|
||||
#include "externals/spirv/GLSL.std.450.h"
|
||||
|
||||
namespace gfx {
|
||||
namespace hir {
|
||||
|
||||
|
|
Loading…
Reference in a new issue