mirror of https://github.com/AxioDL/metaforce.git
Windows fixes for refactor
This commit is contained in:
parent
92e2c03a01
commit
f596cbff83
|
@ -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)
|
||||
|
|
|
@ -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'})
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 3ad748f28b5377027c900ded38eeccdfeb7fe7f6
|
||||
Subproject commit b340a8a42ecf10560891eab65d8c59a6f2640ccc
|
|
@ -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
|
|
@ -1,703 +0,0 @@
|
|||
#include "hecl/Backend/GX.hpp"
|
||||
|
||||
namespace hecl::Backend {
|
||||
|
||||
template <>
|
||||
void GX::Color::Enumerate<athena::io::DNA<athena::Big>::Read>(typename Read::StreamT& reader) {
|
||||
reader.readUBytesToBuf(&num, 4);
|
||||
}
|
||||
template <>
|
||||
void GX::Color::Enumerate<athena::io::DNA<athena::Big>::Write>(typename Write::StreamT& writer) {
|
||||
writer.writeUBytes(reinterpret_cast<const atUint8*>(&num), 4);
|
||||
}
|
||||
template <>
|
||||
void GX::Color::Enumerate<athena::io::DNA<athena::Big>::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
|
|
@ -1,359 +0,0 @@
|
|||
#include "hecl/Backend/HLSL.hpp"
|
||||
#include "hecl/Runtime.hpp"
|
||||
#include <athena/MemoryReader.hpp>
|
||||
#include <athena/MemoryWriter.hpp>
|
||||
#include <boo/graphicsdev/D3D.hpp>
|
||||
|
||||
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
|
|
@ -1,442 +0,0 @@
|
|||
#include "hecl/Backend/Metal.hpp"
|
||||
#include <athena/MemoryReader.hpp>
|
||||
#include <athena/MemoryWriter.hpp>
|
||||
#include <boo/graphicsdev/Metal.hpp>
|
||||
|
||||
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 <metal_stdlib>\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<float> tex%u [[ texture(%u) ]]", i, i);
|
||||
if (reflectionType == ReflectionType::Indirect)
|
||||
texMapDecl += hecl::Format(
|
||||
",\ntexture2d<float> reflectionIndTex [[ texture(%u) ]]\n"
|
||||
",\ntexture2d<float> reflectionTex [[ texture(%u) ]]\n",
|
||||
m_texMapEnd, m_texMapEnd + 1);
|
||||
else if (reflectionType == ReflectionType::Simple)
|
||||
texMapDecl += hecl::Format(",\ntexture2d<float> 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 <metal_stdlib>\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<float> tex%u [[ texture(%u) ]]", i, i);
|
||||
if (reflectionType == ReflectionType::Indirect)
|
||||
texMapDecl += hecl::Format(
|
||||
",\ntexture2d<float> reflectionIndTex [[ texture(%u) ]]\n"
|
||||
",\ntexture2d<float> reflectionTex [[ texture(%u) ]]\n",
|
||||
m_texMapEnd, m_texMapEnd + 1);
|
||||
else if (reflectionType == ReflectionType::Simple)
|
||||
texMapDecl += hecl::Format(",\ntexture2d<float> 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<float> 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 <metal_stdlib>\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
|
|
@ -1,376 +0,0 @@
|
|||
#include "hecl/Backend/ProgrammableCommon.hpp"
|
||||
#include <map>
|
||||
|
||||
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
|
|
@ -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"))
|
||||
|
|
|
@ -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()
|
|
@ -1,282 +0,0 @@
|
|||
#include <boo/boo.hpp>
|
||||
#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 <cmath>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
|
||||
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<boo::IWindow> 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<boo::ITextureR> renderTex;
|
||||
boo::ObjToken<boo::IGraphicsBuffer> vubo;
|
||||
boo::ObjToken<boo::IShaderPipeline> pipeline, pipeline2;
|
||||
boo::ObjToken<boo::IShaderDataBinding> 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<hecl::PipelineConverterBase> 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<boo::ITexture> 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<boo::IGraphicsBufferD>()->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<std::string>& /*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<Platform::String ^> ^ 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() {}
|
|
@ -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<float> tex [[ texture(0) ]])
|
||||
{
|
||||
return tex.sample(samp, vtf.out_uv);
|
||||
}
|
Loading…
Reference in New Issue