diff --git a/hecl/CMakeLists.txt b/hecl/CMakeLists.txt index 3a994e8a1..adee02928 100644 --- a/hecl/CMakeLists.txt +++ b/hecl/CMakeLists.txt @@ -15,7 +15,6 @@ endif() endif() include(ApplicationTools.cmake) -add_shader(test/test) configure_file(DataSpecRegistry.hpp.in ${CMAKE_CURRENT_SOURCE_DIR}/DataSpecRegistry.hpp @ONLY) @@ -78,6 +77,3 @@ add_subdirectory(lib) add_subdirectory(blender) add_subdirectory(driver) install(DIRECTORY include/hecl DESTINATION include/hecl) - -# Runtime test -add_subdirectory(test) diff --git a/hecl/blender/hecl/srea/__init__.py b/hecl/blender/hecl/srea/__init__.py index 7974b7590..8b4bbce1a 100644 --- a/hecl/blender/hecl/srea/__init__.py +++ b/hecl/blender/hecl/srea/__init__.py @@ -322,6 +322,7 @@ def render_lightmaps(context): pixel_size = int(area_data.lightmap_resolution) # Mmm Cycles + context.scene.render.engine = 'CYCLES' context.scene.render.bake.margin = pixel_size // 256 # Iterate materials and setup cycles @@ -330,6 +331,11 @@ def render_lightmaps(context): # Set bake target node active if 'CYCLES_OUT' in mat.node_tree.nodes: mat.node_tree.nodes.active = mat.node_tree.nodes['CYCLES_OUT'] + elif mat.hecl_lightmap and not mat.library: + image_out_node = mat.node_tree.nodes.new('ShaderNodeTexImage') + mat.node_tree.nodes.active = image_out_node + image_out_node.name = 'CYCLES_OUT' + image_out_node.image = make_or_load_cycles_image(mat, area_data) else: image_out_node = mat.node_tree.nodes.new('ShaderNodeTexImage') mat.node_tree.nodes.active = image_out_node @@ -344,11 +350,11 @@ def render_lightmaps(context): for obj in context.scene.objects: if obj.type == 'MESH': - if not len(obj.data.uv_textures): + if not len(obj.data.uv_layers): continue # Make correct UV layer active - obj.data.uv_textures.active_index = 0 + obj.data.uv_layers.active_index = 0 # Make lightmaps bpy.ops.object.bake('INVOKE_DEFAULT', type='DIFFUSE', pass_filter={'DIRECT', 'INDIRECT'}) diff --git a/hecl/blender/hecl_blendershell.py b/hecl/blender/hecl_blendershell.py index 04470707c..c9c036d66 100644 --- a/hecl/blender/hecl_blendershell.py +++ b/hecl/blender/hecl_blendershell.py @@ -2,10 +2,15 @@ import bpy, sys, os, re, struct, traceback ARGS_PATTERN = re.compile(r'''(?:"([^"]+)"|'([^']+)'|(\S+))''') +# Background mode seems to require quit() in some 2.80 builds +def _quitblender(): + bpy.ops.wm.quit_blender() + quit() + # Extract pipe file descriptors from arguments print('HECL Blender Launch', sys.argv) if '--' not in sys.argv: - bpy.ops.wm.quit_blender() + _quitblender() args = sys.argv[sys.argv.index('--')+1:] readfd = int(args[0]) writefd = int(args[1]) @@ -29,7 +34,7 @@ def readpipestr(): read_bytes = os.read(readfd, 4) if len(read_bytes) != 4: print('HECL connection lost or desynchronized') - bpy.ops.wm.quit_blender() + _quitblender() read_len = struct.unpack('I', read_bytes)[0] return os.read(readfd, read_len) @@ -44,7 +49,7 @@ def writepipebuf(linebytes): def quitblender(): writepipestr(b'QUITTING') - bpy.ops.wm.quit_blender() + _quitblender() class PathHasher: def hashpath32(self, path): @@ -62,6 +67,11 @@ class PathHasher: return int(read_str[0:16], 16) return 0 +# Ensure Blender 2.8 is being used +if bpy.app.version < (2, 80, 0): + writepipestr(b'NOT280') + _quitblender() + # If there's a third argument, use it as the .zip path containing the addon did_install = False if len(args) >= 4 and args[3] != 'SKIPINSTALL': @@ -80,12 +90,12 @@ try: import hecl except: writepipestr(b'NOADDON') - bpy.ops.wm.quit_blender() + _quitblender() # Quit if just installed if did_install: writepipestr(b'ADDONINSTALLED') - bpy.ops.wm.quit_blender() + _quitblender() # Intro handshake writepipestr(b'READY') @@ -108,7 +118,7 @@ def read_cmdargs(): cmdline = readpipestr() if cmdline == b'': print('HECL connection lost') - bpy.ops.wm.quit_blender() + _quitblender() cmdargs = [] for match in ARGS_PATTERN.finditer(cmdline.decode()): cmdargs.append(match.group(match.lastindex)) diff --git a/hecl/extern/boo b/hecl/extern/boo index 3ad748f28..b340a8a42 160000 --- a/hecl/extern/boo +++ b/hecl/extern/boo @@ -1 +1 @@ -Subproject commit 3ad748f28b5377027c900ded38eeccdfeb7fe7f6 +Subproject commit b340a8a42ecf10560891eab65d8c59a6f2640ccc diff --git a/hecl/lib/Backend/GLSL.cpp b/hecl/lib/Backend/GLSL.cpp deleted file mode 100644 index 5f712660b..000000000 --- a/hecl/lib/Backend/GLSL.cpp +++ /dev/null @@ -1,365 +0,0 @@ -#include "hecl/Backend/GLSL.hpp" -#include "hecl/Runtime.hpp" -#include "athena/MemoryReader.hpp" -#include "athena/MemoryWriter.hpp" -#include "boo/graphicsdev/GLSLMacros.hpp" - -static logvisor::Module Log("hecl::Backend::GLSL"); - -namespace hecl::Backend { - -std::string GLSL::EmitTexGenSource2(TexGenSrc src, int uvIdx) const { - switch (src) { - case TexGenSrc::Position: - return "objPos.xy"; - case TexGenSrc::Normal: - return "objNorm.xy"; - case TexGenSrc::UV: - return hecl::Format("uvIn[%u]", uvIdx); - default: - break; - } - return std::string(); -} - -std::string GLSL::EmitTexGenSource4(TexGenSrc src, int uvIdx) const { - switch (src) { - case TexGenSrc::Position: - return "vec4(objPos.xyz, 1.0)"; - case TexGenSrc::Normal: - return "vec4(objNorm.xyz, 1.0)"; - case TexGenSrc::UV: - return hecl::Format("vec4(uvIn[%u], 0.0, 1.0)", uvIdx); - default: - break; - } - return std::string(); -} - -std::string GLSL::GenerateVertInStruct(unsigned col, unsigned uv, unsigned w) const { - std::string retval = - "layout(location=0) in vec3 posIn;\n" - "layout(location=1) in vec3 normIn;\n"; - - unsigned idx = 2; - if (col) { - retval += hecl::Format("layout(location=%u) in vec4 colIn[%u];\n", idx, col); - idx += col; - } - - if (uv) { - retval += hecl::Format("layout(location=%u) in vec2 uvIn[%u];\n", idx, uv); - idx += uv; - } - - if (w) { - retval += hecl::Format("layout(location=%u) in vec4 weightIn[%u];\n", idx, w); - } - - return retval; -} - -std::string GLSL::GenerateVertToFragStruct(size_t extTexCount, bool reflectionCoords) const { - std::string retval = - "struct VertToFrag\n" - "{\n" - " vec4 mvPos;\n" - " vec4 mvNorm;\n"; - - if (m_tcgs.size()) - retval += hecl::Format(" vec2 tcgs[%u];\n", unsigned(m_tcgs.size())); - if (extTexCount) - retval += hecl::Format(" vec2 extTcgs[%u];\n", unsigned(extTexCount)); - - if (reflectionCoords) - retval += - " vec2 reflectTcgs[2];\n" - " float reflectAlpha;\n"; - - return retval + "};\n"; -} - -std::string GLSL::GenerateVertUniformStruct(unsigned skinSlots, bool reflectionCoords) const { - std::string retval; - if (skinSlots == 0) { - retval = - "UBINDING0 uniform HECLVertUniform\n" - "{\n" - " mat4 mv;\n" - " mat4 mvInv;\n" - " mat4 proj;\n" - "};\n"; - } else { - retval = hecl::Format( - "UBINDING0 uniform HECLVertUniform\n" - "{\n" - " mat4 objs[%u];\n" - " mat4 objsInv[%u];\n" - " mat4 mv;\n" - " mat4 mvInv;\n" - " mat4 proj;\n" - "};\n", - skinSlots, skinSlots); - } - - retval += - "struct HECLTCGMatrix\n" - "{\n" - " mat4 mtx;\n" - " mat4 postMtx;\n" - "};\n" - "UBINDING1 uniform HECLTexMtxUniform\n" - "{\n" - " HECLTCGMatrix texMtxs[8];\n" - "};\n"; - - if (reflectionCoords) - retval += - "UBINDING3 uniform HECLReflectMtx\n" - "{\n" - " mat4 indMtx;\n" - " mat4 reflectMtx;\n" - " float reflectAlpha;\n" - "};\n" - "\n"; - - return retval; -} - -std::string GLSL::GenerateAlphaTest() const { - return " if (colorOut.a < 0.25)\n" - " {\n" - " discard;\n" - " }\n"; -} - -std::string GLSL::GenerateReflectionExpr(ReflectionType type) const { - switch (type) { - case ReflectionType::None: - default: - return "vec3(0.0, 0.0, 0.0)"; - case ReflectionType::Simple: - return "texture(reflectionTex, vtf.reflectTcgs[1]).rgb * vtf.reflectAlpha"; - case ReflectionType::Indirect: - return "texture(reflectionTex, (texture(reflectionIndTex, vtf.reflectTcgs[0]).ab - " - "vec2(0.5, 0.5)) * vec2(0.5, 0.5) + vtf.reflectTcgs[1]).rgb * vtf.reflectAlpha"; - } -} - -void GLSL::reset(const IR& ir, Diagnostics& diag) { - /* Common programmable interpretation */ - ProgrammableCommon::reset(ir, diag, "GLSL"); -} - -std::string GLSL::makeVert(unsigned col, unsigned uv, unsigned w, unsigned s, size_t extTexCount, - const TextureInfo* extTexs, ReflectionType reflectionType) const { - extTexCount = std::min(int(extTexCount), BOO_GLSL_MAX_TEXTURE_COUNT - int(m_tcgs.size())); - std::string retval = GenerateVertInStruct(col, uv, w) + "\n" + - GenerateVertToFragStruct(extTexCount, reflectionType != ReflectionType::None) + "\n" + - GenerateVertUniformStruct(s, reflectionType != ReflectionType::None) + - "SBINDING(0) out VertToFrag vtf;\n\n" - "void main()\n{\n"; - - if (s) { - /* skinned */ - retval += - " vec4 objPos = vec4(0.0,0.0,0.0,0.0);\n" - " vec4 objNorm = vec4(0.0,0.0,0.0,0.0);\n"; - for (size_t i = 0; i < s; ++i) - retval += hecl::Format(" objPos += (objs[%" PRISize "] * vec4(posIn, 1.0)) * weightIn[%" PRISize "][%" PRISize - "];\n" - " objNorm += (objsInv[%" PRISize "] * vec4(normIn, 1.0)) * weightIn[%" PRISize - "][%" PRISize "];\n", - i, i / 4, i % 4, i, i / 4, i % 4); - retval += - " objPos[3] = 1.0;\n" - " objNorm = vec4(normalize(objNorm.xyz), 0.0);\n" - " vtf.mvPos = mv * objPos;\n" - " vtf.mvNorm = vec4(normalize((mvInv * objNorm).xyz), 0.0);\n" - " gl_Position = proj * vtf.mvPos;\n"; - } else { - /* non-skinned */ - retval += - " vec4 objPos = vec4(posIn, 1.0);\n" - " vec4 objNorm = vec4(normIn, 0.0);\n" - " vtf.mvPos = mv * objPos;\n" - " vtf.mvNorm = mvInv * objNorm;\n" - " gl_Position = proj * vtf.mvPos;\n"; - } - - retval += " vec4 tmpProj;\n"; - - int tcgIdx = 0; - for (const TexCoordGen& tcg : m_tcgs) { - if (tcg.m_mtx < 0) - retval += hecl::Format(" vtf.tcgs[%u] = %s;\n", tcgIdx, EmitTexGenSource2(tcg.m_src, tcg.m_uvIdx).c_str()); - else - retval += hecl::Format( - " tmpProj = texMtxs[%u].postMtx * vec4(%s((texMtxs[%u].mtx * %s).xyz), 1.0);\n" - " vtf.tcgs[%u] = (tmpProj / tmpProj.w).xy;\n", - tcg.m_mtx, tcg.m_norm ? "normalize" : "", tcg.m_mtx, EmitTexGenSource4(tcg.m_src, tcg.m_uvIdx).c_str(), - tcgIdx); - ++tcgIdx; - } - - for (int i = 0; i < extTexCount; ++i) { - const TextureInfo& extTex = extTexs[i]; - if (extTex.mtxIdx < 0) - retval += hecl::Format(" vtf.extTcgs[%u] = %s;\n", i, EmitTexGenSource2(extTex.src, extTex.uvIdx).c_str()); - else - retval += hecl::Format( - " tmpProj = texMtxs[%u].postMtx * vec4(%s((texMtxs[%u].mtx * %s).xyz), 1.0);\n" - " vtf.extTcgs[%u] = (tmpProj / tmpProj.w).xy;\n", - extTex.mtxIdx, extTex.normalize ? "normalize" : "", extTex.mtxIdx, - EmitTexGenSource4(extTex.src, extTex.uvIdx).c_str(), i); - } - - if (reflectionType != ReflectionType::None) - retval += - " vtf.reflectTcgs[0] = normalize((indMtx * vec4(posIn, 1.0)).xz) * vec2(0.5, 0.5) + vec2(0.5, 0.5);\n" - " vtf.reflectTcgs[1] = (reflectMtx * vec4(posIn, 1.0)).xy;\n" - " vtf.reflectAlpha = reflectAlpha;\n"; - - return retval + "}\n"; -} - -std::string GLSL::makeFrag(size_t blockCount, const char** blockNames, bool alphaTest, ReflectionType reflectionType, - BlendFactor srcFactor, BlendFactor dstFactor, const Function& lighting) const { - std::string lightingSrc; - if (!lighting.m_source.empty()) - lightingSrc = lighting.m_source; - else - lightingSrc = - "const vec4 colorReg0 = vec4(1.0);\n" - "const vec4 colorReg1 = vec4(1.0);\n" - "const vec4 colorReg2 = vec4(1.0);\n" - "const vec4 mulColor = vec4(1.0);\n" - "const vec4 addColor = vec4(0.0);\n" - "\n"; - - std::string texMapDecl; - for (unsigned i = 0; i < m_texMapEnd; ++i) - texMapDecl += hecl::Format("TBINDING%u uniform sampler2D tex%u;\n", i, i); - if (reflectionType == ReflectionType::Indirect) - texMapDecl += hecl::Format( - "TBINDING%u uniform sampler2D reflectionIndTex;\n" - "TBINDING%u uniform sampler2D reflectionTex;\n", - m_texMapEnd, m_texMapEnd + 1); - else if (reflectionType == ReflectionType::Simple) - texMapDecl += hecl::Format("TBINDING%u uniform sampler2D reflectionTex;\n", m_texMapEnd); - - std::string retval = std::string("#extension GL_ARB_shader_image_load_store: enable\n") + "#define BLEND_SRC_" + - BlendFactorToDefine(srcFactor, m_blendSrc) + "\n" + "#define BLEND_DST_" + - BlendFactorToDefine(dstFactor, m_blendDst) + "\n" + - GenerateVertToFragStruct(0, reflectionType != ReflectionType::None) + - (!alphaTest ? "#ifdef GL_ARB_shader_image_load_store\n" - "layout(early_fragment_tests) in;\n" - "#endif\n" - : "") + - "layout(location=0) out vec4 colorOut;\n" + texMapDecl + "SBINDING(0) in VertToFrag vtf;\n\n" + - lightingSrc + "\n" + "void main()\n{\n"; - - if (m_lighting) { - if (!lighting.m_entry.empty()) - retval += - hecl::Format(" vec4 lighting = %s(vtf.mvPos.xyz, normalize(vtf.mvNorm.xyz));\n", lighting.m_entry.data()); - else - retval += " vec4 lighting = vec4(1.0,1.0,1.0,1.0);\n"; - } - - unsigned sampIdx = 0; - for (const TexSampling& sampling : m_texSamplings) - retval += hecl::Format(" vec4 sampling%u = texture(tex%u, vtf.tcgs[%u]);\n", sampIdx++, sampling.mapIdx, - sampling.tcgIdx); - - std::string reflectionExpr = GenerateReflectionExpr(reflectionType); - - if (m_alphaExpr.size()) - retval += " colorOut = vec4(" + m_colorExpr + " + " + reflectionExpr + ", " + m_alphaExpr + - ") * mulColor + addColor;\n"; - else - retval += " colorOut = vec4(" + m_colorExpr + " + " + reflectionExpr + ", 1.0) * mulColor + addColor;\n"; - - return retval + (alphaTest ? GenerateAlphaTest() : "") + "}\n"; -} - -std::string GLSL::makeFrag(size_t blockCount, const char** blockNames, bool alphaTest, ReflectionType reflectionType, - BlendFactor srcFactor, BlendFactor dstFactor, const Function& lighting, const Function& post, - size_t extTexCount, const TextureInfo* extTexs, bool diffuseOnly) const { - std::string lightingSrc; - if (!lighting.m_source.empty()) - lightingSrc = lighting.m_source; - else - lightingSrc = - "const vec4 colorReg0 = vec4(1.0);\n" - "const vec4 colorReg1 = vec4(1.0);\n" - "const vec4 colorReg2 = vec4(1.0);\n" - "const vec4 mulColor = vec4(1.0);\n" - "const vec4 addColor = vec4(0.0);\n" - "\n"; - - std::string postSrc; - if (!post.m_source.empty()) - postSrc = post.m_source; - - std::string postEntry; - if (!post.m_entry.empty()) - postEntry = post.m_entry; - - std::string texMapDecl; - for (unsigned i = 0; i < m_texMapEnd; ++i) - texMapDecl += hecl::Format("TBINDING%u uniform sampler2D tex%u;\n", i, i); - if (reflectionType == ReflectionType::Indirect) - texMapDecl += hecl::Format( - "TBINDING%u uniform sampler2D reflectionIndTex;\n" - "TBINDING%u uniform sampler2D reflectionTex;\n", - m_texMapEnd, m_texMapEnd + 1); - else if (reflectionType == ReflectionType::Simple) - texMapDecl += hecl::Format("TBINDING%u uniform sampler2D reflectionTex;\n", m_texMapEnd); - - uint32_t extTexBits = 0; - for (int i = 0; i < extTexCount; ++i) { - const TextureInfo& extTex = extTexs[i]; - if (!(extTexBits & (1 << extTex.mapIdx))) { - texMapDecl += hecl::Format("TBINDING%u uniform sampler2D extTex%u;\n", extTex.mapIdx, extTex.mapIdx); - extTexBits |= (1 << extTex.mapIdx); - } - } - - std::string retval = std::string("#extension GL_ARB_shader_image_load_store: enable\n") + "#define BLEND_SRC_" + - BlendFactorToDefine(srcFactor, m_blendSrc) + "\n" + "#define BLEND_DST_" + - BlendFactorToDefine(dstFactor, m_blendDst) + "\n" + - GenerateVertToFragStruct(extTexCount, reflectionType != ReflectionType::None) + - (!alphaTest ? "\n#ifdef GL_ARB_shader_image_load_store\n" - "layout(early_fragment_tests) in;\n" - "#endif\n" - : "") + - "\nlayout(location=0) out vec4 colorOut;\n" + texMapDecl + "SBINDING(0) in VertToFrag vtf;\n\n" + - lightingSrc + "\n" + postSrc + "\nvoid main()\n{\n"; - - if (m_lighting) { - if (!lighting.m_entry.empty()) - retval += - hecl::Format(" vec4 lighting = %s(vtf.mvPos.xyz, normalize(vtf.mvNorm.xyz));\n", lighting.m_entry.data()); - else - retval += " vec4 lighting = vec4(1.0,1.0,1.0,1.0);\n"; - } - - unsigned sampIdx = 0; - for (const TexSampling& sampling : m_texSamplings) - retval += hecl::Format(" vec4 sampling%u = texture(tex%u, vtf.tcgs[%u]);\n", sampIdx++, sampling.mapIdx, - sampling.tcgIdx); - - std::string reflectionExpr = GenerateReflectionExpr(reflectionType); - - if (m_alphaExpr.size() && !diffuseOnly) - retval += " colorOut = " + postEntry + "(vec4(" + m_colorExpr + " + " + reflectionExpr + ", " + m_alphaExpr + - ")) * mulColor + addColor;\n"; - else - retval += " colorOut = " + postEntry + "(vec4(" + (diffuseOnly ? m_diffuseColorExpr : m_colorExpr) + " + " + - reflectionExpr + ", 1.0)) * mulColor + addColor;\n"; - - return retval + (alphaTest ? GenerateAlphaTest() : "") + "}\n"; -} - -} // namespace hecl::Backend diff --git a/hecl/lib/Backend/GX.cpp b/hecl/lib/Backend/GX.cpp deleted file mode 100644 index 304a4feea..000000000 --- a/hecl/lib/Backend/GX.cpp +++ /dev/null @@ -1,703 +0,0 @@ -#include "hecl/Backend/GX.hpp" - -namespace hecl::Backend { - -template <> -void GX::Color::Enumerate::Read>(typename Read::StreamT& reader) { - reader.readUBytesToBuf(&num, 4); -} -template <> -void GX::Color::Enumerate::Write>(typename Write::StreamT& writer) { - writer.writeUBytes(reinterpret_cast(&num), 4); -} -template <> -void GX::Color::Enumerate::BinarySize>(typename BinarySize::StreamT& s) { - s += 4; -} - -unsigned GX::addKColor(Diagnostics& diag, const SourceLocation& loc, const Color& color) { - for (unsigned i = 0; i < m_kcolorCount; ++i) - if (m_kcolors[i] == color) - return i; - if (m_kcolorCount >= 4) - diag.reportBackendErr(loc, "GX KColor overflow"); - m_kcolors[m_kcolorCount] = color; - m_kcolors[m_kcolorCount].color[3] = 0; - return m_kcolorCount++; -} - -unsigned GX::addKAlpha(Diagnostics& diag, const SourceLocation& loc, float alpha) { - uint8_t ai = uint8_t(std::min(std::max(alpha * 255.f, 0.f), 255.f)); - for (unsigned i = 0; i < m_kcolorCount; ++i) { - if (m_kcolors[i].color[3] == ai) - return i; - else if (m_kcolors[i].color[3] == 0) { - m_kcolors[i].color[3] = ai; - return i; - } - } - if (m_kcolorCount >= 4) - diag.reportBackendErr(loc, "GX KColor overflow"); - m_kcolors[m_kcolorCount] = ai; - return m_kcolorCount++; -} - -unsigned GX::addTexCoordGen(Diagnostics& diag, const SourceLocation& loc, TexGenSrc src, TexMtx mtx, bool norm, - PTTexMtx pmtx) { - for (unsigned i = 0; i < m_tcgCount; ++i) { - TexCoordGen& tcg = m_tcgs[i]; - if (tcg.m_src == src && tcg.m_mtx == mtx && tcg.m_norm == norm && tcg.m_pmtx == pmtx) - return i; - } - if (m_tcgCount >= 8) - diag.reportBackendErr(loc, "GX TexCoordGen overflow"); - GX::TexCoordGen& newTcg = m_tcgs[m_tcgCount]; - newTcg.m_src = src; - newTcg.m_mtx = mtx; - newTcg.m_norm = norm; - newTcg.m_pmtx = pmtx; - return m_tcgCount++; -} - -GX::TEVStage& GX::addTEVStage(Diagnostics& diag, const SourceLocation& loc) { - if (m_tevCount >= 16) - diag.reportBackendErr(loc, "GX TEV stage overflow"); - GX::TEVStage& newTEV = m_tevs[m_tevCount]; - newTEV.m_loc = loc; - if (m_tevCount) { - newTEV.m_prev = &m_tevs[m_tevCount - 1]; - newTEV.m_prev->m_next = &newTEV; - } - ++m_tevCount; - return newTEV; -} - -GX::TEVStage& GX::addAlphaTEVStage(Diagnostics& diag, const SourceLocation& loc) { - ++m_alphaTraceStage; - while (m_tevCount < m_alphaTraceStage + 1) { - TEVStage& stage = addTEVStage(diag, loc); - stage.m_color[3] = CC_CPREV; - stage.m_alpha[3] = CA_APREV; - } - return m_tevs[m_alphaTraceStage]; -} - -unsigned GX::RecursiveTraceTexGen(const IR& ir, Diagnostics& diag, const IR::Instruction& inst, TexMtx mtx, - bool normalize, PTTexMtx pmtx) { - if (inst.m_op != IR::OpType::Call) - diag.reportBackendErr(inst.m_loc, "TexCoordGen resolution requires function"); - - const std::string& tcgName = inst.m_call.m_name; - if (!tcgName.compare("UV")) { - if (inst.getChildCount() < 1) - diag.reportBackendErr(inst.m_loc, "TexCoordGen UV(layerIdx) requires one argument"); - const IR::Instruction& idxInst = inst.getChildInst(ir, 0); - auto& idxImm = idxInst.getImmVec(); - return addTexCoordGen(diag, inst.m_loc, TexGenSrc(TG_TEX0 + unsigned(idxImm.simd[0])), mtx, normalize, pmtx); - } else if (!tcgName.compare("Normal")) - return addTexCoordGen(diag, inst.m_loc, TG_NRM, mtx, normalize, pmtx); - else if (!tcgName.compare("View")) - return addTexCoordGen(diag, inst.m_loc, TG_POS, mtx, normalize, pmtx); - - /* Otherwise treat as game-specific function */ - const IR::Instruction& tcgSrcInst = inst.getChildInst(ir, 0); - bool doNorm = normalize || tcgName.back() == 'N'; - unsigned idx = RecursiveTraceTexGen(ir, diag, tcgSrcInst, TexMtx(TEXMTX0 + m_texMtxCount * 3), doNorm, - doNorm ? PTTexMtx(PTTEXMTX0 + m_texMtxCount * 3) : PTIDENTITY); - GX::TexCoordGen& tcg = m_tcgs[idx]; - m_texMtxRefs[m_texMtxCount] = &tcg; - ++m_texMtxCount; - tcg.m_gameFunction = tcgName; - tcg.m_gameArgs.clear(); - for (int i = 1; i < inst.getChildCount(); ++i) { - const IR::Instruction& ci = inst.getChildInst(ir, i); - tcg.m_gameArgs.push_back(ci.getImmVec()); - } - return idx; -} - -GX::TraceResult GX::RecursiveTraceColor(const IR& ir, Diagnostics& diag, const IR::Instruction& inst, - bool swizzleAlpha) { - switch (inst.m_op) { - case IR::OpType::Call: { - const std::string& name = inst.m_call.m_name; - bool normalize = false; - if (!name.compare("Texture") || (normalize = true && !name.compare("TextureN"))) { - TEVStage& newStage = addTEVStage(diag, inst.m_loc); - - if (inst.getChildCount() < 2) - diag.reportBackendErr(inst.m_loc, "Texture(map, texgen) requires 2 arguments"); - - const IR::Instruction& mapInst = inst.getChildInst(ir, 0); - auto& mapImm = mapInst.getImmVec(); - newStage.m_texMapIdx = unsigned(mapImm.simd[0]); - newStage.m_color[0] = swizzleAlpha ? CC_TEXA : CC_TEXC; - - const IR::Instruction& tcgInst = inst.getChildInst(ir, 1); - newStage.m_texGenIdx = RecursiveTraceTexGen(ir, diag, tcgInst, IDENTITY, normalize, PTIDENTITY); - - return TraceResult(&newStage); - } else if (!name.compare("ColorReg")) { - const IR::Instruction& idxInst = inst.getChildInst(ir, 0); - unsigned idx = unsigned(idxInst.getImmVec().simd[0]); - if (swizzleAlpha) - m_aRegMask |= 1 << idx; - else - m_cRegMask |= 1 << idx; - return TraceResult(TevColorArg((swizzleAlpha ? CC_A0 : CC_C0) + idx * 2)); - } else if (!name.compare("Lighting")) { - return TraceResult(swizzleAlpha ? CC_RASA : CC_RASC); - } else - diag.reportBackendErr(inst.m_loc, "GX backend unable to interpret '%s'", name.c_str()); - break; - } - case IR::OpType::LoadImm: { - const atVec4f& vec = inst.m_loadImm.m_immVec; - if (vec.simd[0] == 0.f && vec.simd[1] == 0.f && vec.simd[2] == 0.f) - return TraceResult(CC_ZERO); - else if (vec.simd[0] == 1.f && vec.simd[1] == 1.f && vec.simd[2] == 1.f) - return TraceResult(CC_ONE); - unsigned idx = addKColor(diag, inst.m_loc, vec); - return TraceResult(TevKColorSel(TEV_KCSEL_K0 + idx)); - } - case IR::OpType::Arithmetic: { - ArithmeticOp op = inst.m_arithmetic.m_op; - const IR::Instruction& aInst = inst.getChildInst(ir, 0); - const IR::Instruction& bInst = inst.getChildInst(ir, 1); - TraceResult aTrace; - TraceResult bTrace; - if (aInst.m_op != IR::OpType::Arithmetic && bInst.m_op == IR::OpType::Arithmetic) { - bTrace = RecursiveTraceColor(ir, diag, bInst); - aTrace = RecursiveTraceColor(ir, diag, aInst); - } else { - aTrace = RecursiveTraceColor(ir, diag, aInst); - bTrace = RecursiveTraceColor(ir, diag, bInst); - } - if (aTrace.type == TraceResult::Type::TEVStage && bTrace.type == TraceResult::Type::TEVStage && - getStageIdx(aTrace.tevStage) > getStageIdx(bTrace.tevStage)) - std::swap(aTrace, bTrace); - - TevKColorSel newKColor = TEV_KCSEL_1; - if (aTrace.type == TraceResult::Type::TEVKColorSel && bTrace.type == TraceResult::Type::TEVKColorSel) - diag.reportBackendErr(inst.m_loc, "unable to handle 2 KColors in one stage"); - else if (aTrace.type == TraceResult::Type::TEVKColorSel) { - newKColor = aTrace.tevKColorSel; - aTrace.type = TraceResult::Type::TEVColorArg; - aTrace.tevColorArg = CC_KONST; - } else if (bTrace.type == TraceResult::Type::TEVKColorSel) { - newKColor = bTrace.tevKColorSel; - bTrace.type = TraceResult::Type::TEVColorArg; - bTrace.tevColorArg = CC_KONST; - } - - switch (op) { - case ArithmeticOp::Add: { - if (aTrace.type == TraceResult::Type::TEVStage && bTrace.type == TraceResult::Type::TEVStage) { - TEVStage* a = aTrace.tevStage; - TEVStage* b = bTrace.tevStage; - if (b->m_prev != a) { - a->m_cRegOut = TEVLAZY; - b->m_color[3] = CC_LAZY; - b->m_lazyCInIdx = m_cRegLazy; - a->m_lazyCOutIdx = m_cRegLazy++; - } else if (b == &m_tevs[m_tevCount - 1] && a->m_texMapIdx == b->m_texMapIdx && - a->m_texGenIdx == b->m_texGenIdx && a->m_color[3] == CC_ZERO && b->m_color[0] != CC_ZERO) { - a->m_color[3] = b->m_color[0]; - --m_tevCount; - return TraceResult(a); - } else - b->m_color[3] = CC_CPREV; - return TraceResult(b); - } else if (aTrace.type == TraceResult::Type::TEVStage && bTrace.type == TraceResult::Type::TEVColorArg) { - TEVStage* a = aTrace.tevStage; - if (a->m_color[3] != CC_ZERO) - diag.reportBackendErr(inst.m_loc, "unable to modify TEV stage for add combine"); - a->m_color[3] = bTrace.tevColorArg; - a->m_kColor = newKColor; - return TraceResult(a); - } else if (aTrace.type == TraceResult::Type::TEVColorArg && bTrace.type == TraceResult::Type::TEVStage) { - TEVStage* b = bTrace.tevStage; - if (b->m_color[3] != CC_ZERO) - diag.reportBackendErr(inst.m_loc, "unable to modify TEV stage for add combine"); - b->m_color[3] = aTrace.tevColorArg; - b->m_kColor = newKColor; - return TraceResult(b); - } else if (aTrace.type == TraceResult::Type::TEVColorArg && bTrace.type == TraceResult::Type::TEVColorArg) { - TEVStage& stage = addTEVStage(diag, inst.m_loc); - stage.m_color[0] = aTrace.tevColorArg; - stage.m_color[3] = bTrace.tevColorArg; - stage.m_kColor = newKColor; - return TraceResult(&stage); - } - break; - } - case ArithmeticOp::Subtract: { - if (aTrace.type == TraceResult::Type::TEVStage && bTrace.type == TraceResult::Type::TEVStage) { - TEVStage* a = aTrace.tevStage; - TEVStage* b = bTrace.tevStage; - if (b->m_prev != a) { - a->m_cRegOut = TEVLAZY; - b->m_color[3] = CC_LAZY; - b->m_lazyCInIdx = m_cRegLazy; - a->m_lazyCOutIdx = m_cRegLazy++; - } else - b->m_color[3] = CC_CPREV; - b->m_cop = TEV_SUB; - return TraceResult(b); - } else if (aTrace.type == TraceResult::Type::TEVStage && bTrace.type == TraceResult::Type::TEVColorArg) { - TEVStage* a = aTrace.tevStage; - if (a->m_color[3] != CC_ZERO) - diag.reportBackendErr(inst.m_loc, "unable to modify TEV stage for subtract combine"); - a->m_color[3] = bTrace.tevColorArg; - a->m_kColor = newKColor; - a->m_cop = TEV_SUB; - return TraceResult(a); - } else if (aTrace.type == TraceResult::Type::TEVColorArg && bTrace.type == TraceResult::Type::TEVColorArg) { - TEVStage& stage = addTEVStage(diag, inst.m_loc); - stage.m_color[0] = aTrace.tevColorArg; - stage.m_color[3] = bTrace.tevColorArg; - stage.m_kColor = newKColor; - stage.m_cop = TEV_SUB; - return TraceResult(&stage); - } - break; - } - case ArithmeticOp::Multiply: { - if (aTrace.type == TraceResult::Type::TEVStage && bTrace.type == TraceResult::Type::TEVStage) { - TEVStage* a = aTrace.tevStage; - TEVStage* b = bTrace.tevStage; - if (b->m_color[2] != CC_ZERO) - diag.reportBackendErr(inst.m_loc, "unable to modify TEV stage for multiply combine"); - if (b->m_prev != a) { - a->m_cRegOut = TEVLAZY; - b->m_color[2] = CC_LAZY; - b->m_lazyCInIdx = m_cRegLazy; - a->m_lazyCOutIdx = m_cRegLazy++; - } else - b->m_color[2] = CC_CPREV; - b->m_color[1] = b->m_color[0]; - b->m_color[0] = CC_ZERO; - b->m_color[3] = CC_ZERO; - return TraceResult(b); - } else if (aTrace.type == TraceResult::Type::TEVColorArg && bTrace.type == TraceResult::Type::TEVColorArg) { - TEVStage& stage = addTEVStage(diag, inst.m_loc); - stage.m_color[1] = aTrace.tevColorArg; - stage.m_color[2] = bTrace.tevColorArg; - stage.m_kColor = newKColor; - return TraceResult(&stage); - } else if (aTrace.type == TraceResult::Type::TEVStage && bTrace.type == TraceResult::Type::TEVColorArg) { - TEVStage* a = aTrace.tevStage; - if (a->m_color[1] != CC_ZERO) { - if (a->m_cRegOut != TEVPREV) - diag.reportBackendErr(inst.m_loc, "unable to modify TEV stage for multiply combine"); - TEVStage& stage = addTEVStage(diag, inst.m_loc); - stage.m_color[1] = CC_CPREV; - stage.m_color[2] = bTrace.tevColorArg; - stage.m_kColor = newKColor; - return TraceResult(&stage); - } - a->m_color[1] = a->m_color[0]; - a->m_color[0] = CC_ZERO; - a->m_color[2] = bTrace.tevColorArg; - a->m_kColor = newKColor; - return TraceResult(a); - } else if (aTrace.type == TraceResult::Type::TEVColorArg && bTrace.type == TraceResult::Type::TEVStage) { - TEVStage* b = bTrace.tevStage; - if (b->m_color[1] != CC_ZERO) { - if (b->m_cRegOut != TEVPREV) - diag.reportBackendErr(inst.m_loc, "unable to modify TEV stage for multiply combine"); - TEVStage& stage = addTEVStage(diag, inst.m_loc); - stage.m_color[1] = aTrace.tevColorArg; - stage.m_color[2] = CC_CPREV; - stage.m_kColor = newKColor; - return TraceResult(&stage); - } - b->m_color[1] = b->m_color[0]; - b->m_color[0] = CC_ZERO; - b->m_color[2] = bTrace.tevColorArg; - b->m_kColor = newKColor; - return TraceResult(b); - } - break; - } - default: - diag.reportBackendErr(inst.m_loc, "invalid arithmetic op"); - } - - diag.reportBackendErr(inst.m_loc, "unable to convert arithmetic to TEV stage"); - break; - } - case IR::OpType::Swizzle: { - if (inst.m_swizzle.m_idxs[0] == 3 && inst.m_swizzle.m_idxs[1] == 3 && inst.m_swizzle.m_idxs[2] == 3 && - inst.m_swizzle.m_idxs[3] == -1) { - const IR::Instruction& cInst = inst.getChildInst(ir, 0); - if (cInst.m_op != IR::OpType::Call) - diag.reportBackendErr(inst.m_loc, "only functions accepted for alpha swizzle"); - return RecursiveTraceColor(ir, diag, cInst, true); - } else - diag.reportBackendErr(inst.m_loc, "only alpha extract may be performed with swizzle operation"); - break; - } - default: - diag.reportBackendErr(inst.m_loc, "invalid color op"); - } - - return TraceResult(); -} - -GX::TraceResult GX::RecursiveTraceAlpha(const IR& ir, Diagnostics& diag, const IR::Instruction& inst) { - switch (inst.m_op) { - case IR::OpType::Call: { - const std::string& name = inst.m_call.m_name; - bool normalize = false; - if (!name.compare("Texture") || (normalize = true && !name.compare("TextureN"))) { - if (inst.getChildCount() < 2) - diag.reportBackendErr(inst.m_loc, "Texture(map, texgen) requires 2 arguments"); - - const IR::Instruction& mapInst = inst.getChildInst(ir, 0); - const atVec4f& mapImm = mapInst.getImmVec(); - unsigned mapIdx = unsigned(mapImm.simd[0]); - - int foundStage = -1; - for (int i = m_alphaTraceStage + 1; i < int(m_tevCount); ++i) { - TEVStage& testStage = m_tevs[i]; - if (testStage.m_texMapIdx == mapIdx) { - foundStage = i; - break; - } - } - - if (foundStage >= 0) { - m_alphaTraceStage = foundStage; - TEVStage& stage = m_tevs[foundStage]; - stage.m_alpha[0] = CA_TEXA; - return TraceResult(&stage); - } - - TEVStage& newStage = addAlphaTEVStage(diag, inst.m_loc); - newStage.m_color[3] = CC_CPREV; - - newStage.m_texMapIdx = mapIdx; - newStage.m_alpha[0] = CA_TEXA; - - const IR::Instruction& tcgInst = inst.getChildInst(ir, 1); - newStage.m_texGenIdx = RecursiveTraceTexGen(ir, diag, tcgInst, IDENTITY, normalize, PTIDENTITY); - - return TraceResult(&newStage); - } else if (!name.compare("ColorReg")) { - const IR::Instruction& idxInst = inst.getChildInst(ir, 0); - unsigned idx = unsigned(idxInst.getImmVec().simd[0]); - m_aRegMask |= 1 << idx; - return TraceResult(TevAlphaArg(CA_A0 + idx)); - } else if (!name.compare("Lighting")) { - return TraceResult(CA_RASA); - } else - diag.reportBackendErr(inst.m_loc, "GX backend unable to interpret '%s'", name.c_str()); - break; - } - case IR::OpType::LoadImm: { - const atVec4f& vec = inst.m_loadImm.m_immVec; - if (vec.simd[0] == 0.f) - return TraceResult(CA_ZERO); - else if (vec.simd[0] == 1.f) - return TraceResult(TEV_KASEL_1); - unsigned idx = addKAlpha(diag, inst.m_loc, vec.simd[0]); - return TraceResult(TevKAlphaSel(TEV_KASEL_K0_A + idx)); - } - case IR::OpType::Arithmetic: { - ArithmeticOp op = inst.m_arithmetic.m_op; - const IR::Instruction& aInst = inst.getChildInst(ir, 0); - const IR::Instruction& bInst = inst.getChildInst(ir, 1); - TraceResult aTrace; - TraceResult bTrace; - if (aInst.m_op != IR::OpType::Arithmetic && bInst.m_op == IR::OpType::Arithmetic) { - bTrace = RecursiveTraceAlpha(ir, diag, bInst); - aTrace = RecursiveTraceAlpha(ir, diag, aInst); - } else { - aTrace = RecursiveTraceAlpha(ir, diag, aInst); - bTrace = RecursiveTraceAlpha(ir, diag, bInst); - } - if (aTrace.type == TraceResult::Type::TEVStage && bTrace.type == TraceResult::Type::TEVStage && - getStageIdx(aTrace.tevStage) > getStageIdx(bTrace.tevStage)) - std::swap(aTrace, bTrace); - - TevKAlphaSel newKAlpha = TEV_KASEL_1; - if (aTrace.type == TraceResult::Type::TEVKAlphaSel && bTrace.type == TraceResult::Type::TEVKAlphaSel) - diag.reportBackendErr(inst.m_loc, "unable to handle 2 KAlphas in one stage"); - else if (aTrace.type == TraceResult::Type::TEVKAlphaSel) { - newKAlpha = aTrace.tevKAlphaSel; - aTrace.type = TraceResult::Type::TEVAlphaArg; - aTrace.tevAlphaArg = CA_KONST; - } else if (bTrace.type == TraceResult::Type::TEVKAlphaSel) { - newKAlpha = bTrace.tevKAlphaSel; - bTrace.type = TraceResult::Type::TEVAlphaArg; - bTrace.tevAlphaArg = CA_KONST; - } - - switch (op) { - case ArithmeticOp::Add: { - if (aTrace.type == TraceResult::Type::TEVStage && bTrace.type == TraceResult::Type::TEVStage) { - TEVStage* a = aTrace.tevStage; - TEVStage* b = bTrace.tevStage; - if (b->m_prev != a) { - a->m_aRegOut = TEVLAZY; - b->m_alpha[3] = CA_LAZY; - if (a->m_lazyAOutIdx != -1) - b->m_lazyAInIdx = a->m_lazyAOutIdx; - else { - b->m_lazyAInIdx = m_aRegLazy; - a->m_lazyAOutIdx = m_aRegLazy++; - } - } else - b->m_alpha[3] = CA_APREV; - return TraceResult(b); - } else if (aTrace.type == TraceResult::Type::TEVStage && bTrace.type == TraceResult::Type::TEVAlphaArg) { - TEVStage* a = aTrace.tevStage; - if (a->m_alpha[3] != CA_ZERO) - diag.reportBackendErr(inst.m_loc, "unable to modify TEV stage for add combine"); - a->m_alpha[3] = bTrace.tevAlphaArg; - a->m_kAlpha = newKAlpha; - return TraceResult(a); - } else if (aTrace.type == TraceResult::Type::TEVAlphaArg && bTrace.type == TraceResult::Type::TEVStage) { - TEVStage* b = bTrace.tevStage; - if (b->m_alpha[3] != CA_ZERO) - diag.reportBackendErr(inst.m_loc, "unable to modify TEV stage for add combine"); - b->m_alpha[3] = aTrace.tevAlphaArg; - b->m_kAlpha = newKAlpha; - return TraceResult(b); - } else if (aTrace.type == TraceResult::Type::TEVAlphaArg && bTrace.type == TraceResult::Type::TEVAlphaArg) { - TEVStage& stage = addAlphaTEVStage(diag, inst.m_loc); - stage.m_alpha[0] = aTrace.tevAlphaArg; - stage.m_alpha[3] = bTrace.tevAlphaArg; - stage.m_kAlpha = newKAlpha; - return TraceResult(&stage); - } - break; - } - case ArithmeticOp::Subtract: { - if (aTrace.type == TraceResult::Type::TEVStage && bTrace.type == TraceResult::Type::TEVStage) { - TEVStage* a = aTrace.tevStage; - TEVStage* b = bTrace.tevStage; - if (b->m_aop != TEV_SUB) - diag.reportBackendErr(inst.m_loc, "unable to integrate alpha subtraction into stage chain"); - if (b->m_prev != a) { - a->m_aRegOut = TEVLAZY; - b->m_alpha[3] = CA_LAZY; - if (a->m_lazyAOutIdx != -1) - b->m_lazyAInIdx = a->m_lazyAOutIdx; - else { - b->m_lazyAInIdx = m_aRegLazy; - a->m_lazyAOutIdx = m_aRegLazy++; - } - } else - b->m_alpha[3] = CA_APREV; - return TraceResult(b); - } else if (aTrace.type == TraceResult::Type::TEVStage && bTrace.type == TraceResult::Type::TEVAlphaArg) { - TEVStage* a = aTrace.tevStage; - if (a->m_aop != TEV_SUB) - diag.reportBackendErr(inst.m_loc, "unable to integrate alpha subtraction into stage chain"); - if (a->m_alpha[3] != CA_ZERO) - diag.reportBackendErr(inst.m_loc, "unable to modify TEV stage for add combine"); - a->m_alpha[3] = bTrace.tevAlphaArg; - a->m_kAlpha = newKAlpha; - return TraceResult(a); - } else if (aTrace.type == TraceResult::Type::TEVAlphaArg && bTrace.type == TraceResult::Type::TEVAlphaArg) { - TEVStage& stage = addAlphaTEVStage(diag, inst.m_loc); - stage.m_alpha[0] = aTrace.tevAlphaArg; - stage.m_alpha[3] = bTrace.tevAlphaArg; - stage.m_kAlpha = newKAlpha; - stage.m_aop = TEV_SUB; - return TraceResult(&stage); - } - break; - } - case ArithmeticOp::Multiply: { - if (aTrace.type == TraceResult::Type::TEVStage && bTrace.type == TraceResult::Type::TEVStage) { - TEVStage* a = aTrace.tevStage; - TEVStage* b = bTrace.tevStage; - if (b->m_alpha[2] != CA_ZERO) - diag.reportBackendErr(inst.m_loc, "unable to modify TEV stage for multiply combine"); - if (b->m_prev != a) { - a->m_aRegOut = TEVLAZY; - b->m_alpha[2] = CA_LAZY; - b->m_lazyAInIdx = m_aRegLazy; - a->m_lazyAOutIdx = m_aRegLazy++; - } else - b->m_alpha[2] = CA_APREV; - b->m_alpha[1] = b->m_alpha[0]; - b->m_alpha[0] = CA_ZERO; - b->m_alpha[3] = CA_ZERO; - return TraceResult(b); - } else if (aTrace.type == TraceResult::Type::TEVAlphaArg && bTrace.type == TraceResult::Type::TEVAlphaArg) { - TEVStage& stage = addAlphaTEVStage(diag, inst.m_loc); - stage.m_color[3] = CC_CPREV; - stage.m_alpha[1] = aTrace.tevAlphaArg; - stage.m_alpha[2] = bTrace.tevAlphaArg; - stage.m_kAlpha = newKAlpha; - return TraceResult(&stage); - } else if (aTrace.type == TraceResult::Type::TEVStage && bTrace.type == TraceResult::Type::TEVAlphaArg) { - TEVStage* a = aTrace.tevStage; - if (a->m_alpha[1] != CA_ZERO) { - if (a->m_aRegOut != TEVPREV) - diag.reportBackendErr(inst.m_loc, "unable to modify TEV stage for multiply combine"); - TEVStage& stage = addAlphaTEVStage(diag, inst.m_loc); - stage.m_alpha[1] = CA_APREV; - stage.m_alpha[2] = bTrace.tevAlphaArg; - stage.m_kAlpha = newKAlpha; - return TraceResult(&stage); - } - a->m_alpha[1] = a->m_alpha[0]; - a->m_alpha[0] = CA_ZERO; - a->m_alpha[2] = bTrace.tevAlphaArg; - a->m_kAlpha = newKAlpha; - return TraceResult(a); - } else if (aTrace.type == TraceResult::Type::TEVAlphaArg && bTrace.type == TraceResult::Type::TEVStage) { - TEVStage* b = bTrace.tevStage; - if (b->m_alpha[1] != CA_ZERO) { - if (b->m_aRegOut != TEVPREV) - diag.reportBackendErr(inst.m_loc, "unable to modify TEV stage for multiply combine"); - TEVStage& stage = addAlphaTEVStage(diag, inst.m_loc); - stage.m_alpha[1] = aTrace.tevAlphaArg; - stage.m_alpha[2] = CA_APREV; - stage.m_kAlpha = newKAlpha; - return TraceResult(&stage); - } - b->m_alpha[1] = b->m_alpha[0]; - b->m_alpha[0] = CA_ZERO; - b->m_alpha[2] = bTrace.tevAlphaArg; - b->m_kAlpha = newKAlpha; - return TraceResult(b); - } - break; - } - default: - diag.reportBackendErr(inst.m_loc, "invalid arithmetic op"); - } - - diag.reportBackendErr(inst.m_loc, "unable to convert arithmetic to TEV stage"); - break; - } - case IR::OpType::Swizzle: { - if (inst.m_swizzle.m_idxs[0] == 3 && inst.m_swizzle.m_idxs[1] == 3 && inst.m_swizzle.m_idxs[2] == 3 && - inst.m_swizzle.m_idxs[3] == -1) { - const IR::Instruction& cInst = inst.getChildInst(ir, 0); - if (cInst.m_op != IR::OpType::Call) - diag.reportBackendErr(inst.m_loc, "only functions accepted for alpha swizzle"); - return RecursiveTraceAlpha(ir, diag, cInst); - } else - diag.reportBackendErr(inst.m_loc, "only alpha extract may be performed with swizzle operation"); - break; - } - default: - diag.reportBackendErr(inst.m_loc, "invalid alpha op"); - } - - return TraceResult(); -} - -void GX::reset(const IR& ir, Diagnostics& diag) { - diag.setBackend("GX"); - - m_tevCount = 0; - m_tcgCount = 0; - m_texMtxCount = 0; - m_kcolorCount = 0; - m_cRegMask = 0; - m_cRegLazy = 0; - m_aRegMask = 0; - m_aRegLazy = 0; - m_alphaTraceStage = -1; - - /* Final instruction is the root call by hecl convention */ - const IR::Instruction& rootCall = ir.m_instructions.back(); - if (!rootCall.m_call.m_name.compare("HECLOpaque")) { - m_blendSrc = BL_ONE; - m_blendDst = BL_ZERO; - } else if (!rootCall.m_call.m_name.compare("HECLAlpha")) { - m_blendSrc = BL_SRCALPHA; - m_blendDst = BL_INVSRCALPHA; - } else if (!rootCall.m_call.m_name.compare("HECLAdditive")) { - m_blendSrc = BL_SRCALPHA; - m_blendDst = BL_ONE; - } else { - diag.reportBackendErr(rootCall.m_loc, "GX backend doesn't handle '%s' root", rootCall.m_call.m_name.c_str()); - return; - } - - /* Follow Color Chain */ - const IR::Instruction& colorRoot = ir.m_instructions.at(rootCall.m_call.m_argInstIdxs.at(0)); - TraceResult result = RecursiveTraceColor(ir, diag, colorRoot); - switch (result.type) { - case TraceResult::Type::TEVColorArg: { - TEVStage& stage = addTEVStage(diag, colorRoot.m_loc); - stage.m_color[3] = result.tevColorArg; - break; - } - case TraceResult::Type::TEVKColorSel: { - TEVStage& stage = addTEVStage(diag, colorRoot.m_loc); - stage.m_color[3] = CC_KONST; - stage.m_kColor = result.tevKColorSel; - break; - } - default: - break; - } - - /* Follow Alpha Chain */ - if (rootCall.m_call.m_argInstIdxs.size() > 1) { - const IR::Instruction& alphaRoot = ir.m_instructions.at(rootCall.m_call.m_argInstIdxs.at(1)); - TraceResult result = RecursiveTraceAlpha(ir, diag, alphaRoot); - switch (result.type) { - case TraceResult::Type::TEVAlphaArg: { - TEVStage& stage = addAlphaTEVStage(diag, alphaRoot.m_loc); - stage.m_alpha[3] = result.tevAlphaArg; - break; - } - case TraceResult::Type::TEVKAlphaSel: { - TEVStage& stage = addAlphaTEVStage(diag, alphaRoot.m_loc); - stage.m_alpha[3] = CA_KONST; - stage.m_kAlpha = result.tevKAlphaSel; - break; - } - default: - break; - } - - /* Ensure Alpha reaches end of chain */ - if (m_alphaTraceStage >= 0) - for (unsigned i = m_alphaTraceStage + 1; i < m_tevCount; ++i) - m_tevs[i].m_alpha[3] = CA_APREV; - } - - /* Resolve lazy color/alpha regs */ - if (m_cRegLazy) { - for (int i = 0; i < int(m_tevCount); ++i) { - TEVStage& stage = m_tevs[i]; - if (stage.m_cRegOut == TEVLAZY) { - int picked = pickCLazy(diag, stage.m_loc, i); - stage.m_cRegOut = TevRegID(TEVREG0 + picked); - for (int j = i + 1; j < int(m_tevCount); ++j) { - TEVStage& nstage = m_tevs[j]; - if (nstage.m_lazyCInIdx == stage.m_lazyCOutIdx) - for (int c = 0; c < 4; ++c) - if (nstage.m_color[c] == CC_LAZY) - nstage.m_color[c] = TevColorArg(CC_C0 + picked * 2); - } - } - - if (stage.m_aRegOut == TEVLAZY) { - int picked = pickALazy(diag, stage.m_loc, i); - stage.m_aRegOut = TevRegID(TEVREG0 + picked); - for (int j = i + 1; j < int(m_tevCount); ++j) { - TEVStage& nstage = m_tevs[j]; - if (nstage.m_lazyAInIdx == stage.m_lazyAOutIdx) - for (int c = 0; c < 4; ++c) - if (nstage.m_alpha[c] == CA_LAZY) - nstage.m_alpha[c] = TevAlphaArg(CA_A0 + picked); - } - } - } - } -} - -} // namespace hecl::Backend diff --git a/hecl/lib/Backend/HLSL.cpp b/hecl/lib/Backend/HLSL.cpp deleted file mode 100644 index c75c92111..000000000 --- a/hecl/lib/Backend/HLSL.cpp +++ /dev/null @@ -1,359 +0,0 @@ -#include "hecl/Backend/HLSL.hpp" -#include "hecl/Runtime.hpp" -#include -#include -#include - -static logvisor::Module Log("hecl::Backend::HLSL"); - -namespace hecl::Backend { - -std::string HLSL::EmitTexGenSource2(TexGenSrc src, int uvIdx) const { - switch (src) { - case TexGenSrc::Position: - return "objPos.xy\n"; - case TexGenSrc::Normal: - return "objNorm.xy\n"; - case TexGenSrc::UV: - return hecl::Format("v.uvIn[%u]", uvIdx); - default: - break; - } - return std::string(); -} - -std::string HLSL::EmitTexGenSource4(TexGenSrc src, int uvIdx) const { - switch (src) { - case TexGenSrc::Position: - return "float4(objPos.xyz, 1.0)\n"; - case TexGenSrc::Normal: - return "float4(objNorm.xyz, 1.0)\n"; - case TexGenSrc::UV: - return hecl::Format("float4(v.uvIn[%u], 0.0, 1.0)", uvIdx); - default: - break; - } - return std::string(); -} - -std::string HLSL::GenerateVertInStruct(unsigned col, unsigned uv, unsigned w) const { - std::string retval = - "struct VertData\n" - "{\n" - " float3 posIn : POSITION;\n" - " float3 normIn : NORMAL;\n"; - - if (col) - retval += hecl::Format(" float4 colIn[%u] : COLOR;\n", col); - - if (uv) - retval += hecl::Format(" float2 uvIn[%u] : UV;\n", uv); - - if (w) - retval += hecl::Format(" float4 weightIn[%u] : WEIGHT;\n", w); - - return retval + "};\n"; -} - -std::string HLSL::GenerateVertToFragStruct(size_t extTexCount, bool reflectionCoords) const { - std::string retval = - "struct VertToFrag\n" - "{\n" - " float4 mvpPos : SV_Position;\n" - " float4 mvPos : POSITION;\n" - " float4 mvNorm : NORMAL;\n"; - - if (m_tcgs.size()) - retval += hecl::Format(" float2 tcgs[%u] : UV;\n", unsigned(m_tcgs.size())); - if (extTexCount) - retval += hecl::Format(" float2 extTcgs[%u] : EXTUV;\n", unsigned(extTexCount)); - - if (reflectionCoords) - retval += - " float2 reflectTcgs[2] : REFLECTUV;\n" - " float reflectAlpha : REFLECTALPHA;\n"; - - return retval + "};\n"; -} - -std::string HLSL::GenerateVertUniformStruct(unsigned skinSlots, bool reflectionCoords) const { - std::string retval; - if (skinSlots == 0) { - retval = - "cbuffer HECLVertUniform : register(b0)\n" - "{\n" - " float4x4 mv;\n" - " float4x4 mvInv;\n" - " float4x4 proj;\n" - "};\n"; - } else { - retval = hecl::Format( - "cbuffer HECLVertUniform : register(b0)\n" - "{\n" - " float4x4 objs[%u];\n" - " float4x4 objsInv[%u];\n" - " float4x4 mv;\n" - " float4x4 mvInv;\n" - " float4x4 proj;\n" - "};\n", - skinSlots, skinSlots); - } - retval += - "struct TCGMtx\n" - "{\n" - " float4x4 mtx;\n" - " float4x4 postMtx;\n" - "};\n" - "cbuffer HECLTCGMatrix : register(b1)\n" - "{\n" - " TCGMtx texMtxs[8];\n" - "};\n"; - - if (reflectionCoords) - retval += - "cbuffer HECLReflectMtx : register(b3)\n" - "{\n" - " float4x4 indMtx;\n" - " float4x4 reflectMtx;\n" - " float reflectAlpha;\n" - "};\n" - "\n"; - - return retval; -} - -std::string HLSL::GenerateAlphaTest() const { - return " if (colorOut.a < 0.25)\n" - " {\n" - " discard;\n" - " }\n"; -} - -std::string HLSL::GenerateReflectionExpr(ReflectionType type) const { - switch (type) { - case ReflectionType::None: - default: - return "float3(0.0, 0.0, 0.0)"; - case ReflectionType::Simple: - return "reflectionTex.Sample(reflectSamp, vtf.reflectTcgs[1]).rgb * vtf.reflectAlpha"; - case ReflectionType::Indirect: - return "reflectionTex.Sample(reflectSamp, (reflectionIndTex.Sample(samp, vtf.reflectTcgs[0]).ab - " - "float2(0.5, 0.5)) * float2(0.5, 0.5) + vtf.reflectTcgs[1]).rgb * vtf.reflectAlpha"; - } -} - -void HLSL::reset(const IR& ir, Diagnostics& diag) { - /* Common programmable interpretation */ - ProgrammableCommon::reset(ir, diag, "HLSL"); -} - -std::string HLSL::makeVert(unsigned col, unsigned uv, unsigned w, unsigned s, size_t extTexCount, - const TextureInfo* extTexs, ReflectionType reflectionType) const { - std::string retval = GenerateVertInStruct(col, uv, w) + "\n" + - GenerateVertToFragStruct(extTexCount, reflectionType != ReflectionType::None) + "\n" + - GenerateVertUniformStruct(s, reflectionType != ReflectionType::None) + "\n" + - "VertToFrag main(in VertData v)\n" - "{\n" - " VertToFrag vtf;\n"; - - if (s) { - /* skinned */ - retval += - " float4 objPos = float4(0.0,0.0,0.0,0.0);\n" - " float4 objNorm = float4(0.0,0.0,0.0,0.0);\n"; - for (size_t i = 0; i < s; ++i) - retval += hecl::Format( - " objPos += mul(objs[%" PRISize "], float4(v.posIn, 1.0)) * v.weightIn[%" PRISize "][%" PRISize - "];\n" - " objNorm += mul(objsInv[%" PRISize "], float4(v.normIn, 1.0)) * v.weightIn[%" PRISize "][%" PRISize "];\n", - i, i / 4, i % 4, i, i / 4, i % 4); - retval += - " objPos[3] = 1.0;\n" - " objNorm = float4(normalize(objNorm.xyz), 0.0);\n" - " vtf.mvPos = mul(mv, objPos);\n" - " vtf.mvNorm = float4(normalize(mul(mvInv, objNorm).xyz), 0.0);\n" - " vtf.mvpPos = mul(proj, vtf.mvPos);\n"; - } else { - /* non-skinned */ - retval += - " float4 objPos = float4(v.posIn, 1.0);\n" - " float4 objNorm = float4(v.normIn, 0.0);\n" - " vtf.mvPos = mul(mv, objPos);\n" - " vtf.mvNorm = mul(mvInv, objNorm);\n" - " vtf.mvpPos = mul(proj, vtf.mvPos);\n"; - } - - retval += " float4 tmpProj;\n"; - - int tcgIdx = 0; - for (const TexCoordGen& tcg : m_tcgs) { - if (tcg.m_mtx < 0) - retval += hecl::Format(" vtf.tcgs[%u] = %s;\n", tcgIdx, EmitTexGenSource2(tcg.m_src, tcg.m_uvIdx).c_str()); - else - retval += hecl::Format( - " tmpProj = mul(texMtxs[%u].postMtx, float4(%s(mul(texMtxs[%u].mtx, %s).xyz), 1.0));\n" - " vtf.tcgs[%u] = (tmpProj / tmpProj.w).xy;\n", - tcg.m_mtx, tcg.m_norm ? "normalize" : "", tcg.m_mtx, EmitTexGenSource4(tcg.m_src, tcg.m_uvIdx).c_str(), - tcgIdx); - ++tcgIdx; - } - - for (int i = 0; i < extTexCount; ++i) { - const TextureInfo& extTex = extTexs[i]; - if (extTex.mtxIdx < 0) - retval += hecl::Format(" vtf.extTcgs[%u] = %s;\n", i, EmitTexGenSource2(extTex.src, extTex.uvIdx).c_str()); - else - retval += hecl::Format( - " tmpProj = mul(texMtxs[%u].postMtx, float4(%s(mul(texMtxs[%u].mtx, %s).xyz), 1.0));\n" - " vtf.extTcgs[%u] = (tmpProj / tmpProj.w).xy;\n", - extTex.mtxIdx, extTex.normalize ? "normalize" : "", extTex.mtxIdx, - EmitTexGenSource4(extTex.src, extTex.uvIdx).c_str(), i); - } - - if (reflectionType != ReflectionType::None) - retval += - " vtf.reflectTcgs[0] = normalize(mul(indMtx, float4(v.posIn, 1.0)).xz) * float2(0.5, 0.5) + float2(0.5, " - "0.5);\n" - " vtf.reflectTcgs[1] = mul(reflectMtx, float4(v.posIn, 1.0)).xy;\n" - " vtf.reflectAlpha = reflectAlpha;\n"; - - return retval + - " return vtf;\n" - "}\n"; -} - -std::string HLSL::makeFrag(size_t blockCount, const char** blockNames, bool alphaTest, ReflectionType reflectionType, - BlendFactor srcFactor, BlendFactor dstFactor, const Function& lighting) const { - std::string lightingSrc; - if (!lighting.m_source.empty()) - lightingSrc = lighting.m_source; - else - lightingSrc = - "static const float4 colorReg0 = float4(1.0, 1.0, 1.0, 1.0);\n" - "static const float4 colorReg1 = float4(1.0, 1.0, 1.0, 1.0);\n" - "static const float4 colorReg2 = float4(1.0, 1.0, 1.0, 1.0);\n" - "static const float4 mulColor = float4(1.0, 1.0, 1.0, 1.0);\n" - "static const float4 addColor = float4(0.0, 0.0, 0.0, 0.0);\n"; - - std::string texMapDecl; - if (m_texMapEnd) - texMapDecl = hecl::Format("Texture2D texs[%u] : register(t0);\n", m_texMapEnd); - if (reflectionType == ReflectionType::Indirect) - texMapDecl += hecl::Format( - "Texture2D reflectionIndTex : register(t%u);\n" - "Texture2D reflectionTex : register(t%u);\n", - m_texMapEnd, m_texMapEnd + 1); - else if (reflectionType == ReflectionType::Simple) - texMapDecl += hecl::Format("Texture2D reflectionTex : register(t%u);\n", m_texMapEnd); - std::string retval = std::string("#define BLEND_SRC_") + BlendFactorToDefine(srcFactor, m_blendSrc) + "\n" + - "#define BLEND_DST_" + BlendFactorToDefine(dstFactor, m_blendDst) + "\n" + - "SamplerState samp : register(s0);\n" - "SamplerState clampSamp : register(s1);\n" - "SamplerState reflectSamp : register(s2);\n" + - GenerateVertToFragStruct(0, reflectionType != ReflectionType::None) + texMapDecl + "\n" + - lightingSrc + "\n" + (!alphaTest ? "\n[earlydepthstencil]\n" : "\n") + - "float4 main(in VertToFrag vtf) : SV_Target0\n{\n"; - - if (m_lighting) { - if (!lighting.m_entry.empty()) - retval += hecl::Format(" float4 lighting = %s(vtf.mvPos.xyz, normalize(vtf.mvNorm.xyz), vtf);\n", - lighting.m_entry.data()); - else - retval += " float4 lighting = float4(1.0,1.0,1.0,1.0);\n"; - } - - unsigned sampIdx = 0; - for (const TexSampling& sampling : m_texSamplings) - retval += hecl::Format(" float4 sampling%u = texs[%u].Sample(samp, vtf.tcgs[%u]);\n", sampIdx++, sampling.mapIdx, - sampling.tcgIdx); - - std::string reflectionExpr = GenerateReflectionExpr(reflectionType); - - retval += " float4 colorOut;\n"; - if (m_alphaExpr.size()) - retval += " colorOut = float4(" + m_colorExpr + " + " + reflectionExpr + ", " + m_alphaExpr + - ") * mulColor + addColor;\n"; - else - retval += " colorOut = float4(" + m_colorExpr + " + " + reflectionExpr + ", 1.0) * mulColor + addColor;\n"; - - return retval + (alphaTest ? GenerateAlphaTest() : "") + " return colorOut;\n}\n"; -} - -std::string HLSL::makeFrag(size_t blockCount, const char** blockNames, bool alphaTest, ReflectionType reflectionType, - BlendFactor srcFactor, BlendFactor dstFactor, const Function& lighting, const Function& post, - size_t extTexCount, const TextureInfo* extTexs, bool diffuseOnly) const { - std::string lightingSrc; - if (!lighting.m_source.empty()) - lightingSrc = lighting.m_source; - else - lightingSrc = - "static const float4 colorReg0 = float4(1.0, 1.0, 1.0, 1.0);\n" - "static const float4 colorReg1 = float4(1.0, 1.0, 1.0, 1.0);\n" - "static const float4 colorReg2 = float4(1.0, 1.0, 1.0, 1.0);\n" - "static const float4 mulColor = float4(1.0, 1.0, 1.0, 1.0);\n" - "static const float4 addColor = float4(0.0, 0.0, 0.0, 0.0);\n"; - - std::string postSrc; - if (!post.m_source.empty()) - postSrc = post.m_source; - - std::string postEntry; - if (!post.m_entry.empty()) - postEntry = post.m_entry; - - std::string texMapDecl; - if (m_texMapEnd) - texMapDecl = hecl::Format("Texture2D texs[%u] : register(t0);\n", m_texMapEnd); - if (reflectionType == ReflectionType::Indirect) - texMapDecl += hecl::Format( - "Texture2D reflectionIndTex : register(t%u);\n" - "Texture2D reflectionTex : register(t%u);\n", - m_texMapEnd, m_texMapEnd + 1); - else if (reflectionType == ReflectionType::Simple) - texMapDecl += hecl::Format("Texture2D reflectionTex : register(t%u);\n", m_texMapEnd); - - uint32_t extTexBits = 0; - for (int i = 0; i < extTexCount; ++i) { - const TextureInfo& extTex = extTexs[i]; - if (!(extTexBits & (1 << extTex.mapIdx))) { - texMapDecl += hecl::Format("Texture2D extTex%u : register(t%u);\n", extTex.mapIdx, extTex.mapIdx); - extTexBits |= (1 << extTex.mapIdx); - } - } - - std::string retval = std::string("#define BLEND_SRC_") + BlendFactorToDefine(srcFactor, m_blendSrc) + "\n" + - "#define BLEND_DST_" + BlendFactorToDefine(dstFactor, m_blendDst) + "\n" + - "SamplerState samp : register(s0);\n" - "SamplerState clampSamp : register(s1);\n" - "SamplerState reflectSamp : register(s2);\n" + - GenerateVertToFragStruct(extTexCount, reflectionType != ReflectionType::None) + texMapDecl + - "\n" + lightingSrc + "\n" + postSrc + (!alphaTest ? "\n[earlydepthstencil]\n" : "\n") + - "float4 main(in VertToFrag vtf) : SV_Target0\n{\n"; - - if (m_lighting) { - if (!lighting.m_entry.empty()) - retval += hecl::Format(" float4 lighting = %s(vtf.mvPos.xyz, normalize(vtf.mvNorm.xyz), vtf);\n", - lighting.m_entry.data()); - else - retval += " float4 lighting = float4(1.0,1.0,1.0,1.0);\n"; - } - - unsigned sampIdx = 0; - for (const TexSampling& sampling : m_texSamplings) - retval += hecl::Format(" float4 sampling%u = texs[%u].Sample(samp, vtf.tcgs[%u]);\n", sampIdx++, sampling.mapIdx, - sampling.tcgIdx); - - std::string reflectionExpr = GenerateReflectionExpr(reflectionType); - - retval += " float4 colorOut;\n"; - if (m_alphaExpr.size() && !diffuseOnly) - retval += " colorOut = " + postEntry + "(" + (postEntry.size() ? "vtf, " : "") + "float4(" + m_colorExpr + - " + " + reflectionExpr + ", " + m_alphaExpr + ")) * mulColor + addColor;\n"; - else - retval += " colorOut = " + postEntry + "(" + (postEntry.size() ? "vtf, " : "") + "float4(" + - (diffuseOnly ? m_diffuseColorExpr : m_colorExpr) + " + " + reflectionExpr + ", 1.0)) * mulColor + addColor;\n"; - - return retval + (alphaTest ? GenerateAlphaTest() : "") + " return colorOut;\n}\n"; -} - -} // namespace hecl::Backend diff --git a/hecl/lib/Backend/Metal.cpp b/hecl/lib/Backend/Metal.cpp deleted file mode 100644 index ad47e0f16..000000000 --- a/hecl/lib/Backend/Metal.cpp +++ /dev/null @@ -1,442 +0,0 @@ -#include "hecl/Backend/Metal.hpp" -#include -#include -#include - -static logvisor::Module Log("hecl::Backend::Metal"); - -namespace hecl::Backend { - -std::string Metal::EmitTexGenSource2(TexGenSrc src, int uvIdx) const { - switch (src) { - case TexGenSrc::Position: - return "objPos.xy\n"; - case TexGenSrc::Normal: - return "objNorm.xy\n"; - case TexGenSrc::UV: - return hecl::Format("v.uvIn%u", uvIdx); - default: - break; - } - return std::string(); -} - -std::string Metal::EmitTexGenSource4(TexGenSrc src, int uvIdx) const { - switch (src) { - case TexGenSrc::Position: - return "float4(objPos.xyz, 1.0)\n"; - case TexGenSrc::Normal: - return "float4(objNorm.xyz, 1.0)\n"; - case TexGenSrc::UV: - return hecl::Format("float4(v.uvIn%u, 0.0, 1.0)", uvIdx); - default: - break; - } - return std::string(); -} - -std::string Metal::GenerateVertInStruct(unsigned col, unsigned uv, unsigned w) const { - std::string retval = - "struct VertData\n" - "{\n" - " float3 posIn [[ attribute(0) ]];\n" - " float3 normIn [[ attribute(1) ]];\n"; - - unsigned idx = 2; - if (col) { - for (unsigned i = 0; i < col; ++i, ++idx) - retval += hecl::Format(" float4 colIn%u [[ attribute(%u) ]];\n", i, idx); - } - - if (uv) { - for (unsigned i = 0; i < uv; ++i, ++idx) - retval += hecl::Format(" float2 uvIn%u [[ attribute(%u) ]];\n", i, idx); - } - - if (w) { - for (unsigned i = 0; i < w; ++i, ++idx) - retval += hecl::Format(" float4 weightIn%u [[ attribute(%u) ]];\n", i, idx); - } - - return retval + "};\n"; -} - -std::string Metal::GenerateVertToFragStruct(size_t extTexCount, bool reflectionCoords) const { - std::string retval = - "struct VertToFrag\n" - "{\n" - " float4 mvpPos [[ position ]];\n" - " float4 mvPos;\n" - " float4 mvNorm;\n"; - - if (m_tcgs.size()) - for (size_t i = 0; i < m_tcgs.size(); ++i) - retval += hecl::Format(" float2 tcgs%" PRISize ";\n", i); - if (extTexCount) - for (size_t i = 0; i < extTexCount; ++i) - retval += hecl::Format(" float2 extTcgs%" PRISize ";\n", i); - - if (reflectionCoords) - retval += - " float2 reflectTcgs0;\n" - " float2 reflectTcgs1;\n" - " float reflectAlpha;\n"; - - return retval + "};\n"; -} - -std::string Metal::GenerateVertUniformStruct(unsigned skinSlots) const { - std::string retval; - if (skinSlots == 0) { - retval = - "struct HECLVertUniform\n" - "{\n" - " float4x4 mv;\n" - " float4x4 mvInv;\n" - " float4x4 proj;\n" - "};\n" - "struct TexMtxs {float4x4 mtx; float4x4 postMtx;};\n" - "struct ReflectTexMtxs {float4x4 indMtx; float4x4 reflectMtx; float reflectAlpha;};\n"; - } else { - retval = hecl::Format( - "struct HECLVertUniform\n" - "{\n" - " float4x4 objs[%u];\n" - " float4x4 objsInv[%u];\n" - " float4x4 mv;\n" - " float4x4 mvInv;\n" - " float4x4 proj;\n" - "};\n" - "struct TexMtxs {float4x4 mtx; float4x4 postMtx;};\n" - "struct ReflectTexMtxs {float4x4 indMtx; float4x4 reflectMtx; float reflectAlpha;};\n", - skinSlots, skinSlots); - } - return retval; -} - -std::string Metal::GenerateFragOutStruct() const { - return "struct FragOut\n" - "{\n" - " float4 color [[ color(0) ]];\n" - " //float depth [[ depth(less) ]];\n" - "};\n"; -} - -std::string Metal::GenerateAlphaTest() const { - return " if (out.color.a < 0.25)\n" - " {\n" - " discard_fragment();\n" - " }\n"; -} - -std::string Metal::GenerateReflectionExpr(ReflectionType type) const { - switch (type) { - case ReflectionType::None: - default: - return "float3(0.0, 0.0, 0.0)"; - case ReflectionType::Simple: - return "reflectionTex.sample(reflectSamp, vtf.reflectTcgs1).rgb * vtf.reflectAlpha"; - case ReflectionType::Indirect: - return "reflectionTex.sample(reflectSamp, (reflectionIndTex.sample(samp, vtf.reflectTcgs0).ab - " - "float2(0.5, 0.5)) * float2(0.5, 0.5) + vtf.reflectTcgs1).rgb * vtf.reflectAlpha"; - } -} - -void Metal::reset(const IR& ir, Diagnostics& diag) { - /* Common programmable interpretation */ - ProgrammableCommon::reset(ir, diag, "Metal"); -} - -std::string Metal::makeVert(unsigned col, unsigned uv, unsigned w, unsigned s, size_t extTexCount, - const TextureInfo* extTexs, ReflectionType reflectionType) const { - std::string tmStr = ",\nconstant TexMtxs* texMtxs [[ buffer(3) ]]"; - if (reflectionType != ReflectionType::None) - tmStr += ",\nconstant ReflectTexMtxs& reflectMtxs [[ buffer(5) ]]"; - std::string retval = "#include \nusing namespace metal;\n" + GenerateVertInStruct(col, uv, w) + "\n" + - GenerateVertToFragStruct(extTexCount, reflectionType != ReflectionType::None) + "\n" + - GenerateVertUniformStruct(s) + - "\nvertex VertToFrag vmain(VertData v [[ stage_in ]],\n" - " constant HECLVertUniform& vu [[ buffer(2) ]]" + - tmStr + - ")\n" - "{\n" - " VertToFrag vtf;\n"; - - if (s) { - /* skinned */ - retval += - " float4 objPos = float4(0.0,0.0,0.0,0.0);\n" - " float4 objNorm = float4(0.0,0.0,0.0,0.0);\n"; - for (size_t i = 0; i < s; ++i) - retval += hecl::Format( - " objPos += (vu.objs[%" PRISize "] * float4(v.posIn, 1.0)) * v.weightIn%" PRISize "[%" PRISize - "];\n" - " objNorm += (vu.objsInv[%" PRISize "] * float4(v.normIn, 1.0)) * v.weightIn%" PRISize "[%" PRISize "];\n", - i, i / 4, i % 4, i, i / 4, i % 4); - retval += - " objPos[3] = 1.0;\n" - " objNorm = float4(normalize(objNorm.xyz), 0.0);\n" - " vtf.mvPos = vu.mv * objPos;\n" - " vtf.mvNorm = float4(normalize((vu.mvInv * objNorm).xyz), 0.0);\n" - " vtf.mvpPos = vu.proj * vtf.mvPos;\n"; - } else { - /* non-skinned */ - retval += - " float4 objPos = float4(v.posIn, 1.0);\n" - " float4 objNorm = float4(v.normIn, 0.0);\n" - " vtf.mvPos = vu.mv * objPos;\n" - " vtf.mvNorm = vu.mvInv * objNorm;\n" - " vtf.mvpPos = vu.proj * vtf.mvPos;\n"; - } - - retval += " float4 tmpProj;\n"; - - int tcgIdx = 0; - for (const TexCoordGen& tcg : m_tcgs) { - if (tcg.m_mtx < 0) - retval += hecl::Format(" vtf.tcgs%u = %s;\n", tcgIdx, EmitTexGenSource2(tcg.m_src, tcg.m_uvIdx).c_str()); - else - retval += hecl::Format( - " tmpProj = texMtxs[%u].postMtx * float4(%s((texMtxs[%u].mtx * %s).xyz), 1.0);\n" - " vtf.tcgs%u = (tmpProj / tmpProj.w).xy;\n", - tcg.m_mtx, tcg.m_norm ? "normalize" : "", tcg.m_mtx, EmitTexGenSource4(tcg.m_src, tcg.m_uvIdx).c_str(), - tcgIdx); - ++tcgIdx; - } - - for (int i = 0; i < extTexCount; ++i) { - const TextureInfo& extTex = extTexs[i]; - if (extTex.mtxIdx < 0) - retval += hecl::Format(" vtf.extTcgs%u = %s;\n", i, EmitTexGenSource2(extTex.src, extTex.uvIdx).c_str()); - else - retval += hecl::Format( - " tmpProj = texMtxs[%u].postMtx * float4(%s((texMtxs[%u].mtx * %s).xyz), 1.0);\n" - " vtf.extTcgs%u = (tmpProj / tmpProj.w).xy;\n", - extTex.mtxIdx, extTex.normalize ? "normalize" : "", extTex.mtxIdx, - EmitTexGenSource4(extTex.src, extTex.uvIdx).c_str(), i); - } - - if (reflectionType != ReflectionType::None) - retval += - " vtf.reflectTcgs0 = normalize((reflectMtxs.indMtx * float4(v.posIn, 1.0)).xz) * float2(0.5, 0.5) + " - "float2(0.5, 0.5);\n" - " vtf.reflectTcgs1 = (reflectMtxs.reflectMtx * float4(v.posIn, 1.0)).xy;\n" - " vtf.reflectAlpha = reflectMtxs.reflectAlpha;\n"; - - return retval + " return vtf;\n}\n"; -} - -std::string Metal::makeFrag(size_t blockCount, const char** blockNames, bool alphaTest, ReflectionType reflectionType, - BlendFactor srcFactor, BlendFactor dstFactor, const Function& lighting) const { - std::string lightingSrc; - if (!lighting.m_source.empty()) - lightingSrc = lighting.m_source; - - std::string texMapDecl; - if (m_texMapEnd) - for (int i = 0; i < m_texMapEnd; ++i) - texMapDecl += hecl::Format(",\ntexture2d tex%u [[ texture(%u) ]]", i, i); - if (reflectionType == ReflectionType::Indirect) - texMapDecl += hecl::Format( - ",\ntexture2d reflectionIndTex [[ texture(%u) ]]\n" - ",\ntexture2d reflectionTex [[ texture(%u) ]]\n", - m_texMapEnd, m_texMapEnd + 1); - else if (reflectionType == ReflectionType::Simple) - texMapDecl += hecl::Format(",\ntexture2d reflectionTex [[ texture(%u) ]]\n", m_texMapEnd); - - std::string blockCall; - for (size_t i = 0; i < blockCount; ++i) { - texMapDecl += hecl::Format(",\nconstant %s& block%" PRISize " [[ buffer(%" PRISize ") ]]", blockNames[i], i, i + 4); - if (blockCall.size()) - blockCall += ", "; - blockCall += hecl::Format("block%" PRISize, i); - } - - std::string retval = - std::string("#include \nusing namespace metal;\n") + "#define BLEND_SRC_" + - BlendFactorToDefine(srcFactor, m_blendSrc) + "\n" + "#define BLEND_DST_" + - BlendFactorToDefine(dstFactor, m_blendDst) + "\n" + - GenerateVertToFragStruct(0, reflectionType != ReflectionType::None) + "\n" + GenerateFragOutStruct() + "\n" + - lightingSrc + "\n" + - "fragment FragOut fmain(VertToFrag vtf [[ stage_in ]],\n" - "sampler samp [[ sampler(0) ]], sampler clampSamp [[ sampler(1) ]], sampler reflectSamp [[ sampler(2) ]]" + - texMapDecl + - ")\n" - "{\n" - " FragOut out;\n"; - - if (!lighting.m_source.empty()) { - retval += - " float4 colorReg0 = block0.colorReg0;\n" - " float4 colorReg1 = block0.colorReg1;\n" - " float4 colorReg2 = block0.colorReg2;\n" - " float4 mulColor = block0.mulColor;\n" - " float4 addColor = block0.addColor;\n"; - } else { - retval += - " float4 colorReg0 = float4(1.0, 1.0, 1.0, 1.0);\n" - " float4 colorReg1 = float4(1.0, 1.0, 1.0, 1.0);\n" - " float4 colorReg2 = float4(1.0, 1.0, 1.0, 1.0);\n" - " float4 mulColor = float4(1.0, 1.0, 1.0, 1.0);\n" - " float4 addColor = float4(0.0, 0.0, 0.0, 0.0);\n"; - } - - if (m_lighting) { - if (!lighting.m_entry.empty()) - retval += hecl::Format(" float4 lighting = %s(%s, vtf.mvPos.xyz, normalize(vtf.mvNorm.xyz), vtf);\n", - lighting.m_entry.data(), blockCall.c_str()); - else - retval += " float4 lighting = float4(1.0,1.0,1.0,1.0);\n"; - } - - unsigned sampIdx = 0; - for (const TexSampling& sampling : m_texSamplings) - retval += hecl::Format(" float4 sampling%u = tex%u.sample(samp, vtf.tcgs%u);\n", sampIdx++, sampling.mapIdx, - sampling.tcgIdx); - - std::string reflectionExpr = GenerateReflectionExpr(reflectionType); - - if (m_alphaExpr.size()) - retval += " out.color = float4(" + m_colorExpr + " + " + reflectionExpr + ", " + m_alphaExpr + - ") * mulColor + addColor;\n"; - else - retval += " out.color = float4(" + m_colorExpr + " + " + reflectionExpr + ", 1.0) * mulColor + addColor;\n"; - - return retval + (alphaTest ? GenerateAlphaTest() : "") + - " return out;\n" - "}\n"; -} - -std::string Metal::makeFrag(size_t blockCount, const char** blockNames, bool alphaTest, ReflectionType reflectionType, - BlendFactor srcFactor, BlendFactor dstFactor, const Function& lighting, - const Function& post, size_t extTexCount, const TextureInfo* extTexs, - bool diffuseOnly) const { - std::string lightingSrc; - if (!lighting.m_source.empty()) - lightingSrc = lighting.m_source; - - std::string postSrc; - if (!post.m_source.empty()) - postSrc = post.m_source; - - std::string lightingEntry; - if (!lighting.m_entry.empty()) - lightingEntry = lighting.m_entry; - - std::string postEntry; - if (!post.m_entry.empty()) - postEntry = post.m_entry; - - int extTexBits = 0; - for (int i = 0; i < extTexCount; ++i) { - const TextureInfo& extTex = extTexs[i]; - extTexBits |= 1 << extTex.mapIdx; - } - - std::string texMapDecl; - if (m_texMapEnd) - for (int i = 0; i < m_texMapEnd; ++i) - if (!(extTexBits & (1 << i))) - texMapDecl += hecl::Format(",\ntexture2d tex%u [[ texture(%u) ]]", i, i); - if (reflectionType == ReflectionType::Indirect) - texMapDecl += hecl::Format( - ",\ntexture2d reflectionIndTex [[ texture(%u) ]]\n" - ",\ntexture2d reflectionTex [[ texture(%u) ]]\n", - m_texMapEnd, m_texMapEnd + 1); - else if (reflectionType == ReflectionType::Simple) - texMapDecl += hecl::Format(",\ntexture2d reflectionTex [[ texture(%u) ]]\n", m_texMapEnd); - - std::string extTexCall; - int extTexBits2 = 0; - for (int i = 0; i < extTexCount; ++i) { - const TextureInfo& extTex = extTexs[i]; - if (!(extTexBits2 & (1 << extTex.mapIdx))) { - if (extTexCall.size()) - extTexCall += ", "; - extTexCall += hecl::Format("tex%u", extTex.mapIdx); - texMapDecl += hecl::Format(",\ntexture2d tex%u [[ texture(%u) ]]", extTex.mapIdx, extTex.mapIdx); - extTexBits2 |= 1 << extTex.mapIdx; - } - } - - std::string blockCall; - for (size_t i = 0; i < blockCount; ++i) { - texMapDecl += hecl::Format(",\nconstant %s& block%" PRISize " [[ buffer(%" PRISize ") ]]", blockNames[i], i, i + 4); - if (blockCall.size()) - blockCall += ", "; - blockCall += hecl::Format("block%" PRISize, i); - } - - std::string retval = - std::string("#include \nusing namespace metal;\n") + "#define BLEND_SRC_" + - BlendFactorToDefine(srcFactor, m_blendSrc) + "\n" + "#define BLEND_DST_" + - BlendFactorToDefine(dstFactor, m_blendDst) + "\n" + - GenerateVertToFragStruct(extTexCount, reflectionType != ReflectionType::None) + "\n" + GenerateFragOutStruct() + - "\n" + lightingSrc + "\n" + postSrc + "\n" + - "fragment FragOut fmain(VertToFrag vtf [[ stage_in ]],\n" - "sampler samp [[ sampler(0) ]], sampler clampSamp [[ sampler(1) ]], sampler reflectSamp [[ sampler(2) ]]" + - texMapDecl + - ")\n" - "{\n" - " FragOut out;\n"; - - if (!lighting.m_source.empty()) { - retval += - " float4 colorReg0 = block0.colorReg0;\n" - " float4 colorReg1 = block0.colorReg1;\n" - " float4 colorReg2 = block0.colorReg2;\n" - " float4 mulColor = block0.mulColor;\n" - " float4 addColor = block0.addColor;\n"; - } else { - retval += - " float4 colorReg0 = float4(1.0, 1.0, 1.0, 1.0);\n" - " float4 colorReg1 = float4(1.0, 1.0, 1.0, 1.0);\n" - " float4 colorReg2 = float4(1.0, 1.0, 1.0, 1.0);\n" - " float4 mulColor = float4(1.0, 1.0, 1.0, 1.0);\n" - " float4 addColor = float4(0.0, 0.0, 0.0, 0.0);\n"; - } - - if (m_lighting) { - if (!lighting.m_entry.empty()) { - retval += - " float4 lighting = " + lightingEntry + "(" + blockCall + - ", vtf.mvPos.xyz, normalize(vtf.mvNorm.xyz), vtf" + - (!strncmp(lighting.m_entry.data(), "EXT", 3) ? (extTexCall.size() ? (", samp, clampSamp," + extTexCall) : "") - : "") + - ");\n"; - } else - retval += " float4 lighting = float4(1.0,1.0,1.0,1.0);\n"; - } - - unsigned sampIdx = 0; - for (const TexSampling& sampling : m_texSamplings) - retval += hecl::Format(" float4 sampling%u = tex%u.sample(samp, vtf.tcgs%u);\n", sampIdx++, sampling.mapIdx, - sampling.tcgIdx); - - std::string reflectionExpr = GenerateReflectionExpr(reflectionType); - - if (m_alphaExpr.size() && !diffuseOnly) { - retval += " out.color = " + postEntry + "(" + - (postEntry.size() ? ("vtf, " + (blockCall.size() ? (blockCall + ", ") : "") + - (!strncmp(post.m_entry.data(), "EXT", 3) - ? (extTexCall.size() ? ("samp, clampSamp," + extTexCall + ", ") : "") - : "")) - : "") + - "float4(" + m_colorExpr + " + " + reflectionExpr + ", " + m_alphaExpr + ")) * mulColor + addColor;\n"; - } else { - retval += " out.color = " + postEntry + "(" + - (postEntry.size() ? ("vtf, " + (blockCall.size() ? (blockCall + ", ") : "") + - (!strncmp(post.m_entry.data(), "EXT", 3) - ? (extTexCall.size() ? ("samp, clampSamp," + extTexCall + ", ") : "") - : "")) - : "") + - "float4(" + (diffuseOnly ? m_diffuseColorExpr : m_colorExpr) + " + " + reflectionExpr + - ", 1.0)) * mulColor + addColor;\n"; - } - - return retval + (alphaTest ? GenerateAlphaTest() : "") + - " return out;\n" - "}\n"; -} - -} // namespace hecl::Backend diff --git a/hecl/lib/Backend/ProgrammableCommon.cpp b/hecl/lib/Backend/ProgrammableCommon.cpp deleted file mode 100644 index 834b657e9..000000000 --- a/hecl/lib/Backend/ProgrammableCommon.cpp +++ /dev/null @@ -1,376 +0,0 @@ -#include "hecl/Backend/ProgrammableCommon.hpp" -#include - -namespace hecl::Backend { - -const char* ProgrammableCommon::BlendFactorToDefine(BlendFactor factor, BlendFactor defaultFactor) { - switch (factor) { - case BlendFactor::Zero: - return "ZERO"; - case BlendFactor::One: - return "ONE"; - case BlendFactor::SrcColor: - return "SRCCOLOR"; - case BlendFactor::InvSrcColor: - return "INVSRCCOLOR"; - case BlendFactor::DstColor: - return "DSTCOLOR"; - case BlendFactor::InvDstColor: - return "INVDSTCOLOR"; - case BlendFactor::SrcAlpha: - return "SRCALPHA"; - case BlendFactor::InvSrcAlpha: - return "INVSRCALPHA"; - case BlendFactor::DstAlpha: - return "DSTALPHA"; - case BlendFactor::InvDstAlpha: - return "INVDSTALPHA"; - case BlendFactor::SrcColor1: - return "SRCCOLOR1"; - case BlendFactor::InvSrcColor1: - return "INVSRCCOLOR1"; - default: - return BlendFactorToDefine(defaultFactor, BlendFactor::Zero); - } -} - -unsigned ProgrammableCommon::addTexCoordGen(TexGenSrc src, int uvIdx, int mtx, bool normalize) { - for (unsigned i = 0; i < m_tcgs.size(); ++i) { - TexCoordGen& tcg = m_tcgs[i]; - if (tcg.m_src == src && tcg.m_uvIdx == uvIdx && tcg.m_mtx == mtx && tcg.m_norm == normalize) - return i; - } - m_tcgs.emplace_back(); - TexCoordGen& newTcg = m_tcgs.back(); - newTcg.m_src = src; - newTcg.m_uvIdx = uvIdx; - newTcg.m_mtx = mtx; - newTcg.m_norm = normalize; - return m_tcgs.size() - 1; -} - -unsigned ProgrammableCommon::addTexSampling(unsigned mapIdx, unsigned tcgIdx) { - for (unsigned i = 0; i < m_texSamplings.size(); ++i) { - TexSampling& samp = m_texSamplings[i]; - if (samp.mapIdx == mapIdx && samp.tcgIdx == tcgIdx) - return i; - } - m_texSamplings.emplace_back(); - TexSampling& samp = m_texSamplings.back(); - samp.mapIdx = mapIdx; - samp.tcgIdx = tcgIdx; - if (m_texMapEnd < mapIdx + 1) - m_texMapEnd = mapIdx + 1; - return m_texSamplings.size() - 1; -} - -unsigned ProgrammableCommon::RecursiveTraceTexGen(const IR& ir, Diagnostics& diag, const IR::Instruction& inst, int mtx, - bool normalize) { - if (inst.m_op != IR::OpType::Call) - diag.reportBackendErr(inst.m_loc, "TexCoordGen resolution requires function"); - - const std::string& tcgName = inst.m_call.m_name; - if (!tcgName.compare("UV")) { - if (inst.getChildCount() < 1) - diag.reportBackendErr(inst.m_loc, "TexCoordGen UV(layerIdx) requires one argument"); - const IR::Instruction& idxInst = inst.getChildInst(ir, 0); - auto& idxImm = idxInst.getImmVec(); - return addTexCoordGen(TexGenSrc::UV, int(idxImm.simd[0]), mtx, normalize); - } else if (!tcgName.compare("Normal")) - return addTexCoordGen(TexGenSrc::Normal, -1, mtx, normalize); - else if (!tcgName.compare("View")) - return addTexCoordGen(TexGenSrc::Position, -1, mtx, normalize); - - /* Otherwise treat as game-specific function */ - const IR::Instruction& tcgSrcInst = inst.getChildInst(ir, 0); - unsigned idx = RecursiveTraceTexGen(ir, diag, tcgSrcInst, m_texMtxRefs.size(), normalize || tcgName.back() == 'N'); - TexCoordGen& tcg = m_tcgs[idx]; - m_texMtxRefs.push_back(idx); - tcg.m_gameFunction = tcgName; - tcg.m_gameArgs.clear(); - for (int i = 1; i < inst.getChildCount(); ++i) { - const IR::Instruction& ci = inst.getChildInst(ir, i); - tcg.m_gameArgs.push_back(ci.getImmVec()); - } - return idx; -} - -std::string ProgrammableCommon::RecursiveTraceDiffuseColor(const IR& ir, Diagnostics& diag, const IR::Instruction& inst, - bool toSwizzle, bool fallback) { - switch (inst.m_op) { - case IR::OpType::Call: { - const std::string& name = inst.m_call.m_name; - bool normalize = false; - if (!name.compare("TextureD") || - (fallback && !name.compare("Texture")) || - ((normalize = true) && !name.compare("TextureDN")) || - ((normalize = true) && fallback && !name.compare("TextureN"))) { - if (inst.getChildCount() < 2) - diag.reportBackendErr(inst.m_loc, "Texture(map, texgen) requires 2 arguments"); - - const IR::Instruction& mapInst = inst.getChildInst(ir, 0); - auto& mapImm = mapInst.getImmVec(); - unsigned mapIdx = unsigned(mapImm.simd[0]); - - const IR::Instruction& tcgInst = inst.getChildInst(ir, 1); - unsigned texGenIdx = RecursiveTraceTexGen(ir, diag, tcgInst, -1, normalize); - - return toSwizzle ? EmitSamplingUseRaw(addTexSampling(mapIdx, texGenIdx)) - : EmitSamplingUseRGB(addTexSampling(mapIdx, texGenIdx)); - } else - return std::string(); - } - case IR::OpType::LoadImm: { - const atVec4f& vec = inst.m_loadImm.m_immVec; - return EmitVec3(vec); - } - case IR::OpType::Arithmetic: { - const IR::Instruction& aInst = inst.getChildInst(ir, 0); - const IR::Instruction& bInst = inst.getChildInst(ir, 1); - std::string aTrace = RecursiveTraceDiffuseColor(ir, diag, aInst, false, fallback); - std::string bTrace = RecursiveTraceDiffuseColor(ir, diag, bInst, false, fallback); - return (!aTrace.empty()) ? aTrace : bTrace; - } - case IR::OpType::Swizzle: { - const IR::Instruction& aInst = inst.getChildInst(ir, 0); - std::string aTrace = RecursiveTraceDiffuseColor(ir, diag, aInst, true, fallback); - if (!aTrace.empty()) - return EmitSwizzle3(diag, inst.m_loc, aTrace, inst.m_swizzle.m_idxs); - return std::string(); - } - default: - diag.reportBackendErr(inst.m_loc, "invalid color op"); - } - - return std::string(); -} - -std::string ProgrammableCommon::RecursiveTraceColor(const IR& ir, Diagnostics& diag, const IR::Instruction& inst, - bool toSwizzle) { - switch (inst.m_op) { - case IR::OpType::Call: { - const std::string& name = inst.m_call.m_name; - bool normalize = false; - if (!name.compare("Texture") || !name.compare("TextureD") || - ((normalize = true) && !name.compare("TextureN")) || - ((normalize = true) && !name.compare("TextureDN"))) { - if (inst.getChildCount() < 2) - diag.reportBackendErr(inst.m_loc, "Texture(map, texgen) requires 2 arguments"); - - const IR::Instruction& mapInst = inst.getChildInst(ir, 0); - auto& mapImm = mapInst.getImmVec(); - unsigned mapIdx = unsigned(mapImm.simd[0]); - - const IR::Instruction& tcgInst = inst.getChildInst(ir, 1); - unsigned texGenIdx = RecursiveTraceTexGen(ir, diag, tcgInst, -1, normalize); - - return toSwizzle ? EmitSamplingUseRaw(addTexSampling(mapIdx, texGenIdx)) - : EmitSamplingUseRGB(addTexSampling(mapIdx, texGenIdx)); - } else if (!name.compare("ColorReg")) { - const IR::Instruction& idxInst = inst.getChildInst(ir, 0); - unsigned idx = unsigned(idxInst.getImmVec().simd[0]); - return toSwizzle ? EmitColorRegUseRaw(idx) : EmitColorRegUseRGB(idx); - } else if (!name.compare("Lighting")) { - m_lighting = true; - return toSwizzle ? EmitLightingRaw() : EmitLightingRGB(); - } else if (!name.compare("vec3")) { - if (inst.getChildCount() < 3) - diag.reportBackendErr(inst.m_loc, "vec3(r,g,b) requires 3 arguments"); - const IR::Instruction& aInst = inst.getChildInst(ir, 0); - const IR::Instruction& bInst = inst.getChildInst(ir, 1); - const IR::Instruction& cInst = inst.getChildInst(ir, 2); - return EmitVec3(RecursiveTraceAlpha(ir, diag, aInst, false), RecursiveTraceAlpha(ir, diag, bInst, false), - RecursiveTraceAlpha(ir, diag, cInst, false)); - } else - diag.reportBackendErr(inst.m_loc, "unable to interpret '%s'", name.c_str()); - break; - } - case IR::OpType::LoadImm: { - const atVec4f& vec = inst.m_loadImm.m_immVec; - return EmitVec3(vec); - } - case IR::OpType::Arithmetic: { - ArithmeticOp op = inst.m_arithmetic.m_op; - const IR::Instruction& aInst = inst.getChildInst(ir, 0); - const IR::Instruction& bInst = inst.getChildInst(ir, 1); - std::string aTrace = RecursiveTraceColor(ir, diag, aInst, false); - std::string bTrace = RecursiveTraceColor(ir, diag, bInst, false); - - switch (op) { - case ArithmeticOp::Add: { - return EmitAdd(aTrace, bTrace); - } - case ArithmeticOp::Subtract: { - return EmitSub(aTrace, bTrace); - } - case ArithmeticOp::Multiply: { - return EmitMult(aTrace, bTrace); - } - case ArithmeticOp::Divide: { - return EmitDiv(aTrace, bTrace); - } - default: - diag.reportBackendErr(inst.m_loc, "invalid arithmetic op"); - } - break; - } - case IR::OpType::Swizzle: { - const IR::Instruction& aInst = inst.getChildInst(ir, 0); - std::string aTrace = RecursiveTraceColor(ir, diag, aInst, true); - return EmitSwizzle3(diag, inst.m_loc, aTrace, inst.m_swizzle.m_idxs); - } - default: - diag.reportBackendErr(inst.m_loc, "invalid color op"); - } - - return std::string(); -} - -std::string ProgrammableCommon::RecursiveTraceAlpha(const IR& ir, Diagnostics& diag, const IR::Instruction& inst, - bool toSwizzle) { - switch (inst.m_op) { - case IR::OpType::Call: { - const std::string& name = inst.m_call.m_name; - bool normalize = false; - if (!name.compare("Texture") || !name.compare("TextureD") || - ((normalize = true) && !name.compare("TextureN")) || - ((normalize = true) && !name.compare("TextureDN"))) { - if (inst.getChildCount() < 2) - diag.reportBackendErr(inst.m_loc, "Texture(map, texgen) requires 2 arguments"); - - const IR::Instruction& mapInst = inst.getChildInst(ir, 0); - const atVec4f& mapImm = mapInst.getImmVec(); - unsigned mapIdx = unsigned(mapImm.simd[0]); - - const IR::Instruction& tcgInst = inst.getChildInst(ir, 1); - unsigned texGenIdx = RecursiveTraceTexGen(ir, diag, tcgInst, -1, normalize); - - return toSwizzle ? EmitSamplingUseRaw(addTexSampling(mapIdx, texGenIdx)) - : EmitSamplingUseAlpha(addTexSampling(mapIdx, texGenIdx)); - } else if (!name.compare("ColorReg")) { - const IR::Instruction& idxInst = inst.getChildInst(ir, 0); - unsigned idx = unsigned(idxInst.getImmVec().simd[0]); - return toSwizzle ? EmitColorRegUseRaw(idx) : EmitColorRegUseAlpha(idx); - } else if (!name.compare("Lighting")) { - m_lighting = true; - return toSwizzle ? EmitLightingRaw() : EmitLightingAlpha(); - } else - diag.reportBackendErr(inst.m_loc, "unable to interpret '%s'", name.c_str()); - break; - } - case IR::OpType::LoadImm: { - const atVec4f& vec = inst.m_loadImm.m_immVec; - return EmitVal(vec.simd[0]); - } - case IR::OpType::Arithmetic: { - ArithmeticOp op = inst.m_arithmetic.m_op; - const IR::Instruction& aInst = inst.getChildInst(ir, 0); - const IR::Instruction& bInst = inst.getChildInst(ir, 1); - std::string aTrace = RecursiveTraceAlpha(ir, diag, aInst, false); - std::string bTrace = RecursiveTraceAlpha(ir, diag, bInst, false); - - switch (op) { - case ArithmeticOp::Add: { - return EmitAdd(aTrace, bTrace); - } - case ArithmeticOp::Subtract: { - return EmitSub(aTrace, bTrace); - } - case ArithmeticOp::Multiply: { - return EmitMult(aTrace, bTrace); - } - case ArithmeticOp::Divide: { - return EmitDiv(aTrace, bTrace); - } - default: - diag.reportBackendErr(inst.m_loc, "invalid arithmetic op"); - } - break; - } - case IR::OpType::Swizzle: { - const IR::Instruction& aInst = inst.getChildInst(ir, 0); - std::string aTrace = RecursiveTraceAlpha(ir, diag, aInst, true); - return EmitSwizzle1(diag, inst.m_loc, aTrace, inst.m_swizzle.m_idxs); - } - default: - diag.reportBackendErr(inst.m_loc, "invalid alpha op"); - } - - return std::string(); -} - -void ProgrammableCommon::resetResourceAccumulators() { - m_texSamplings.clear(); - m_texMapEnd = 0; - m_tcgs.clear(); - m_texMtxRefs.clear(); -} - -void ProgrammableCommon::reset(const IR& ir, Diagnostics& diag, const char* backendName) { - m_lighting = false; - m_texSamplings.clear(); - m_texMapEnd = 0; - m_tcgs.clear(); - m_texMtxRefs.clear(); - m_colorExpr.clear(); - m_alphaExpr.clear(); - - diag.setBackend(backendName); - - /* Final instruction is the root call by hecl convention */ - const IR::Instruction& rootCall = ir.m_instructions.back(); - if (!rootCall.m_call.m_name.compare("HECLOpaque")) { - m_blendSrc = BlendFactor::One; - m_blendDst = BlendFactor::Zero; - } else if (!rootCall.m_call.m_name.compare("HECLAlpha")) { - m_blendSrc = BlendFactor::SrcAlpha; - m_blendDst = BlendFactor::InvSrcAlpha; - } else if (!rootCall.m_call.m_name.compare("HECLAdditive")) { - m_blendSrc = BlendFactor::SrcAlpha; - m_blendDst = BlendFactor::One; - } else { - diag.reportBackendErr(rootCall.m_loc, "%s backend doesn't handle '%s' root", backendName, - rootCall.m_call.m_name.c_str()); - return; - } - - /* Follow Color Chain */ - const IR::Instruction& colorRoot = ir.m_instructions.at(rootCall.m_call.m_argInstIdxs.at(0)); - m_diffuseColorExpr = RecursiveTraceDiffuseColor(ir, diag, colorRoot, false, false); - resetResourceAccumulators(); - if (m_diffuseColorExpr.empty()) { - m_diffuseColorExpr = RecursiveTraceDiffuseColor(ir, diag, colorRoot, false, true); - resetResourceAccumulators(); - } - m_colorExpr = RecursiveTraceColor(ir, diag, colorRoot, false); - - /* Follow Alpha Chain */ - if (rootCall.m_call.m_argInstIdxs.size() > 1) { - const IR::Instruction& alphaRoot = ir.m_instructions.at(rootCall.m_call.m_argInstIdxs.at(1)); - m_alphaExpr = RecursiveTraceAlpha(ir, diag, alphaRoot, false); - } -} - -static const char SWIZZLE_CHARS[] = "rgba"; - -std::string ProgrammableCommon::EmitSwizzle3(Diagnostics& diag, const SourceLocation& loc, const std::string& a, - const atInt8 swiz[4]) const { - std::string retval = a + '.'; - for (int i = 0; i < 3; ++i) { - if (swiz[i] < 0 || swiz[i] > 3) - diag.reportBackendErr(loc, "unable to use swizzle as RGB value"); - retval += SWIZZLE_CHARS[swiz[i]]; - } - return retval; -} - -std::string ProgrammableCommon::EmitSwizzle1(Diagnostics& diag, const SourceLocation& loc, const std::string& a, - const atInt8 swiz[4]) const { - std::string retval = a + '.'; - if (swiz[0] < 0 || swiz[0] > 3) - diag.reportBackendErr(loc, "unable to use swizzle as Alpha value"); - retval += SWIZZLE_CHARS[swiz[0]]; - return retval; -} - -} // namespace hecl::Backend diff --git a/hecl/lib/Blender/Connection.cpp b/hecl/lib/Blender/Connection.cpp index fb02f8bc4..8a2270f4d 100644 --- a/hecl/lib/Blender/Connection.cpp +++ b/hecl/lib/Blender/Connection.cpp @@ -275,7 +275,7 @@ Connection::Connection(int verbosityLevel) { SECURITY_ATTRIBUTES sattrs = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE}; HANDLE consoleOutReadTmp, consoleOutWrite, consoleErrWrite, consoleOutRead; - if (!CreatePipe(&consoleOutReadTmp, &consoleOutWrite, &sattrs, 0)) + if (!CreatePipe(&consoleOutReadTmp, &consoleOutWrite, &sattrs, 1024)) BlenderLog.report(logvisor::Fatal, "Error with CreatePipe"); if (!DuplicateHandle(GetCurrentProcess(), consoleOutWrite, GetCurrentProcess(), &consoleErrWrite, 0, TRUE, @@ -362,7 +362,7 @@ Connection::Connection(int verbosityLevel) { m_consoleThreadRunning = true; m_consoleThread = std::thread([=]() { - CHAR lpBuffer[256]; + CHAR lpBuffer[1024]; DWORD nBytesRead; DWORD nCharsWritten; @@ -482,6 +482,9 @@ Connection::Connection(int verbosityLevel) { DEFAULT_BLENDER_BIN); else BlenderLog.report(logvisor::Fatal, _SYS_STR("Unable to find blender at '%s'"), DEFAULT_BLENDER_BIN); + } else if (!strcmp(lineBuf, "NOT280")) { + _closePipe(); + BlenderLog.report(logvisor::Fatal, _SYS_STR("Installed blender version must be >= 2.80")); } else if (!strcmp(lineBuf, "NOADDON")) { _closePipe(); if (blenderAddonPath != _SYS_STR("SKIPINSTALL")) diff --git a/hecl/test/CMakeLists.txt b/hecl/test/CMakeLists.txt deleted file mode 100644 index bd6f78208..000000000 --- a/hecl/test/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -add_executable(heclTest WIN32 main.cpp) -target_link_libraries(heclTest - ${HECL_APPLICATION_REPS_TARGETS_LIST} - hecl-full hecl-blender-addon - athena-core athena-libyaml xxhash logvisor boo - ${ZLIB_LIBRARIES} lzokay ${BOO_SYS_LIBS}) -if(COMMAND add_sanitizers) - add_sanitizers(heclTest) -endif() diff --git a/hecl/test/main.cpp b/hecl/test/main.cpp deleted file mode 100644 index eb69e977d..000000000 --- a/hecl/test/main.cpp +++ /dev/null @@ -1,282 +0,0 @@ -#include -#include "logvisor/logvisor.hpp" -#include "hecl/Console.hpp" -#include "hecl/CVarManager.hpp" -#include "athena/MemoryWriter.hpp" -#include "hecl/Runtime.hpp" -#include "hecl/Backend/Backend.hpp" -#include "hecl/HMDLMeta.hpp" -#include "hecl/Pipeline.hpp" -#include -#include -#include -#include - -using namespace std::literals; - -struct HECLWindowCallback : boo::IWindowCallback { - bool m_sizeDirty = false; - boo::SWindowRect m_latestSize; - virtual ~HECLWindowCallback(); - void resized(const boo::SWindowRect& rect, bool /*sync*/) { - m_sizeDirty = true; - m_latestSize = rect; - } - - bool m_destroyed = false; - void destroyed() { m_destroyed = true; } - - void charKeyDown(unsigned long charCode, boo::EModifierKey mods, bool isRepeat) { - hecl::Console::instance()->handleCharCode(charCode, mods, isRepeat); - } - void specialKeyDown(boo::ESpecialKey key, boo::EModifierKey mods, bool isRepeat) { - hecl::Console::instance()->handleSpecialKeyDown(key, mods, isRepeat); - } - void specialKeyUp(boo::ESpecialKey key, boo::EModifierKey mods) { - hecl::Console::instance()->hecl::Console::handleSpecialKeyUp(key, mods); - } -}; - -HECLWindowCallback::~HECLWindowCallback() {} - -struct HECLApplicationCallback : boo::IApplicationCallback { - HECLWindowCallback m_windowCb; - hecl::Runtime::FileStoreManager m_fileStoreMgr; - hecl::CVarManager m_cvarManager; - hecl::Console m_console; - std::shared_ptr m_mainWindow; - bool m_running = true; - - HECLApplicationCallback() - : m_fileStoreMgr(_SYS_STR("heclTest")), m_cvarManager(m_fileStoreMgr), m_console(&m_cvarManager) { - m_console.registerCommand( - "quit"sv, "Quits application"sv, "", - std::bind(&HECLApplicationCallback::quit, this, std::placeholders::_1, std::placeholders::_2)); - } - - virtual ~HECLApplicationCallback(); - - int appMain(boo::IApplication* app) { - hecl::VerbosityLevel = 2; - - /* Setup boo window */ - m_mainWindow = app->newWindow(_SYS_STR("HECL Test")); - m_mainWindow->setCallback(&m_windowCb); - - boo::ObjToken renderTex; - boo::ObjToken vubo; - boo::ObjToken pipeline, pipeline2; - boo::ObjToken binding, binding2; - - struct VertexUBO { - float modelview[4][4] = {}; - float modelviewInv[4][4] = {}; - float projection[4][4] = {}; - VertexUBO() { - modelview[0][0] = 1.0; - modelview[1][1] = 1.0; - modelview[2][2] = 1.0; - modelview[3][3] = 1.0; - modelviewInv[0][0] = 1.0; - modelviewInv[1][1] = 1.0; - modelviewInv[2][2] = 1.0; - modelviewInv[3][3] = 1.0; - projection[0][0] = 1.0; - projection[1][1] = 1.0; - projection[2][2] = 1.0; - projection[3][3] = 1.0; - } - } vuboData; - - /* Make ramp texture */ - using Pixel = uint8_t[4]; - static Pixel tex[256][256]; - for (int i = 0; i < 256; ++i) - for (int j = 0; j < 256; ++j) { - tex[i][j][0] = uint8_t(i); - tex[i][j][1] = uint8_t(j); - tex[i][j][2] = 0; - tex[i][j][3] = 0xff; - } - - boo::IGraphicsDataFactory* gfxF = m_mainWindow->getMainContextDataFactory(); - if (gfxF->platform() == boo::IGraphicsDataFactory::Platform::Vulkan) - vuboData.modelview[1][1] = -1.f; - - /* Pipeline converter */ - std::unique_ptr conv = hecl::NewPipelineConverter(gfxF); - - /* Compile HECL shader */ - static std::string testShader = "HECLOpaque(Texture(0, UV(0)))"; - // static std::string testShader = "HECLOpaque(vec3(1.0,1.0,1.0),1.0)"; - hecl::Backend::ShaderTag testShaderTag(testShader, 0, 1, 0, 0, boo::Primitive::TriStrips, - hecl::Backend::ReflectionType::None, false, false, false, false); - hecl::Frontend::Frontend FE; - hecl::Frontend::IR ir = FE.compileSource(testShader, "booTest"); - hecl::HECLIR irObj(ir, testShaderTag, 0); - - gfxF->commitTransaction([&](boo::IGraphicsDataFactory::Context& ctx) { - pipeline = conv->convert(ctx, irObj); - pipeline2 = conv->convert(ctx, Shader_test{}); - - boo::SWindowRect mainWindowRect = m_mainWindow->getWindowFrame(); - renderTex = ctx.newRenderTexture(size_t(mainWindowRect.size[0]), size_t(mainWindowRect.size[1]), - boo::TextureClampMode::Repeat, 1, 0); - - /* Generate meta structure (usually statically serialized) */ - hecl::HMDLMeta testMeta; - testMeta.topology = hecl::HMDLTopology::TriStrips; - testMeta.vertStride = 32; - testMeta.vertCount = 4; - testMeta.indexCount = 4; - testMeta.colorCount = 0; - testMeta.uvCount = 1; - testMeta.weightCount = 0; - testMeta.bankCount = 0; - - /* Binary form of meta structure */ - atUint8 testMetaBuf[HECL_HMDL_META_SZ]; - athena::io::MemoryWriter testMetaWriter(testMetaBuf, HECL_HMDL_META_SZ); - testMeta.write(testMetaWriter); - - /* Make Tri-strip VBO */ - struct Vert { - float pos[3]; - float norm[3]; - float uv[2]; - }; - static const Vert quad[4] = {{{0.5, 0.5}, {}, {1.0, 1.0}}, - {{-0.5, 0.5}, {}, {0.0, 1.0}}, - {{0.5, -0.5}, {}, {1.0, 0.0}}, - {{-0.5, -0.5}, {}, {0.0, 0.0}}}; - - /* Now simple IBO */ - static const uint32_t ibo[4] = {0, 1, 2, 3}; - - /* Construct quad mesh against boo factory */ - hecl::Runtime::HMDLData testData(ctx, testMetaBuf, quad, ibo); - - boo::ObjToken texture = ctx.newStaticTexture(256, 256, 1, boo::TextureFormat::RGBA8, - boo::TextureClampMode::Repeat, tex, 256 * 256 * 4) - .get(); - - /* Make vertex uniform buffer */ - vubo = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(VertexUBO), 1).get(); - - /* Assemble data binding */ - binding = testData.newShaderDataBindng(ctx, pipeline, 1, &vubo, nullptr, 1, &texture); - binding2 = testData.newShaderDataBindng(ctx, pipeline2, 1, &vubo, nullptr, 1, &texture); - return true; - } BooTrace); - - m_mainWindow->showWindow(); - m_windowCb.m_latestSize = m_mainWindow->getWindowFrame(); - boo::IGraphicsCommandQueue* gfxQ = m_mainWindow->getCommandQueue(); - - size_t frameIdx = 0; - while (m_running) { - m_mainWindow->waitForRetrace(); - - if (m_windowCb.m_destroyed) { - m_running = false; - break; - } - - if (m_windowCb.m_sizeDirty) { - gfxQ->resizeRenderTexture(renderTex, size_t(m_windowCb.m_latestSize.size[0]), - size_t(m_windowCb.m_latestSize.size[1])); - m_windowCb.m_sizeDirty = false; - } - - m_console.proc(); - - gfxQ->setRenderTarget(renderTex); - boo::SWindowRect r = m_windowCb.m_latestSize; - r.location[0] = 0; - r.location[1] = 0; - gfxQ->setViewport(r); - gfxQ->setScissor(r); - float rgba[] = {sinf(frameIdx / 60.0f), cosf(frameIdx / 60.0f), 0.0f, 1.0f}; - gfxQ->setClearColor(rgba); - gfxQ->clearTarget(); - - vuboData.modelview[3][0] = sinf(frameIdx / 60.0f) * 0.5f; - vuboData.modelview[3][1] = cosf(frameIdx / 60.0f) * 0.5f; - vubo.cast()->load(&vuboData, sizeof(vuboData)); - - gfxQ->setShaderDataBinding(binding2); - gfxQ->drawIndexed(0, 4); - gfxQ->resolveDisplay(renderTex); - m_console.draw(gfxQ); - gfxQ->execute(); - - ++frameIdx; - } - - m_cvarManager.serialize(); - gfxQ->stopRenderer(); - return 0; - } - void appQuitting(boo::IApplication* /*app*/) { m_running = false; } - - void quit(hecl::Console* /*con*/, const std::vector& /*args*/) { m_running = false; } -}; - -void AthenaExcHandler(athena::error::Level level, const char* file, const char* /*function*/, int line, const char* fmt, - ...) { - static logvisor::Module Log("heclTest::AthenaExcHandler"); - va_list ap; - va_start(ap, fmt); - Log.reportSource(logvisor::Level(level), file, uint32_t(line), fmt, ap); - va_end(ap); -} - -#if !WINDOWS_STORE -#if _WIN32 -int wmain(int argc, const boo::SystemChar** argv) -#else -int main(int argc, const boo::SystemChar** argv) -#endif -{ - atSetExceptionHandler(AthenaExcHandler); - logvisor::RegisterStandardExceptions(); - logvisor::RegisterConsoleLogger(); - HECLApplicationCallback appCb; - int ret = boo::ApplicationRun(boo::IApplication::EPlatformType::Auto, appCb, _SYS_STR("heclTest"), - _SYS_STR("HECL Test"), argc, argv); - printf("IM DYING!!\n"); - return ret; -} -#else -using namespace Windows::ApplicationModel::Core; - -[Platform::MTAThread] int WINAPIV main(Platform::Array ^ params) { - logvisor::RegisterStandardExceptions(); - logvisor::RegisterConsoleLogger(); - HECLApplicationCallback appCb; - boo::ViewProvider ^ viewProvider = ref new boo::ViewProvider(appCb, _SYS_STR("heclTest"), _SYS_STR("HECL Test"), - _SYS_STR("heclTest"), params, false); - CoreApplication::Run(viewProvider); - return 0; -} -#endif - -#if _WIN32 && !WINDOWS_STORE -int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR lpCmdLine, int) { - int argc = 0; - const boo::SystemChar** argv; - if (lpCmdLine[0]) - argv = (const wchar_t**)(CommandLineToArgvW(lpCmdLine, &argc)); - static boo::SystemChar selfPath[1024]; - GetModuleFileNameW(nullptr, selfPath, 1024); - static const boo::SystemChar* booArgv[32] = {}; - booArgv[0] = selfPath; - for (int i = 0; i < argc; ++i) - booArgv[i + 1] = argv[i]; - - logvisor::CreateWin32Console(); - return wmain(argc + 1, booArgv); -} -#endif - -HECLApplicationCallback::~HECLApplicationCallback() {} diff --git a/hecl/test/test.shader b/hecl/test/test.shader deleted file mode 100644 index 224d1bffd..000000000 --- a/hecl/test/test.shader +++ /dev/null @@ -1,93 +0,0 @@ -#shader test - -#culling none -#attribute position3 -#attribute normal3 -#attribute uv2 - -#vertex glsl -layout(location=0) in vec3 in_pos; -layout(location=1) in vec3 in_norm; -layout(location=2) in vec2 in_uv; -SBINDING(0) out vec2 out_uv; -void main() -{ - gl_Position = vec4(in_pos, 1.0); - out_uv = in_uv; -} - -#fragment glsl -precision highp float; -TBINDING0 uniform sampler2D texs[1]; -layout(location=0) out vec4 out_frag; -SBINDING(0) in vec2 out_uv; -void main() -{ - out_frag = texture(texs[0], out_uv); -} - -#vertex hlsl -struct VertData -{ - float3 in_pos : POSITION; - float3 in_norm : NORMAL; - float2 in_uv : UV; -}; -struct VertToFrag -{ - float4 position : SV_Position; - float2 out_uv : UV; -}; -VertToFrag main(in VertData v) -{ - VertToFrag ret; - ret.position = float4(v.in_pos, 1.0); - ret.out_uv = v.in_uv; - return ret; -} - -#fragment hlsl -struct VertToFrag -{ - float4 position : SV_Position; - float2 out_uv : UV; -}; -Texture2D texs : register(t0); -SamplerState samp : register(s0); -float4 main(in VertToFrag vtf) : SV_Target0 -{ - return texs.Sample(samp, vtf.out_uv); -} - -#vertex metal -struct VertData -{ - float3 in_pos [[ attribute(0) ]]; - float3 in_norm [[ attribute(1) ]]; - float2 in_uv [[ attribute(2) ]]; -}; -struct VertToFrag -{ - float4 position [[ position ]]; - float2 out_uv; -}; -vertex VertToFrag vmain(VertData v [[ stage_in ]]) -{ - VertToFrag ret; - ret.position = float4(v.in_pos, 1.0); - ret.out_uv = v.in_uv; - return ret; -} - -#fragment metal -struct VertToFrag -{ - float4 position [[ position ]]; - float2 out_uv; -}; -fragment float4 fmain(VertToFrag vtf [[ stage_in ]], - sampler samp [[ sampler(0) ]], - texture2d tex [[ texture(0) ]]) -{ - return tex.sample(samp, vtf.out_uv); -}