Matrix and GLSL extensions support on gfx::hir

This commit is contained in:
Alexandro Sánchez Bach 2016-05-12 14:27:31 +02:00
parent 0e0a7f6f0f
commit 8e7c2d98a8
13 changed files with 105 additions and 25 deletions

View file

@ -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) {

View file

@ -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);
}

View file

@ -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));
}

View file

@ -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);

View file

@ -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

View file

@ -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) {

View file

@ -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) {

View file

@ -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);

View file

@ -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 {

View file

@ -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 {

View file

@ -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;
}

View file

@ -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

View file

@ -7,6 +7,8 @@
#include "nucleus/common.h"
#include "externals/spirv/GLSL.std.450.h"
namespace gfx {
namespace hir {