Switching from fork to main glslang spirv builder.
This commit is contained in:
@@ -7,6 +7,7 @@ project("xenia-gpu")
|
||||
kind("StaticLib")
|
||||
language("C++")
|
||||
links({
|
||||
"glslang-spirv",
|
||||
"snappy",
|
||||
"spirv-tools",
|
||||
"xenia-base",
|
||||
@@ -29,6 +30,7 @@ project("xenia-gpu-shader-compiler")
|
||||
language("C++")
|
||||
links({
|
||||
"gflags",
|
||||
"glslang-spirv",
|
||||
"spirv-tools",
|
||||
"xenia-base",
|
||||
"xenia-gpu",
|
||||
|
||||
@@ -137,7 +137,7 @@ bool ShaderTranslator::Translate(Shader* shader) {
|
||||
constant_register_map_.packed_byte_length +=
|
||||
4 * xe::bit_count(constant_register_map_.int_bitmap);
|
||||
// Direct map between words and words we upload.
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
if (constant_register_map_.bool_bitmap[i]) {
|
||||
constant_register_map_.packed_byte_length += 4;
|
||||
}
|
||||
@@ -161,6 +161,8 @@ bool ShaderTranslator::Translate(Shader* shader) {
|
||||
}
|
||||
}
|
||||
|
||||
PostTranslation(shader);
|
||||
|
||||
return shader->is_valid_;
|
||||
}
|
||||
|
||||
|
||||
@@ -71,6 +71,13 @@ class ShaderTranslator {
|
||||
return std::vector<uint8_t>();
|
||||
}
|
||||
|
||||
// Handles post-translation tasks when the shader has been fully translated.
|
||||
virtual void PostTranslation(Shader* shader) {}
|
||||
// Sets the host disassembly on a shader.
|
||||
void set_host_disassembly(Shader* shader, std::string value) {
|
||||
shader->host_disassembly_ = std::move(value);
|
||||
}
|
||||
|
||||
// Handles translation for control flow label addresses.
|
||||
// This is triggered once for each label required (due to control flow
|
||||
// operations) before any of the instructions within the target exec.
|
||||
|
||||
@@ -11,124 +11,182 @@
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "xenia/base/logging.h"
|
||||
|
||||
namespace xe {
|
||||
namespace gpu {
|
||||
|
||||
using spv::GLSLstd450;
|
||||
using spv::Id;
|
||||
using spv::Op;
|
||||
|
||||
SpirvShaderTranslator::SpirvShaderTranslator() = default;
|
||||
|
||||
SpirvShaderTranslator::~SpirvShaderTranslator() = default;
|
||||
|
||||
void SpirvShaderTranslator::StartTranslation() {
|
||||
auto& e = emitter_;
|
||||
// Create a new builder.
|
||||
builder_ = std::make_unique<spv::Builder>(0xFFFFFFFF);
|
||||
auto& b = *builder_;
|
||||
|
||||
auto fn = e.MakeMainEntry();
|
||||
auto float_1_0 = e.MakeFloatConstant(1.0f);
|
||||
auto acos = e.CreateGlslStd450InstructionCall(
|
||||
spv::Decoration::Invariant, e.MakeFloatType(32), spv::GLSLstd450::kAcos,
|
||||
{float_1_0});
|
||||
e.MakeReturn(true);
|
||||
// Import required modules.
|
||||
glsl_std_450_instruction_set_ = b.import("GLSL.std.450");
|
||||
|
||||
// Configure environment.
|
||||
b.setSource(spv::SourceLanguage::SourceLanguageUnknown, 0);
|
||||
b.setMemoryModel(spv::AddressingModel::AddressingModelLogical,
|
||||
spv::MemoryModel::MemoryModelGLSL450);
|
||||
b.addCapability(spv::Capability::CapabilityShader);
|
||||
b.addCapability(spv::Capability::CapabilityGenericPointer);
|
||||
if (is_vertex_shader()) {
|
||||
b.addCapability(spv::Capability::CapabilityClipDistance);
|
||||
b.addCapability(spv::Capability::CapabilityCullDistance);
|
||||
}
|
||||
if (is_pixel_shader()) {
|
||||
b.addCapability(spv::Capability::CapabilityDerivativeControl);
|
||||
}
|
||||
|
||||
// main() entry point.
|
||||
auto mainFn = b.makeMain();
|
||||
if (is_vertex_shader()) {
|
||||
b.addEntryPoint(spv::ExecutionModel::ExecutionModelVertex, mainFn, "main");
|
||||
} else {
|
||||
b.addEntryPoint(spv::ExecutionModel::ExecutionModelFragment, mainFn,
|
||||
"main");
|
||||
b.addExecutionMode(mainFn, spv::ExecutionModeOriginUpperLeft);
|
||||
}
|
||||
|
||||
// TODO(benvanik): transform feedback.
|
||||
if (false) {
|
||||
b.addCapability(spv::Capability::CapabilityTransformFeedback);
|
||||
b.addExecutionMode(mainFn, spv::ExecutionMode::ExecutionModeXfb);
|
||||
}
|
||||
|
||||
auto float_1_0 = b.makeFloatConstant(2.0f);
|
||||
auto acos = CreateGlslStd450InstructionCall(
|
||||
spv::Decoration::DecorationInvariant, b.makeFloatType(32),
|
||||
GLSLstd450::kAcos, {float_1_0});
|
||||
}
|
||||
|
||||
std::vector<uint8_t> SpirvShaderTranslator::CompleteTranslation() {
|
||||
auto& e = emitter_;
|
||||
auto& b = *builder_;
|
||||
|
||||
b.makeReturn(false);
|
||||
|
||||
std::vector<uint32_t> spirv_words;
|
||||
e.Serialize(spirv_words);
|
||||
b.dump(spirv_words);
|
||||
|
||||
// Cleanup builder.
|
||||
builder_.reset();
|
||||
|
||||
// Copy bytes out.
|
||||
// TODO(benvanik): avoid copy?
|
||||
std::vector<uint8_t> spirv_bytes;
|
||||
spirv_bytes.resize(spirv_words.size() * 4);
|
||||
std::memcpy(spirv_bytes.data(), spirv_words.data(), spirv_bytes.size());
|
||||
return spirv_bytes;
|
||||
}
|
||||
|
||||
void SpirvShaderTranslator::PostTranslation(Shader* shader) {
|
||||
// TODO(benvanik): only if needed? could be slowish.
|
||||
auto disasm = disassembler_.Disassemble(
|
||||
reinterpret_cast<const uint32_t*>(shader->translated_binary().data()),
|
||||
shader->translated_binary().size() / 4);
|
||||
if (disasm->has_error()) {
|
||||
XELOGE("Failed to disassemble SPIRV - invalid?");
|
||||
return;
|
||||
}
|
||||
set_host_disassembly(shader, disasm->to_string());
|
||||
}
|
||||
|
||||
void SpirvShaderTranslator::ProcessLabel(uint32_t cf_index) {
|
||||
auto& e = emitter_;
|
||||
auto& b = *builder_;
|
||||
|
||||
EmitUnimplementedTranslationError();
|
||||
}
|
||||
|
||||
void SpirvShaderTranslator::ProcessControlFlowNopInstruction() {
|
||||
auto& e = emitter_;
|
||||
auto& b = *builder_;
|
||||
|
||||
EmitUnimplementedTranslationError();
|
||||
}
|
||||
|
||||
void SpirvShaderTranslator::ProcessExecInstructionBegin(
|
||||
const ParsedExecInstruction& instr) {
|
||||
auto& e = emitter_;
|
||||
auto& b = *builder_;
|
||||
|
||||
EmitUnimplementedTranslationError();
|
||||
}
|
||||
|
||||
void SpirvShaderTranslator::ProcessExecInstructionEnd(
|
||||
const ParsedExecInstruction& instr) {
|
||||
auto& e = emitter_;
|
||||
auto& b = *builder_;
|
||||
|
||||
EmitUnimplementedTranslationError();
|
||||
}
|
||||
|
||||
void SpirvShaderTranslator::ProcessLoopStartInstruction(
|
||||
const ParsedLoopStartInstruction& instr) {
|
||||
auto& e = emitter_;
|
||||
auto& b = *builder_;
|
||||
|
||||
EmitUnimplementedTranslationError();
|
||||
}
|
||||
|
||||
void SpirvShaderTranslator::ProcessLoopEndInstruction(
|
||||
const ParsedLoopEndInstruction& instr) {
|
||||
auto& e = emitter_;
|
||||
auto& b = *builder_;
|
||||
|
||||
EmitUnimplementedTranslationError();
|
||||
}
|
||||
|
||||
void SpirvShaderTranslator::ProcessCallInstruction(
|
||||
const ParsedCallInstruction& instr) {
|
||||
auto& e = emitter_;
|
||||
auto& b = *builder_;
|
||||
|
||||
EmitUnimplementedTranslationError();
|
||||
}
|
||||
|
||||
void SpirvShaderTranslator::ProcessReturnInstruction(
|
||||
const ParsedReturnInstruction& instr) {
|
||||
auto& e = emitter_;
|
||||
auto& b = *builder_;
|
||||
|
||||
EmitUnimplementedTranslationError();
|
||||
}
|
||||
|
||||
void SpirvShaderTranslator::ProcessJumpInstruction(
|
||||
const ParsedJumpInstruction& instr) {
|
||||
auto& e = emitter_;
|
||||
auto& b = *builder_;
|
||||
|
||||
EmitUnimplementedTranslationError();
|
||||
}
|
||||
|
||||
void SpirvShaderTranslator::ProcessAllocInstruction(
|
||||
const ParsedAllocInstruction& instr) {
|
||||
auto& e = emitter_;
|
||||
auto& b = *builder_;
|
||||
|
||||
EmitUnimplementedTranslationError();
|
||||
}
|
||||
|
||||
void SpirvShaderTranslator::ProcessVertexFetchInstruction(
|
||||
const ParsedVertexFetchInstruction& instr) {
|
||||
auto& e = emitter_;
|
||||
auto& b = *builder_;
|
||||
|
||||
EmitUnimplementedTranslationError();
|
||||
}
|
||||
|
||||
void SpirvShaderTranslator::ProcessTextureFetchInstruction(
|
||||
const ParsedTextureFetchInstruction& instr) {
|
||||
auto& e = emitter_;
|
||||
auto& b = *builder_;
|
||||
|
||||
EmitUnimplementedTranslationError();
|
||||
}
|
||||
|
||||
void SpirvShaderTranslator::ProcessAluInstruction(
|
||||
const ParsedAluInstruction& instr) {
|
||||
auto& e = emitter_;
|
||||
auto& b = *builder_;
|
||||
switch (instr.type) {
|
||||
case ParsedAluInstruction::Type::kNop:
|
||||
e.CreateNop();
|
||||
b.createNoResultOp(spv::Op::OpNop);
|
||||
break;
|
||||
case ParsedAluInstruction::Type::kVector:
|
||||
ProcessVectorAluInstruction(instr);
|
||||
@@ -141,14 +199,14 @@ void SpirvShaderTranslator::ProcessAluInstruction(
|
||||
|
||||
void SpirvShaderTranslator::ProcessVectorAluInstruction(
|
||||
const ParsedAluInstruction& instr) {
|
||||
auto& e = emitter_;
|
||||
auto& b = *builder_;
|
||||
|
||||
EmitUnimplementedTranslationError();
|
||||
}
|
||||
|
||||
void SpirvShaderTranslator::ProcessScalarAluInstruction(
|
||||
const ParsedAluInstruction& instr) {
|
||||
auto& e = emitter_;
|
||||
auto& b = *builder_;
|
||||
|
||||
spv::Id value_id = LoadFromOperand(instr.operands[0]);
|
||||
|
||||
@@ -157,11 +215,19 @@ void SpirvShaderTranslator::ProcessScalarAluInstruction(
|
||||
EmitUnimplementedTranslationError();
|
||||
}
|
||||
|
||||
spv::Id SpirvShaderTranslator::LoadFromOperand(const InstructionOperand& op) {
|
||||
auto& e = emitter_;
|
||||
Id SpirvShaderTranslator::CreateGlslStd450InstructionCall(
|
||||
spv::Decoration precision, Id result_type, GLSLstd450 instruction_ordinal,
|
||||
std::vector<Id> args) {
|
||||
return builder_->createBuiltinCall(result_type, glsl_std_450_instruction_set_,
|
||||
static_cast<int>(instruction_ordinal),
|
||||
args);
|
||||
}
|
||||
|
||||
spv::Id current_type_id = e.MakeFloatType(32);
|
||||
spv::Id current_value_id = e.CreateUndefined(current_type_id);
|
||||
spv::Id SpirvShaderTranslator::LoadFromOperand(const InstructionOperand& op) {
|
||||
auto& b = *builder_;
|
||||
|
||||
spv::Id current_type_id = b.makeFloatType(32);
|
||||
spv::Id current_value_id = b.createUndefined(current_type_id);
|
||||
|
||||
// storage_addressing_mode
|
||||
switch (op.storage_source) {
|
||||
@@ -186,13 +252,13 @@ spv::Id SpirvShaderTranslator::LoadFromOperand(const InstructionOperand& op) {
|
||||
}
|
||||
|
||||
if (op.is_absolute_value) {
|
||||
current_value_id = e.CreateGlslStd450InstructionCall(
|
||||
spv::Decoration::RelaxedPrecision, current_type_id,
|
||||
spv::GLSLstd450::kFAbs, {current_value_id});
|
||||
current_value_id = CreateGlslStd450InstructionCall(
|
||||
spv::Decoration::DecorationRelaxedPrecision, current_type_id,
|
||||
GLSLstd450::kFAbs, {current_value_id});
|
||||
}
|
||||
if (op.is_negated) {
|
||||
current_value_id =
|
||||
e.CreateUnaryOp(spv::Op::OpFNegate, current_type_id, current_value_id);
|
||||
b.createUnaryOp(spv::Op::OpFNegate, current_type_id, current_value_id);
|
||||
}
|
||||
|
||||
// swizzle
|
||||
@@ -202,7 +268,7 @@ spv::Id SpirvShaderTranslator::LoadFromOperand(const InstructionOperand& op) {
|
||||
|
||||
void SpirvShaderTranslator::StoreToResult(spv::Id source_value_id,
|
||||
const InstructionResult& result) {
|
||||
auto& e = emitter_;
|
||||
auto& b = *builder_;
|
||||
|
||||
if (result.storage_target == InstructionStorageTarget::kNone) {
|
||||
// No-op?
|
||||
@@ -236,7 +302,7 @@ void SpirvShaderTranslator::StoreToResult(spv::Id source_value_id,
|
||||
}
|
||||
|
||||
spv::Id current_value_id = source_value_id;
|
||||
spv::Id current_type_id = e.GetTypeId(source_value_id);
|
||||
spv::Id current_type_id = b.getTypeId(source_value_id);
|
||||
|
||||
// Clamp the input value.
|
||||
if (result.is_clamped) {
|
||||
@@ -248,7 +314,7 @@ void SpirvShaderTranslator::StoreToResult(spv::Id source_value_id,
|
||||
// swizzle
|
||||
|
||||
// Convert to the appropriate type, if needed.
|
||||
spv::Id desired_type_id = e.MakeFloatType(32);
|
||||
spv::Id desired_type_id = b.makeFloatType(32);
|
||||
if (current_value_id != desired_type_id) {
|
||||
EmitTranslationError("Type conversion on storage not yet implemented");
|
||||
}
|
||||
|
||||
@@ -14,8 +14,10 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "third_party/glslang-spirv/SpvBuilder.h"
|
||||
#include "third_party/spirv/GLSL.std.450.hpp11"
|
||||
#include "xenia/gpu/shader_translator.h"
|
||||
#include "xenia/ui/spirv/spirv_emitter.h"
|
||||
#include "xenia/ui/spirv/spirv_disassembler.h"
|
||||
|
||||
namespace xe {
|
||||
namespace gpu {
|
||||
@@ -28,6 +30,7 @@ class SpirvShaderTranslator : public ShaderTranslator {
|
||||
protected:
|
||||
void StartTranslation() override;
|
||||
std::vector<uint8_t> CompleteTranslation() override;
|
||||
void PostTranslation(Shader* shader) override;
|
||||
|
||||
void ProcessLabel(uint32_t cf_index) override;
|
||||
void ProcessControlFlowNopInstruction() override;
|
||||
@@ -48,9 +51,16 @@ class SpirvShaderTranslator : public ShaderTranslator {
|
||||
void ProcessAluInstruction(const ParsedAluInstruction& instr) override;
|
||||
|
||||
private:
|
||||
void SetupPushConstants();
|
||||
|
||||
void ProcessVectorAluInstruction(const ParsedAluInstruction& instr);
|
||||
void ProcessScalarAluInstruction(const ParsedAluInstruction& instr);
|
||||
|
||||
// Creates a call to the given GLSL intrinsic.
|
||||
spv::Id SpirvShaderTranslator::CreateGlslStd450InstructionCall(
|
||||
spv::Decoration precision, spv::Id result_type,
|
||||
spv::GLSLstd450 instruction_ordinal, std::vector<spv::Id> args);
|
||||
|
||||
// Loads an operand into a value.
|
||||
// The value returned will be in the form described in the operand (number of
|
||||
// components, etc).
|
||||
@@ -60,7 +70,11 @@ class SpirvShaderTranslator : public ShaderTranslator {
|
||||
// the proper components will be selected.
|
||||
void StoreToResult(spv::Id source_value_id, const InstructionResult& result);
|
||||
|
||||
xe::ui::spirv::SpirvEmitter emitter_;
|
||||
xe::ui::spirv::SpirvDisassembler disassembler_;
|
||||
|
||||
// TODO(benvanik): replace with something better, make reusable, etc.
|
||||
std::unique_ptr<spv::Builder> builder_;
|
||||
spv::Id glsl_std_450_instruction_set_ = 0;
|
||||
};
|
||||
|
||||
} // namespace gpu
|
||||
|
||||
@@ -22,6 +22,8 @@ VulkanShader::VulkanShader(ShaderType shader_type, uint64_t data_hash,
|
||||
|
||||
VulkanShader::~VulkanShader() = default;
|
||||
|
||||
bool VulkanShader::Prepare() { return true; }
|
||||
|
||||
} // namespace vulkan
|
||||
} // namespace gpu
|
||||
} // namespace xe
|
||||
|
||||
@@ -24,6 +24,13 @@ class VulkanShader : public Shader {
|
||||
VulkanShader(ShaderType shader_type, uint64_t data_hash,
|
||||
const uint32_t* dword_ptr, uint32_t dword_count);
|
||||
~VulkanShader() override;
|
||||
|
||||
VkShaderModule shader_module() const { return shader_module_; }
|
||||
|
||||
bool Prepare();
|
||||
|
||||
private:
|
||||
VkShaderModule shader_module_ = nullptr;
|
||||
};
|
||||
|
||||
} // namespace vulkan
|
||||
|
||||
Reference in New Issue
Block a user