[D3D12] Shader translator CompleteTranslation

This commit is contained in:
Triang3l 2018-07-23 17:23:35 +03:00
parent 60706077a3
commit f237f7e8eb
2 changed files with 91 additions and 48 deletions

View File

@ -9,6 +9,8 @@
#include "xenia/gpu/hlsl_shader_translator.h" #include "xenia/gpu/hlsl_shader_translator.h"
#include <algorithm>
#include "xenia/base/assert.h" #include "xenia/base/assert.h"
namespace xe { namespace xe {
@ -17,11 +19,10 @@ using namespace ucode;
constexpr uint32_t kMaxInterpolators = 16; constexpr uint32_t kMaxInterpolators = 16;
#define EmitSource(...) source_.AppendFormat(__VA_ARGS__) #define EmitSource(...) source_inner_.AppendFormat(__VA_ARGS__)
#define EmitSourceDepth(...) \ #define EmitSourceDepth(...) \
source_.Append(" "); \ source_inner_.Append(depth_prefix_); \
source_.Append(depth_prefix_); \ source_inner_.AppendFormat(__VA_ARGS__)
source_.AppendFormat(__VA_ARGS__)
HlslShaderTranslator::HlslShaderTranslator() {} HlslShaderTranslator::HlslShaderTranslator() {}
HlslShaderTranslator::~HlslShaderTranslator() = default; HlslShaderTranslator::~HlslShaderTranslator() = default;
@ -29,9 +30,9 @@ HlslShaderTranslator::~HlslShaderTranslator() = default;
void HlslShaderTranslator::Reset() { void HlslShaderTranslator::Reset() {
ShaderTranslator::Reset(); ShaderTranslator::Reset();
source_.Reset(); source_inner_.Reset();
depth_ = 0; depth_ = 0;
depth_prefix[0] = 0; depth_prefix_[0] = 0;
cf_wrote_pc_ = false; cf_wrote_pc_ = false;
cf_exec_pred_ = false; cf_exec_pred_ = false;
@ -69,8 +70,21 @@ void HlslShaderTranslator::Unindent() {
} }
void HlslShaderTranslator::StartTranslation() { void HlslShaderTranslator::StartTranslation() {
// Common things. // Main function level (1).
EmitSource( Indent();
// Do while PC != 0xFFFF level (2).
Indent();
// Switch level (3).
Indent();
EmitSourceDepth("case 0:\n");
}
std::vector<uint8_t> HlslShaderTranslator::CompleteTranslation() {
// Add the declarations, the prologue and the epilogue knowing what is needed.
StringBuffer source;
// Common declarations.
source.Append(
"#define XE_FLT_MAX 3.402823466e+38\n" "#define XE_FLT_MAX 3.402823466e+38\n"
"\n" "\n"
"cbuffer xe_system_constants : register(b0) {\n" "cbuffer xe_system_constants : register(b0) {\n"
@ -98,7 +112,7 @@ void HlslShaderTranslator::StartTranslation() {
// 11 for 16-in-32. This means we can check bits 0 ^ 1 to see if we need to // 11 for 16-in-32. This means we can check bits 0 ^ 1 to see if we need to
// do a 8-in-16 swap, and bit 1 to see if a 16-in-32 swap is needed. // do a 8-in-16 swap, and bit 1 to see if a 16-in-32 swap is needed.
// Vertex element is a temporary integer value for fetches. // Vertex element is a temporary integer value for fetches.
EmitSource( source.AppendFormat(
"cbuffer xe_vertex_fetch_constants : register(b18) {\n" "cbuffer xe_vertex_fetch_constants : register(b18) {\n"
" uint2 xe_vertex_fetch[96];\n" " uint2 xe_vertex_fetch[96];\n"
"}\n" "}\n"
@ -139,7 +153,7 @@ void HlslShaderTranslator::StartTranslation() {
// Pixel shader inputs, outputs and prologue. // Pixel shader inputs, outputs and prologue.
// If the shader writes to depth, it needs to define // If the shader writes to depth, it needs to define
// XE_PIXEL_SHADER_WRITES_DEPTH in the beginning of the final output. // XE_PIXEL_SHADER_WRITES_DEPTH in the beginning of the final output.
EmitSource( source.AppendFormat(
"struct XePixelShaderInput {\n" "struct XePixelShaderInput {\n"
" float4 position : SV_Position;\n" " float4 position : SV_Position;\n"
" float4 interpolators[%u] : TEXCOORD;\n" " float4 interpolators[%u] : TEXCOORD;\n"
@ -147,20 +161,19 @@ void HlslShaderTranslator::StartTranslation() {
"\n" "\n"
"struct XePixelShaderOutput {\n" "struct XePixelShaderOutput {\n"
" float4 colors[4] : SV_Target;\n" " float4 colors[4] : SV_Target;\n"
" #ifdef XE_PIXEL_SHADER_WRITES_DEPTH\n" "%s"
" float depth : SV_Depth;\n"
" #endif\n"
"}\n" "}\n"
"\n" "\n"
"XePixelShaderOutput main(XePixelShaderInput xe_input) {\n" "XePixelShaderOutput main(XePixelShaderInput xe_input) {\n"
" float4 xe_r[%u];\n" " float4 xe_r[%u];\n"
" XePixelShaderOutput xe_output;\n", " XePixelShaderOutput xe_output;\n",
kMaxInterpolators, register_count()); kMaxInterpolators, writes_depth_ ? " float depth : SV_Depth;\n" : "",
// Copy interpolators to the first registers. register_count());
// Copy interpolants to the first registers.
uint32_t interpolator_register_count = uint32_t interpolator_register_count =
std::min(register_count(), kMaxInterpolators); std::min(register_count(), kMaxInterpolators);
for (uint32_t i = 0; i < interpolator_register_count; ++i) { for (uint32_t i = 0; i < interpolator_register_count; ++i) {
EmitSource(" xe_r[%u] = xe_input.interpolators[%u];\n", i, i); source.AppendFormat(" xe_r[%u] = xe_input.interpolators[%u];\n", i, i);
} }
// No need to write zero to every output because in case an output is // No need to write zero to every output because in case an output is
// completely unused, writing to that render target will be disabled in the // completely unused, writing to that render target will be disabled in the
@ -169,7 +182,8 @@ void HlslShaderTranslator::StartTranslation() {
// TODO(Triang3l): ps_param_gen. // TODO(Triang3l): ps_param_gen.
} }
EmitSource( // Common main function variables and prologue.
source.Append(
// Dynamic index for source operands (mainly for float and bool constants // Dynamic index for source operands (mainly for float and bool constants
// since they are indexed in two parts). // since they are indexed in two parts).
" uint xe_src_index;\n" " uint xe_src_index;\n"
@ -191,14 +205,24 @@ void HlslShaderTranslator::StartTranslation() {
// Master loop and switch for flow control. // Master loop and switch for flow control.
" uint xe_pc = 0u;\n" " uint xe_pc = 0u;\n"
"\n" "\n"
" do {\n"; " do {\n"
" switch (xe_pc) {\n" " switch (xe_pc) {\n");
" case 0u:\n");
// Main function level (1). // Translated code.
Indent(); source.Append(source_inner_.GetString());
// Do level (2)
Indent(); // Epilogue.
source.Append(
" default:\n"
" pc = 0xFFFFu;\n"
" }\n"
" } while (xe_pc != 0xFFFFu);\n");
// TODO(Triang3l): Window offset, half pixel offset, alpha test, gamma.
source.Append(
" return xe_output;\n"
"}\n");
return source.ToBytes();
} }
void HlslShaderTranslator::ProcessLabel(uint32_t cf_index) { void HlslShaderTranslator::ProcessLabel(uint32_t cf_index) {
@ -228,7 +252,7 @@ void HlslShaderTranslator::ProcessControlFlowInstructionEnd(uint32_t cf_index) {
void HlslShaderTranslator::ProcessExecInstructionBegin( void HlslShaderTranslator::ProcessExecInstructionBegin(
const ParsedExecInstruction& instr) { const ParsedExecInstruction& instr) {
EmitSourceDepth("// "); EmitSourceDepth("// ");
instr.Disassemble(&source_); instr.Disassemble(&source_inner_);
cf_exec_pred_ = false; cf_exec_pred_ = false;
switch (instr.type) { switch (instr.type) {
@ -264,7 +288,7 @@ void HlslShaderTranslator::ProcessExecInstructionEnd(
void HlslShaderTranslator::ProcessLoopStartInstruction( void HlslShaderTranslator::ProcessLoopStartInstruction(
const ParsedLoopStartInstruction& instr) { const ParsedLoopStartInstruction& instr) {
EmitSourceDepth("// "); EmitSourceDepth("// ");
instr.Disassemble(&source_); instr.Disassemble(&source_inner_);
// Setup counter. // Setup counter.
EmitSourceDepth("xe_loop_count.yzw = xe_loop_count.xyz;\n"); EmitSourceDepth("xe_loop_count.yzw = xe_loop_count.xyz;\n");
@ -292,7 +316,7 @@ void HlslShaderTranslator::ProcessLoopStartInstruction(
void HlslShaderTranslator::ProcessLoopEndInstruction( void HlslShaderTranslator::ProcessLoopEndInstruction(
const ParsedLoopEndInstruction& instr) { const ParsedLoopEndInstruction& instr) {
EmitSourceDepth("// "); EmitSourceDepth("// ");
instr.Disassemble(&source_); instr.Disassemble(&source_inner_);
// Decrement loop counter, and if we are done break out. // Decrement loop counter, and if we are done break out.
EmitSourceDepth("if (--xe_loop_count.x == 0u"); EmitSourceDepth("if (--xe_loop_count.x == 0u");
@ -332,7 +356,7 @@ void HlslShaderTranslator::ProcessLoopEndInstruction(
void HlslShaderTranslator::ProcessCallInstruction( void HlslShaderTranslator::ProcessCallInstruction(
const ParsedCallInstruction& instr) { const ParsedCallInstruction& instr) {
EmitSourceDepth("// "); EmitSourceDepth("// ");
instr.Disassemble(&source_); instr.Disassemble(&source_inner_);
EmitUnimplementedTranslationError(); EmitUnimplementedTranslationError();
} }
@ -340,7 +364,7 @@ void HlslShaderTranslator::ProcessCallInstruction(
void HlslShaderTranslator::ProcessReturnInstruction( void HlslShaderTranslator::ProcessReturnInstruction(
const ParsedReturnInstruction& instr) { const ParsedReturnInstruction& instr) {
EmitSourceDepth("// "); EmitSourceDepth("// ");
instr.Disassemble(&source_); instr.Disassemble(&source_inner_);
EmitUnimplementedTranslationError(); EmitUnimplementedTranslationError();
} }
@ -348,7 +372,7 @@ void HlslShaderTranslator::ProcessReturnInstruction(
void HlslShaderTranslator::ProcessJumpInstruction( void HlslShaderTranslator::ProcessJumpInstruction(
const ParsedJumpInstruction& instr) { const ParsedJumpInstruction& instr) {
EmitSourceDepth("// "); EmitSourceDepth("// ");
instr.Disassemble(&source_); instr.Disassemble(&source_inner_);
bool needs_fallthrough = false; bool needs_fallthrough = false;
switch (instr.type) { switch (instr.type) {
@ -386,14 +410,14 @@ void HlslShaderTranslator::ProcessJumpInstruction(
void HlslShaderTranslator::ProcessAllocInstruction( void HlslShaderTranslator::ProcessAllocInstruction(
const ParsedAllocInstruction& instr) { const ParsedAllocInstruction& instr) {
EmitSourceDepth("// "); EmitSourceDepth("// ");
instr.Disassemble(&source_); instr.Disassemble(&source_inner_);
} }
bool HlslShaderTranslator::BeginPredicatedInstruction( bool HlslShaderTranslator::BeginPredicatedInstruction(
bool is_predicated, bool predicate_condition) { bool is_predicated, bool predicate_condition) {
if (is_predicated && if (is_predicated &&
(!cf_exec_pred_ || cf_exec_pred_cond_ != predicate_condition)) { (!cf_exec_pred_ || cf_exec_pred_cond_ != predicate_condition)) {
EmitSourceDepth("if (%cxe_p0) {\n", instr.predicate_condition ? ' ' : '!'); EmitSourceDepth("if (%cxe_p0) {\n", predicate_condition ? ' ' : '!');
Indent(); Indent();
return true; return true;
} }
@ -407,7 +431,7 @@ void HlslShaderTranslator::EndPredicatedInstruction(bool conditional_emitted) {
} }
} }
void HlslShaderTranslator::EmitLoadOperand(uint32_t src_index, void HlslShaderTranslator::EmitLoadOperand(size_t src_index,
const InstructionOperand& op) { const InstructionOperand& op) {
// If indexing dynamically, emit the index because float and bool constants // If indexing dynamically, emit the index because float and bool constants
// need to be indexed in two parts. // need to be indexed in two parts.
@ -415,14 +439,14 @@ void HlslShaderTranslator::EmitLoadOperand(uint32_t src_index,
uint32_t storage_index_max; uint32_t storage_index_max;
switch (op.storage_source) { switch (op.storage_source) {
case InstructionStorageSource::kRegister: case InstructionStorageSource::kRegister:
index_max = 127; storage_index_max = 127;
break; break;
case InstructionStorageSource::kConstantFloat: case InstructionStorageSource::kConstantFloat:
case InstructionStorageSource::kConstantBool: case InstructionStorageSource::kConstantBool:
index_max = 255; storage_index_max = 255;
break; break;
case InstructionStorageSource::kConstantInt: case InstructionStorageSource::kConstantInt:
index_max = 31; storage_index_max = 31;
break; break;
default: default:
assert_always(); assert_always();
@ -439,7 +463,7 @@ void HlslShaderTranslator::EmitLoadOperand(uint32_t src_index,
} }
// Negation and abs are store modifiers, so they're applied after swizzling. // Negation and abs are store modifiers, so they're applied after swizzling.
EmitSourceDepth("xe_src%u = ", src_index); EmitSourceDepth("xe_src%u = ", uint32_t(src_index));
if (op.is_negated) { if (op.is_negated) {
EmitSource("-"); EmitSource("-");
} }
@ -670,10 +694,10 @@ void HlslShaderTranslator::EmitStoreResult(const InstructionResult& result,
void HlslShaderTranslator::ProcessVertexFetchInstruction( void HlslShaderTranslator::ProcessVertexFetchInstruction(
const ParsedVertexFetchInstruction& instr) { const ParsedVertexFetchInstruction& instr) {
EmitSourceDepth("// "); EmitSourceDepth("// ");
instr.Disassemble(&source_); instr.Disassemble(&source_inner_);
if (instr.operand_count < 2 || if (instr.operand_count < 2 ||
instr.operand[1].storage_source != instr.operands[1].storage_source !=
InstructionStorageSource::kVertexFetchConstant) { InstructionStorageSource::kVertexFetchConstant) {
assert_always(); assert_always();
return; return;
@ -737,7 +761,7 @@ void HlslShaderTranslator::ProcessVertexFetchInstruction(
} }
break; break;
case VertexFormat::k_2_10_10_10: case VertexFormat::k_2_10_10_10:
EmitSourceDepth("xe_vertex_element = (xe_vertex_element.xxxx >>\n" EmitSourceDepth("xe_vertex_element = (xe_vertex_element.xxxx >>\n");
EmitSourceDepth( EmitSourceDepth(
" uint4(0u, 10u, 20u, 30u)) & uint4((1023u).xxx, 3u);\n"); " uint4(0u, 10u, 20u, 30u)) & uint4((1023u).xxx, 3u);\n");
if (instr.attributes.is_signed) { if (instr.attributes.is_signed) {
@ -757,7 +781,7 @@ void HlslShaderTranslator::ProcessVertexFetchInstruction(
} }
break; break;
case VertexFormat::k_10_11_11: case VertexFormat::k_10_11_11:
EmitSourceDepth("xe_vertex_element.xyz = (xe_vertex_element.xxx >>\n" EmitSourceDepth("xe_vertex_element.xyz = (xe_vertex_element.xxx >>\n");
EmitSourceDepth( EmitSourceDepth(
" uint3(0u, 11u, 22u)) & uint3(2047u, 2047u, 1023u);\n"); " uint3(0u, 11u, 22u)) & uint3(2047u, 2047u, 1023u);\n");
if (instr.attributes.is_signed) { if (instr.attributes.is_signed) {
@ -779,7 +803,7 @@ void HlslShaderTranslator::ProcessVertexFetchInstruction(
EmitSourceDepth("xe_pv.w = 1.0;\n"); EmitSourceDepth("xe_pv.w = 1.0;\n");
break; break;
case VertexFormat::k_11_11_10: case VertexFormat::k_11_11_10:
EmitSourceDepth("xe_vertex_element.xyz = (xe_vertex_element.xxx >>\n" EmitSourceDepth("xe_vertex_element.xyz = (xe_vertex_element.xxx >>\n");
EmitSourceDepth( EmitSourceDepth(
" uint3(0u, 10u, 21u)) & uint3(1023u, 2047u, 2047u);\n"); " uint3(0u, 10u, 21u)) & uint3(1023u, 2047u, 2047u);\n");
if (instr.attributes.is_signed) { if (instr.attributes.is_signed) {
@ -930,6 +954,22 @@ uint32_t HlslShaderTranslator::AddSampler(uint32_t fetch_constant) {
return sampler_count_++; return sampler_count_++;
} }
void HlslShaderTranslator::ProcessTextureFetchInstruction(
const ParsedTextureFetchInstruction& instr) {
EmitSourceDepth("// ");
instr.Disassemble(&source_inner_);
bool conditional_emitted = BeginPredicatedInstruction(
instr.is_predicated, instr.predicate_condition);
// TODO(Triang3l): Texture fetch when textures are added.
EmitSourceDepth("xe_pv = (1.0).xxxx;\n");
EmitStoreResult(instr.result, false);
EndPredicatedInstruction(conditional_emitted);
}
void HlslShaderTranslator::ProcessVectorAluInstruction( void HlslShaderTranslator::ProcessVectorAluInstruction(
const ParsedAluInstruction& instr) { const ParsedAluInstruction& instr) {
bool conditional_emitted = BeginPredicatedInstruction( bool conditional_emitted = BeginPredicatedInstruction(
@ -1153,7 +1193,7 @@ void HlslShaderTranslator::ProcessScalarAluInstruction(
EmitSourceDepth("xe_a0 = clamp(int(round(xe_src0.x)), -256, 255);\n"); EmitSourceDepth("xe_a0 = clamp(int(round(xe_src0.x)), -256, 255);\n");
EmitSourceDepth("xe_ps = max(xe_src0.x, xe_src0.y);\n"); EmitSourceDepth("xe_ps = max(xe_src0.x, xe_src0.y);\n");
break; break;
case AluScalarOpcode::kMaxAf: case AluScalarOpcode::kMaxAsf:
EmitSourceDepth("xe_a0 = clamp(int(floor(xe_src0.x)), -256, 255);\n"); EmitSourceDepth("xe_a0 = clamp(int(floor(xe_src0.x)), -256, 255);\n");
EmitSourceDepth("xe_ps = max(xe_src0.x, xe_src0.y);\n"); EmitSourceDepth("xe_ps = max(xe_src0.x, xe_src0.y);\n");
break; break;
@ -1257,7 +1297,7 @@ void HlslShaderTranslator::ProcessScalarAluInstruction(
void HlslShaderTranslator::ProcessAluInstruction( void HlslShaderTranslator::ProcessAluInstruction(
const ParsedAluInstruction& instr) { const ParsedAluInstruction& instr) {
EmitSourceDepth("// "); EmitSourceDepth("// ");
instr.Disassemble(&source_); instr.Disassemble(&source_inner_);
switch (instr.type) { switch (instr.type) {
case ParsedAluInstruction::Type::kNop: case ParsedAluInstruction::Type::kNop:

View File

@ -46,6 +46,9 @@ class HlslShaderTranslator : public ShaderTranslator {
void EmitTranslationError(const char* message) override; void EmitTranslationError(const char* message) override;
void EmitUnimplementedTranslationError() override; void EmitUnimplementedTranslationError() override;
void StartTranslation() override;
std::vector<uint8_t> CompleteTranslation() override;
void ProcessLabel(uint32_t cf_index) override; void ProcessLabel(uint32_t cf_index) override;
void ProcessControlFlowNopInstruction(uint32_t cf_index) override; void ProcessControlFlowNopInstruction(uint32_t cf_index) override;
@ -76,12 +79,12 @@ class HlslShaderTranslator : public ShaderTranslator {
bool BeginPredicatedInstruction(bool is_predicated, bool predicate_condition); bool BeginPredicatedInstruction(bool is_predicated, bool predicate_condition);
void EndPredicatedInstruction(bool conditional_emitted); void EndPredicatedInstruction(bool conditional_emitted);
void EmitLoadOperand(uint32_t src_index, const InstructionOperand& op); void EmitLoadOperand(size_t src_index, const InstructionOperand& op);
void EmitStoreResult(const InstructionResult& result, bool source_is_scalar); void EmitStoreResult(const InstructionResult& result, bool source_is_scalar);
StringBuffer source_; StringBuffer source_inner_;
uint32_t depth_ = 0; uint32_t depth_ = 0;
char depth_prefix_[16] = {0}; char depth_prefix_[32] = {0};
bool cf_wrote_pc_ = false; bool cf_wrote_pc_ = false;
bool cf_exec_pred_ = false; bool cf_exec_pred_ = false;