mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-20 03:25:16 +00:00
commit
14123d67e1
25 changed files with 422 additions and 398 deletions
|
@ -325,7 +325,8 @@ public:
|
|||
auto& vmfprog = vm::ps3::_ref<CgBinaryFragmentProgram>(ptr + vmprog.program);
|
||||
u32 size;
|
||||
u32 ctrl = (vmfprog.outputFromH0 ? 0 : 0x40) | (vmfprog.depthReplace ? 0xe : 0);
|
||||
GLFragmentDecompilerThread(m_glsl_shader, param_array, ptr + vmprog.ucode, size, ctrl).Task();
|
||||
std::vector<texture_dimension> td;
|
||||
GLFragmentDecompilerThread(m_glsl_shader, param_array, ptr + vmprog.ucode, size, ctrl, td).Task();
|
||||
vm::close();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -180,14 +180,19 @@ bool is_primitive_native(unsigned m_draw_mode) noexcept
|
|||
case CELL_GCM_PRIMITIVE_TRIANGLES:
|
||||
case CELL_GCM_PRIMITIVE_TRIANGLE_STRIP:
|
||||
case CELL_GCM_PRIMITIVE_QUAD_STRIP:
|
||||
case CELL_GCM_PRIMITIVE_POLYGON:
|
||||
return true;
|
||||
case CELL_GCM_PRIMITIVE_POLYGON:
|
||||
case CELL_GCM_PRIMITIVE_TRIANGLE_FAN:
|
||||
case CELL_GCM_PRIMITIVE_QUADS:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** We assume that polygon is convex in polygon mode (constraints in OpenGL)
|
||||
*In such case polygon triangulation equates to triangle fan with arbitrary start vertex
|
||||
* see http://www.gamedev.net/page/resources/_/technical/graphics-programming-and-theory/polygon-triangulation-r3334
|
||||
*/
|
||||
|
||||
size_t get_index_count(unsigned m_draw_mode, unsigned initial_index_count) noexcept
|
||||
{
|
||||
// Index count
|
||||
|
@ -196,6 +201,7 @@ size_t get_index_count(unsigned m_draw_mode, unsigned initial_index_count) noexc
|
|||
|
||||
switch (m_draw_mode)
|
||||
{
|
||||
case CELL_GCM_PRIMITIVE_POLYGON:
|
||||
case CELL_GCM_PRIMITIVE_TRIANGLE_FAN:
|
||||
return (initial_index_count - 2) * 3;
|
||||
case CELL_GCM_PRIMITIVE_QUADS:
|
||||
|
@ -221,6 +227,7 @@ void write_index_array_for_non_indexed_non_native_primitive_to_buffer(char* dst,
|
|||
switch (draw_mode)
|
||||
{
|
||||
case CELL_GCM_PRIMITIVE_TRIANGLE_FAN:
|
||||
case CELL_GCM_PRIMITIVE_POLYGON:
|
||||
for (unsigned i = 0; i < (count - 2); i++)
|
||||
{
|
||||
typedDst[3 * i] = first;
|
||||
|
|
|
@ -5,12 +5,13 @@
|
|||
|
||||
#include "FragmentProgramDecompiler.h"
|
||||
|
||||
FragmentProgramDecompiler::FragmentProgramDecompiler(u32 addr, u32& size, u32 ctrl) :
|
||||
FragmentProgramDecompiler::FragmentProgramDecompiler(u32 addr, u32& size, u32 ctrl, const std::vector<texture_dimension> &texture_dimensions) :
|
||||
m_addr(addr),
|
||||
m_size(size),
|
||||
m_const_index(0),
|
||||
m_location(0),
|
||||
m_ctrl(ctrl)
|
||||
m_ctrl(ctrl),
|
||||
m_texture_dimensions(texture_dimensions)
|
||||
{
|
||||
m_size = 0;
|
||||
}
|
||||
|
@ -128,7 +129,7 @@ std::string FragmentProgramDecompiler::AddConst()
|
|||
|
||||
std::string FragmentProgramDecompiler::AddTex()
|
||||
{
|
||||
return m_parr.AddParam(PF_PARAM_UNIFORM, "sampler2D", std::string("tex") + std::to_string(dst.tex_num));
|
||||
return m_parr.AddParam(PF_PARAM_UNIFORM, (m_texture_dimensions[dst.tex_num] == texture_dimension::texture_dimension_cubemap) ? "samplerCube" : "sampler2D", std::string("tex") + std::to_string(dst.tex_num));
|
||||
}
|
||||
|
||||
std::string FragmentProgramDecompiler::Format(const std::string& code)
|
||||
|
@ -319,11 +320,6 @@ std::string FragmentProgramDecompiler::BuildCode()
|
|||
{
|
||||
//main += fmt::format("\tgl_FragColor = %c0;\n", m_ctrl & 0x40 ? 'r' : 'h');
|
||||
|
||||
if (m_ctrl & 0xe)
|
||||
{
|
||||
main += m_ctrl & 0x40 ? "\tgl_FragDepth = r1.z;\n" : "\tgl_FragDepth = h0.z;\n";
|
||||
}
|
||||
|
||||
std::stringstream OS;
|
||||
insertHeader(OS);
|
||||
OS << std::endl;
|
||||
|
@ -421,9 +417,39 @@ bool FragmentProgramDecompiler::handle_tex_srb(u32 opcode)
|
|||
case RSX_FP_OPCODE_DDY: SetDst(getFunction(FUNCTION::FUNCTION_DFDY)); return true;
|
||||
case RSX_FP_OPCODE_NRM: SetDst("normalize($0)"); return true;
|
||||
case RSX_FP_OPCODE_BEM: LOG_ERROR(RSX, "Unimplemented TEX_SRB instruction: BEM"); return true;
|
||||
case RSX_FP_OPCODE_TEX: SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE)); return true;
|
||||
case RSX_FP_OPCODE_TEX:
|
||||
if (dst.tex_num >= m_texture_dimensions.size())
|
||||
{
|
||||
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE));
|
||||
return true;
|
||||
}
|
||||
switch (m_texture_dimensions[dst.tex_num])
|
||||
{
|
||||
case texture_dimension::texture_dimension_2d:
|
||||
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE));
|
||||
return true;
|
||||
case texture_dimension::texture_dimension_cubemap:
|
||||
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_CUBE_SAMPLE));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case RSX_FP_OPCODE_TEXBEM: SetDst("texture($t, $0.xy, $1.x)"); return true;
|
||||
case RSX_FP_OPCODE_TXP: SetDst("textureProj($t, $0.xyz, $1.x)"); return true; //TODO: More testing (Sonic The Hedgehog (NPUB-30442/NPEB-00478) and The Simpsons Arcade Game (NPUB30563))
|
||||
case RSX_FP_OPCODE_TXP:
|
||||
if (dst.tex_num >= m_texture_dimensions.size())
|
||||
{
|
||||
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE_PROJ));
|
||||
return true;
|
||||
}
|
||||
switch (m_texture_dimensions[dst.tex_num])
|
||||
{
|
||||
case texture_dimension::texture_dimension_2d:
|
||||
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE_PROJ));
|
||||
return true;
|
||||
case texture_dimension::texture_dimension_cubemap:
|
||||
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_CUBE_SAMPLE_PROJ));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case RSX_FP_OPCODE_TXPBEM: SetDst("textureProj($t, $0.xyz, $1.x)"); return true;
|
||||
case RSX_FP_OPCODE_TXD: LOG_ERROR(RSX, "Unimplemented TEX_SRB instruction: TXD"); return true;
|
||||
case RSX_FP_OPCODE_TXB: SetDst("texture($t, $0.xy, $1.x)"); return true;
|
||||
|
|
|
@ -22,6 +22,7 @@ class FragmentProgramDecompiler
|
|||
std::string main;
|
||||
u32 m_addr;
|
||||
u32& m_size;
|
||||
const std::vector<texture_dimension> m_texture_dimensions;
|
||||
u32 m_const_index;
|
||||
u32 m_offset;
|
||||
u32 m_location;
|
||||
|
@ -107,6 +108,6 @@ protected:
|
|||
virtual void insertMainEnd(std::stringstream &OS) = 0;
|
||||
public:
|
||||
ParamArray m_parr;
|
||||
FragmentProgramDecompiler(u32 addr, u32& size, u32 ctrl);
|
||||
FragmentProgramDecompiler(u32 addr, u32& size, u32 ctrl, const std::vector<texture_dimension> &texture_dimensions);
|
||||
std::string Decompile();
|
||||
};
|
||||
|
|
|
@ -14,6 +14,9 @@ enum class FUNCTION {
|
|||
FUNCTION_DFDX,
|
||||
FUNCTION_DFDY,
|
||||
FUNCTION_TEXTURE_SAMPLE,
|
||||
FUNCTION_TEXTURE_SAMPLE_PROJ,
|
||||
FUNCTION_TEXTURE_CUBE_SAMPLE,
|
||||
FUNCTION_TEXTURE_CUBE_SAMPLE_PROJ,
|
||||
};
|
||||
|
||||
enum class COMPARE {
|
||||
|
|
|
@ -11,222 +11,144 @@ namespace
|
|||
/**
|
||||
* Write data, assume src pixels are packed but not mipmaplevel
|
||||
*/
|
||||
std::vector<MipmapLevelInfo>
|
||||
writeTexelsGeneric(const char *src, char *dst, size_t widthInBlock, size_t heightInBlock, size_t blockSize, size_t mipmapCount)
|
||||
struct texel_rgba
|
||||
{
|
||||
std::vector<MipmapLevelInfo> Result;
|
||||
size_t offsetInDst = 0, offsetInSrc = 0;
|
||||
size_t currentHeight = heightInBlock, currentWidth = widthInBlock;
|
||||
for (unsigned mipLevel = 0; mipLevel < mipmapCount; mipLevel++)
|
||||
template<size_t block_size>
|
||||
static size_t copy_mipmap_level(void *dst, void *src, size_t row_count, size_t width_in_block, size_t dst_pitch_in_block, size_t src_pitch_in_block) noexcept
|
||||
{
|
||||
size_t rowPitch = align(currentWidth * blockSize, 256);
|
||||
|
||||
MipmapLevelInfo currentMipmapLevelInfo = {};
|
||||
currentMipmapLevelInfo.offset = offsetInDst;
|
||||
currentMipmapLevelInfo.height = currentHeight;
|
||||
currentMipmapLevelInfo.width = currentWidth;
|
||||
currentMipmapLevelInfo.rowPitch = rowPitch;
|
||||
Result.push_back(currentMipmapLevelInfo);
|
||||
|
||||
for (unsigned row = 0; row < currentHeight; row++)
|
||||
memcpy((char*)dst + offsetInDst + row * rowPitch, (char*)src + offsetInSrc + row * widthInBlock * blockSize, currentWidth * blockSize);
|
||||
|
||||
offsetInDst += currentHeight * rowPitch;
|
||||
offsetInDst = align(offsetInDst, 512);
|
||||
offsetInSrc += currentHeight * widthInBlock * blockSize;
|
||||
currentHeight = MAX2(currentHeight / 2, 1);
|
||||
currentWidth = MAX2(currentWidth / 2, 1);
|
||||
for (unsigned row = 0; row < row_count; row++)
|
||||
memcpy((char*)dst + row * dst_pitch_in_block * block_size, (char*)src + row * src_pitch_in_block * block_size, width_in_block * block_size);
|
||||
return row_count * src_pitch_in_block * block_size;
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write data, assume src pixels are swizzled and but not mipmaplevel
|
||||
*/
|
||||
std::vector<MipmapLevelInfo>
|
||||
writeTexelsSwizzled(const char *src, char *dst, size_t widthInBlock, size_t heightInBlock, size_t blockSize, size_t mipmapCount)
|
||||
{
|
||||
std::vector<MipmapLevelInfo> Result;
|
||||
size_t offsetInDst = 0, offsetInSrc = 0;
|
||||
size_t currentHeight = heightInBlock, currentWidth = widthInBlock;
|
||||
for (unsigned mipLevel = 0; mipLevel < mipmapCount; mipLevel++)
|
||||
{
|
||||
size_t rowPitch = align(currentWidth * blockSize, 256);
|
||||
|
||||
MipmapLevelInfo currentMipmapLevelInfo = {};
|
||||
currentMipmapLevelInfo.offset = offsetInDst;
|
||||
currentMipmapLevelInfo.height = currentHeight;
|
||||
currentMipmapLevelInfo.width = currentWidth;
|
||||
currentMipmapLevelInfo.rowPitch = rowPitch;
|
||||
Result.push_back(currentMipmapLevelInfo);
|
||||
|
||||
u32 *castedSrc, *castedDst;
|
||||
|
||||
castedSrc = (u32*)src + offsetInSrc;
|
||||
castedDst = (u32*)dst + offsetInDst;
|
||||
|
||||
std::unique_ptr<u32[]> temp_swizzled(new u32[currentHeight * currentWidth]);
|
||||
rsx::convert_linear_swizzle<u32>(castedSrc, temp_swizzled.get(), currentWidth, currentHeight, true);
|
||||
for (unsigned row = 0; row < currentHeight; row++)
|
||||
memcpy((char*)dst + offsetInDst + row * rowPitch, (char*)temp_swizzled.get() + offsetInSrc + row * widthInBlock * blockSize, currentWidth * blockSize);
|
||||
|
||||
offsetInDst += currentHeight * rowPitch;
|
||||
offsetInSrc += currentHeight * widthInBlock * blockSize;
|
||||
currentHeight = MAX2(currentHeight / 2, 1);
|
||||
currentWidth = MAX2(currentWidth / 2, 1);
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write data, assume compressed (DXTCn) format
|
||||
*/
|
||||
std::vector<MipmapLevelInfo>
|
||||
writeCompressedTexel(const char *src, char *dst, size_t widthInBlock, size_t blockWidth, size_t heightInBlock, size_t blockHeight, size_t blockSize, size_t mipmapCount)
|
||||
{
|
||||
std::vector<MipmapLevelInfo> Result;
|
||||
size_t offsetInDst = 0, offsetInSrc = 0;
|
||||
size_t currentHeight = heightInBlock, currentWidth = widthInBlock;
|
||||
for (unsigned mipLevel = 0; mipLevel < mipmapCount; mipLevel++)
|
||||
{
|
||||
size_t rowPitch = align(currentWidth * blockSize, 256);
|
||||
|
||||
MipmapLevelInfo currentMipmapLevelInfo = {};
|
||||
currentMipmapLevelInfo.offset = offsetInDst;
|
||||
currentMipmapLevelInfo.height = currentHeight * blockHeight;
|
||||
currentMipmapLevelInfo.width = currentWidth * blockWidth;
|
||||
currentMipmapLevelInfo.rowPitch = rowPitch;
|
||||
Result.push_back(currentMipmapLevelInfo);
|
||||
|
||||
for (unsigned row = 0; row < currentHeight; row++)
|
||||
memcpy((char*)dst + offsetInDst + row * rowPitch, (char*)src + offsetInSrc + row * currentWidth * blockSize, currentWidth * blockSize);
|
||||
|
||||
offsetInDst += currentHeight * rowPitch;
|
||||
offsetInDst = align(offsetInDst, 512);
|
||||
offsetInSrc += currentHeight * currentWidth * blockSize;
|
||||
currentHeight = MAX2(currentHeight / 2, 1);
|
||||
currentWidth = MAX2(currentWidth / 2, 1);
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Write 16 bytes pixel textures, assume src pixels are swizzled and but not mipmaplevel
|
||||
*/
|
||||
std::vector<MipmapLevelInfo>
|
||||
write16bTexelsSwizzled(const char *src, char *dst, size_t widthInBlock, size_t heightInBlock, size_t blockSize, size_t mipmapCount)
|
||||
struct texel_16b_swizzled
|
||||
{
|
||||
std::vector<MipmapLevelInfo> Result;
|
||||
size_t offsetInDst = 0, offsetInSrc = 0;
|
||||
size_t currentHeight = heightInBlock, currentWidth = widthInBlock;
|
||||
size_t srcPitch = widthInBlock * blockSize;
|
||||
for (unsigned mipLevel = 0; mipLevel < mipmapCount; mipLevel++)
|
||||
template<size_t block_size>
|
||||
static size_t copy_mipmap_level(void *dst, void *src, size_t row_count, size_t width_in_block, size_t dst_pitch_in_block, size_t src_pitch_in_block) noexcept
|
||||
{
|
||||
size_t rowPitch = align(currentWidth * blockSize, 256);
|
||||
u16 *castedSrc = static_cast<u16*>(src), *castedDst = static_cast<u16*>(dst);
|
||||
|
||||
MipmapLevelInfo currentMipmapLevelInfo = {};
|
||||
currentMipmapLevelInfo.offset = offsetInDst;
|
||||
currentMipmapLevelInfo.height = currentHeight;
|
||||
currentMipmapLevelInfo.width = currentWidth;
|
||||
currentMipmapLevelInfo.rowPitch = rowPitch;
|
||||
Result.push_back(currentMipmapLevelInfo);
|
||||
|
||||
u16 *castedSrc, *castedDst;
|
||||
|
||||
castedSrc = (u16*)src + offsetInSrc;
|
||||
castedDst = (u16*)dst + offsetInDst;
|
||||
|
||||
std::unique_ptr<u16[]> temp_swizzled(new u16[currentHeight * currentWidth]);
|
||||
rsx::convert_linear_swizzle<u16>(castedSrc, temp_swizzled.get(), currentWidth, currentHeight, true);
|
||||
for (unsigned row = 0; row < heightInBlock; row++)
|
||||
for (int j = 0; j < currentWidth; j++)
|
||||
std::unique_ptr<u16[]> temp_swizzled(new u16[row_count * width_in_block]);
|
||||
rsx::convert_linear_swizzle<u16>(castedSrc, temp_swizzled.get(), src_pitch_in_block, row_count, true);
|
||||
for (unsigned row = 0; row < row_count; row++)
|
||||
for (int j = 0; j < width_in_block; j++)
|
||||
{
|
||||
u16 tmp = temp_swizzled[offsetInSrc / 2 + row * srcPitch / 2 + j];
|
||||
castedDst[offsetInDst / 2 + row * rowPitch / 2 + j] = (tmp >> 8) | (tmp << 8);
|
||||
u16 tmp = temp_swizzled[row * src_pitch_in_block + j];
|
||||
castedDst[row * dst_pitch_in_block + j] = (tmp >> 8) | (tmp << 8);
|
||||
}
|
||||
|
||||
offsetInDst += currentHeight * rowPitch;
|
||||
offsetInSrc += currentHeight * widthInBlock * blockSize;
|
||||
currentHeight = MAX2(currentHeight / 2, 1);
|
||||
currentWidth = MAX2(currentWidth / 2, 1);
|
||||
return row_count * src_pitch_in_block * block_size;
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Write data, assume src pixels are swizzled and but not mipmaplevel
|
||||
*/
|
||||
struct texel_rgba_swizzled
|
||||
{
|
||||
template<size_t block_size>
|
||||
static size_t copy_mipmap_level(void *dst, void *src, size_t row_count, size_t width_in_block, size_t dst_pitch_in_block, size_t src_pitch_in_block) noexcept
|
||||
{
|
||||
u32 *castedSrc, *castedDst;
|
||||
castedSrc = (u32*)src;
|
||||
castedDst = (u32*)dst ;
|
||||
std::unique_ptr<u32[]> temp_swizzled(new u32[src_pitch_in_block * row_count]);
|
||||
rsx::convert_linear_swizzle<u32>(castedSrc, temp_swizzled.get(), src_pitch_in_block, row_count, true);
|
||||
for (unsigned row = 0; row < row_count; row++)
|
||||
memcpy((char*)dst + row * dst_pitch_in_block * block_size, (char*)temp_swizzled.get() + row * src_pitch_in_block * block_size, width_in_block * block_size);
|
||||
return row_count * src_pitch_in_block * block_size;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Write data, assume compressed (DXTCn) format
|
||||
* Data are tightly packed
|
||||
*/
|
||||
struct texel_bc_format {
|
||||
template<size_t block_size>
|
||||
static size_t copy_mipmap_level(void *dst, void *src, size_t row_count, size_t width_in_block, size_t dst_pitch_in_block, size_t src_pitch_in_block) noexcept
|
||||
{
|
||||
for (unsigned row = 0; row < row_count; row++)
|
||||
memcpy((char*)dst + row * dst_pitch_in_block * block_size, (char*)src + row * width_in_block * block_size, width_in_block * block_size);
|
||||
return width_in_block * row_count * block_size;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Write 16 bytes pixel textures, assume src pixels are packed but not mipmaplevel
|
||||
*/
|
||||
std::vector<MipmapLevelInfo>
|
||||
write16bTexelsGeneric(const char *src, char *dst, size_t widthInBlock, size_t heightInBlock, size_t blockSize, size_t mipmapCount)
|
||||
{
|
||||
std::vector<MipmapLevelInfo> Result;
|
||||
size_t offsetInDst = 0, offsetInSrc = 0;
|
||||
size_t currentHeight = heightInBlock, currentWidth = widthInBlock;
|
||||
size_t srcPitch = widthInBlock * blockSize;
|
||||
for (unsigned mipLevel = 0; mipLevel < mipmapCount; mipLevel++)
|
||||
struct texel_16b_format {
|
||||
template<size_t block_size>
|
||||
static size_t copy_mipmap_level(void *dst, void *src, size_t row_count, size_t width_in_block, size_t dst_pitch_in_block, size_t src_pitch_in_block) noexcept
|
||||
{
|
||||
size_t rowPitch = align(currentWidth * blockSize, 256);
|
||||
|
||||
MipmapLevelInfo currentMipmapLevelInfo = {};
|
||||
currentMipmapLevelInfo.offset = offsetInDst;
|
||||
currentMipmapLevelInfo.height = currentHeight;
|
||||
currentMipmapLevelInfo.width = currentWidth;
|
||||
currentMipmapLevelInfo.rowPitch = rowPitch;
|
||||
Result.push_back(currentMipmapLevelInfo);
|
||||
|
||||
unsigned short *castedDst = (unsigned short *)dst, *castedSrc = (unsigned short *)src;
|
||||
|
||||
for (unsigned row = 0; row < heightInBlock; row++)
|
||||
for (int j = 0; j < currentWidth; j++)
|
||||
for (unsigned row = 0; row < row_count; row++)
|
||||
for (int j = 0; j < width_in_block; j++)
|
||||
{
|
||||
u16 tmp = castedSrc[offsetInSrc / 2 + row * srcPitch / 2 + j];
|
||||
castedDst[offsetInDst / 2 + row * rowPitch / 2 + j] = (tmp >> 8) | (tmp << 8);
|
||||
u16 tmp = castedSrc[row * src_pitch_in_block + j];
|
||||
castedDst[row * dst_pitch_in_block + j] = (tmp >> 8) | (tmp << 8);
|
||||
}
|
||||
|
||||
offsetInDst += currentHeight * rowPitch;
|
||||
offsetInSrc += currentHeight * widthInBlock * blockSize;
|
||||
currentHeight = MAX2(currentHeight / 2, 1);
|
||||
currentWidth = MAX2(currentWidth / 2, 1);
|
||||
return row_count * src_pitch_in_block * block_size;
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Write 16 bytes pixel textures, assume src pixels are packed but not mipmaplevel
|
||||
* Write 16 bytes X 4 pixel textures, assume src pixels are packed but not mipmaplevel
|
||||
*/
|
||||
std::vector<MipmapLevelInfo>
|
||||
write16bX4TexelsGeneric(const char *src, char *dst, size_t widthInBlock, size_t heightInBlock, size_t blockSize, size_t mipmapCount)
|
||||
struct texel_16bX4_format {
|
||||
template<size_t block_size>
|
||||
static size_t copy_mipmap_level(void *dst, void *src, size_t row_count, size_t width_in_block, size_t dst_pitch_in_block, size_t src_pitch_in_block) noexcept
|
||||
{
|
||||
unsigned short *casted_dst = (unsigned short *)dst, *casted_src = (unsigned short *)src;
|
||||
for (unsigned row = 0; row < row_count; row++)
|
||||
for (int j = 0; j < width_in_block * 4; j++)
|
||||
{
|
||||
u16 tmp = casted_src[row * src_pitch_in_block * 4 + j];
|
||||
casted_dst[row * dst_pitch_in_block * 4 + j] = (tmp >> 8) | (tmp << 8);
|
||||
}
|
||||
return row_count * src_pitch_in_block * block_size;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Texture upload template.
|
||||
* The template iterates over all depth (including cubemap) and over all mipmaps.
|
||||
* The alignment is 256 for mipmap levels and 512 for depth (TODO: make this customisable for Vulkan ?)
|
||||
* The template takes a struct with a "copy_mipmap_level" static function that copy the given mipmap level and returns the offset to add to the src buffer for next
|
||||
* mipmap level (to allow same code for packed/non packed texels)
|
||||
*/
|
||||
template <typename T, size_t block_size_in_bytes, size_t block_edge_in_texel = 1>
|
||||
std::vector<MipmapLevelInfo> copy_texture_data(void *dst, const void *src, size_t widthInBlock, size_t heightInBlock, size_t depth, size_t mipmapCount) noexcept
|
||||
{
|
||||
std::vector<MipmapLevelInfo> Result;
|
||||
size_t offsetInDst = 0, offsetInSrc = 0;
|
||||
size_t currentHeight = heightInBlock, currentWidth = widthInBlock;
|
||||
size_t srcPitch = widthInBlock * blockSize;
|
||||
for (unsigned mipLevel = 0; mipLevel < mipmapCount; mipLevel++)
|
||||
// Every mipmap level of rsx textures use the same rowpitch.
|
||||
size_t src_pitch = widthInBlock;
|
||||
for (unsigned depth_level = 0; depth_level < depth; depth_level++)
|
||||
{
|
||||
size_t rowPitch = align(currentWidth * blockSize, 256);
|
||||
size_t miplevel_height_in_block = heightInBlock, miplevel_width_in_block = widthInBlock;
|
||||
for (unsigned mip_level = 0; mip_level < mipmapCount; mip_level++)
|
||||
{
|
||||
size_t dst_pitch = align(miplevel_width_in_block * block_size_in_bytes, 256) / block_size_in_bytes;
|
||||
|
||||
MipmapLevelInfo currentMipmapLevelInfo = {};
|
||||
currentMipmapLevelInfo.offset = offsetInDst;
|
||||
currentMipmapLevelInfo.height = currentHeight;
|
||||
currentMipmapLevelInfo.width = currentWidth;
|
||||
currentMipmapLevelInfo.rowPitch = rowPitch;
|
||||
Result.push_back(currentMipmapLevelInfo);
|
||||
MipmapLevelInfo currentMipmapLevelInfo = {};
|
||||
currentMipmapLevelInfo.offset = offsetInDst;
|
||||
currentMipmapLevelInfo.height = miplevel_height_in_block * block_edge_in_texel;
|
||||
currentMipmapLevelInfo.width = miplevel_width_in_block * block_edge_in_texel;
|
||||
currentMipmapLevelInfo.rowPitch = dst_pitch * block_size_in_bytes;
|
||||
Result.push_back(currentMipmapLevelInfo);
|
||||
|
||||
unsigned short *castedDst = (unsigned short *)dst, *castedSrc = (unsigned short *)src;
|
||||
|
||||
for (unsigned row = 0; row < heightInBlock; row++)
|
||||
for (int j = 0; j < currentWidth * 4; j++)
|
||||
{
|
||||
u16 tmp = castedSrc[offsetInSrc / 2 + row * srcPitch / 2 + j];
|
||||
castedDst[offsetInDst / 2 + row * rowPitch / 2 + j] = (tmp >> 8) | (tmp << 8);
|
||||
}
|
||||
|
||||
offsetInDst += currentHeight * rowPitch;
|
||||
offsetInSrc += currentHeight * widthInBlock * blockSize;
|
||||
currentHeight = MAX2(currentHeight / 2, 1);
|
||||
currentWidth = MAX2(currentWidth / 2, 1);
|
||||
offsetInSrc += T::template copy_mipmap_level<block_size_in_bytes>((char*)dst + offsetInDst, (char*)src + offsetInSrc, miplevel_height_in_block, miplevel_width_in_block, dst_pitch, src_pitch);
|
||||
offsetInDst += align(miplevel_height_in_block * dst_pitch * block_size_in_bytes, 512);
|
||||
miplevel_height_in_block = MAX2(miplevel_height_in_block / 2, 1);
|
||||
miplevel_width_in_block = MAX2(miplevel_width_in_block / 2, 1);
|
||||
}
|
||||
offsetInSrc = align(offsetInSrc, 128);
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
@ -328,12 +250,14 @@ size_t get_placed_texture_storage_size(const rsx::texture &texture, size_t rowPi
|
|||
|
||||
size_t rowPitch = align(blockSizeInByte * widthInBlocks, rowPitchAlignement);
|
||||
|
||||
return rowPitch * heightInBlocks * 2; // * 2 for mipmap levels
|
||||
return rowPitch * heightInBlocks * (texture.cubemap() ? 6 : 1) * 2; // * 2 for mipmap levels
|
||||
}
|
||||
|
||||
std::vector<MipmapLevelInfo> upload_placed_texture(const rsx::texture &texture, size_t rowPitchAlignement, void* textureData) noexcept
|
||||
{
|
||||
size_t w = texture.width(), h = texture.height();
|
||||
size_t depth = texture.depth();
|
||||
if (texture.cubemap()) depth *= 6;
|
||||
|
||||
int format = texture.format() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
|
||||
|
||||
|
@ -352,24 +276,28 @@ std::vector<MipmapLevelInfo> upload_placed_texture(const rsx::texture &texture,
|
|||
{
|
||||
case CELL_GCM_TEXTURE_A8R8G8B8:
|
||||
if (is_swizzled)
|
||||
return writeTexelsSwizzled((char*)pixels, (char*)textureData, w, h, 4, texture.mipmap());
|
||||
return copy_texture_data<texel_rgba_swizzled, 4, 1>(textureData, pixels, widthInBlocks, heightInBlocks, depth, texture.mipmap());
|
||||
else
|
||||
return writeTexelsGeneric((char*)pixels, (char*)textureData, w, h, 4, texture.mipmap());
|
||||
return copy_texture_data<texel_rgba, 4, 1>(textureData, pixels, widthInBlocks, heightInBlocks, depth, texture.mipmap());
|
||||
case CELL_GCM_TEXTURE_A1R5G5B5:
|
||||
case CELL_GCM_TEXTURE_A4R4G4B4:
|
||||
case CELL_GCM_TEXTURE_R5G6B5:
|
||||
if (is_swizzled)
|
||||
return write16bTexelsSwizzled((char*)pixels, (char*)textureData, w, h, 2, texture.mipmap());
|
||||
return copy_texture_data<texel_16b_swizzled, 2, 1>(textureData, pixels, widthInBlocks, heightInBlocks, depth, texture.mipmap());
|
||||
else
|
||||
return write16bTexelsGeneric((char*)pixels, (char*)textureData, w, h, 2, texture.mipmap());
|
||||
return copy_texture_data<texel_16b_format, 2, 1>(textureData, pixels, widthInBlocks, heightInBlocks, depth, texture.mipmap());
|
||||
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT:
|
||||
return write16bX4TexelsGeneric((char*)pixels, (char*)textureData, w, h, 8, texture.mipmap());
|
||||
return copy_texture_data<texel_16bX4_format, 8, 1>(textureData, pixels, widthInBlocks, heightInBlocks, depth, texture.mipmap());
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT1:
|
||||
return copy_texture_data<texel_bc_format, 8, 4>(textureData, pixels, widthInBlocks, heightInBlocks, depth, texture.mipmap());
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT23:
|
||||
return copy_texture_data<texel_bc_format, 16, 4>(textureData, pixels, widthInBlocks, heightInBlocks, depth, texture.mipmap());
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT45:
|
||||
return writeCompressedTexel((char*)pixels, (char*)textureData, widthInBlocks, blockEdge, heightInBlocks, blockEdge, blockSizeInByte, texture.mipmap());
|
||||
return copy_texture_data<texel_bc_format, 16, 4>(textureData, pixels, widthInBlocks, heightInBlocks, depth, texture.mipmap());
|
||||
case CELL_GCM_TEXTURE_B8:
|
||||
return copy_texture_data<texel_rgba, 1, 1>(textureData, pixels, widthInBlocks, heightInBlocks, depth, texture.mipmap());
|
||||
default:
|
||||
return writeTexelsGeneric((char*)pixels, (char*)textureData, w, h, blockSizeInByte, texture.mipmap());
|
||||
return copy_texture_data<texel_rgba, 4, 1>(textureData, pixels, widthInBlocks, heightInBlocks, depth, texture.mipmap());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -253,7 +253,7 @@ std::string VertexProgramDecompiler::GetCond()
|
|||
swizzle += f[d0.mask_w];
|
||||
|
||||
swizzle = swizzle == "xyzw" ? "" : "." + swizzle;
|
||||
return "any(" + compareFunction(cond_string_table[d0.cond], "cc" + std::to_string(d0.cond_reg_sel_1), getFloatTypeName(4) + "(0., 0., 0., 0.)" + swizzle) + ")";
|
||||
return "any(" + compareFunction(cond_string_table[d0.cond], "cc" + std::to_string(d0.cond_reg_sel_1) + swizzle, getFloatTypeName(4) + "(0., 0., 0., 0.)" + swizzle) + ")";
|
||||
}
|
||||
|
||||
void VertexProgramDecompiler::AddCodeCond(const std::string& dst, const std::string& src)
|
||||
|
|
|
@ -159,9 +159,14 @@ void D3D12GSRender::upload_and_bind_scale_offset_matrix(size_t descriptorIndex)
|
|||
size_t tex_idx = 0;
|
||||
for (u32 i = 0; i < rsx::limits::textures_count; ++i)
|
||||
{
|
||||
if (!textures[i].enabled()) continue;
|
||||
if (!textures[i].enabled())
|
||||
{
|
||||
int is_unorm = false;
|
||||
memcpy((char*)mapped_buffer + heap_offset + (18 + tex_idx++) * sizeof(int), &is_unorm, sizeof(int));
|
||||
continue;
|
||||
}
|
||||
size_t w = textures[i].width(), h = textures[i].height();
|
||||
if (!w || !h) continue;
|
||||
// if (!w || !h) continue;
|
||||
|
||||
int is_unorm = (textures[i].format() & CELL_GCM_TEXTURE_UN);
|
||||
memcpy((char*)mapped_buffer + heap_offset + (18 + tex_idx++) * sizeof(int), &is_unorm, sizeof(int));
|
||||
|
|
|
@ -44,6 +44,12 @@ std::string getFunctionImp(FUNCTION f)
|
|||
return "frac($0)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE:
|
||||
return "$t.Sample($tsampler, $0.xy * $t_scale)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE_PROJ:
|
||||
return "$t.Sample($tsampler, ($0.xy / $0.z) * $t_scale)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_CUBE_SAMPLE:
|
||||
return "$t.Sample($tsampler, $0.xyz)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_CUBE_SAMPLE_PROJ:
|
||||
return "$t.Sample($tsampler, ($0.xyz / $0.w))";
|
||||
case FUNCTION::FUNCTION_DFDX:
|
||||
return "ddx($0)";
|
||||
case FUNCTION::FUNCTION_DFDY:
|
||||
|
|
|
@ -18,9 +18,9 @@ D3D12_BLEND_OP get_blend_op(u16 op) noexcept
|
|||
case CELL_GCM_FUNC_ADD_SIGNED:
|
||||
case CELL_GCM_FUNC_REVERSE_ADD_SIGNED:
|
||||
case CELL_GCM_FUNC_REVERSE_SUBTRACT_SIGNED:
|
||||
unreachable("Unsupported blend op");
|
||||
unreachable("Unsupported blend op used %x, please report this to a developer.", op);
|
||||
}
|
||||
unreachable("Wrong blend op");
|
||||
unreachable("Unimplemented blend op used %x, please report this to a developer.", op);
|
||||
}
|
||||
|
||||
D3D12_BLEND get_blend_factor(u16 factor) noexcept
|
||||
|
@ -42,9 +42,9 @@ D3D12_BLEND get_blend_factor(u16 factor) noexcept
|
|||
case CELL_GCM_ONE_MINUS_CONSTANT_COLOR:
|
||||
case CELL_GCM_CONSTANT_ALPHA:
|
||||
case CELL_GCM_ONE_MINUS_CONSTANT_ALPHA:
|
||||
unreachable("Unsupported blend color factor");
|
||||
unreachable("Unsupported blend color factor used %x, please report this to a developer.", factor);
|
||||
}
|
||||
unreachable("Wrong blend color factor");
|
||||
unreachable("Unimplemented blend color factor used %x, please report this to a developer.", factor);
|
||||
}
|
||||
|
||||
D3D12_BLEND get_blend_factor_alpha(u16 factor) noexcept
|
||||
|
@ -66,9 +66,9 @@ D3D12_BLEND get_blend_factor_alpha(u16 factor) noexcept
|
|||
case CELL_GCM_ONE_MINUS_CONSTANT_COLOR:
|
||||
case CELL_GCM_CONSTANT_ALPHA:
|
||||
case CELL_GCM_ONE_MINUS_CONSTANT_ALPHA:
|
||||
unreachable("Unsupported blend alpha factor");
|
||||
unreachable("Unsupported blend alpha factor used %x, please report this to a developer.", factor);
|
||||
}
|
||||
unreachable("Wrong blend alpha factor");
|
||||
unreachable("Unimplemented blend alpha factor used %x, please report this to a developer.", factor);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -94,7 +94,7 @@ D3D12_LOGIC_OP get_logic_op(u32 op) noexcept
|
|||
case CELL_GCM_OR_INVERTED: return D3D12_LOGIC_OP_OR_INVERTED;
|
||||
case CELL_GCM_NAND: return D3D12_LOGIC_OP_NAND;
|
||||
}
|
||||
unreachable("Wrong logic op");
|
||||
unreachable("Unimplemented logic op used %x, please report this to a developer.", op);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -113,15 +113,13 @@ D3D12_STENCIL_OP get_stencil_op(u32 op) noexcept
|
|||
case CELL_GCM_INCR_WRAP: return D3D12_STENCIL_OP_INCR;
|
||||
case CELL_GCM_DECR_WRAP: return D3D12_STENCIL_OP_DECR;
|
||||
}
|
||||
LOG_ERROR(RSX, "Unknow stencil op used %x, please report this to a developer.", op);
|
||||
unreachable("Wrong Stencil op");
|
||||
unreachable("Unimplemented stencil op used %x, please report this to a developer.", op);
|
||||
}
|
||||
|
||||
D3D12_COMPARISON_FUNC get_compare_func(u32 op) noexcept
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case CELL_GCM_ZERO:
|
||||
case CELL_GCM_NEVER: return D3D12_COMPARISON_FUNC_NEVER;
|
||||
case CELL_GCM_LESS: return D3D12_COMPARISON_FUNC_LESS;
|
||||
case CELL_GCM_EQUAL: return D3D12_COMPARISON_FUNC_EQUAL;
|
||||
|
@ -130,71 +128,48 @@ D3D12_COMPARISON_FUNC get_compare_func(u32 op) noexcept
|
|||
case CELL_GCM_NOTEQUAL: return D3D12_COMPARISON_FUNC_NOT_EQUAL;
|
||||
case CELL_GCM_GEQUAL: return D3D12_COMPARISON_FUNC_GREATER_EQUAL;
|
||||
case CELL_GCM_ALWAYS: return D3D12_COMPARISON_FUNC_ALWAYS;
|
||||
case CELL_GCM_ZERO:
|
||||
unreachable("Unsupported compare function used %x, please report this to a developer.", op);
|
||||
}
|
||||
unreachable("Wrong compare function");
|
||||
unreachable("Unimplemented compare function used %x, please report this to a developer.", op);
|
||||
}
|
||||
|
||||
DXGI_FORMAT get_texture_format(int format) noexcept
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case CELL_GCM_TEXTURE_B8:
|
||||
return DXGI_FORMAT_R8_UNORM;
|
||||
case CELL_GCM_TEXTURE_A1R5G5B5:
|
||||
return DXGI_FORMAT_B5G5R5A1_UNORM;
|
||||
case CELL_GCM_TEXTURE_A4R4G4B4:
|
||||
return DXGI_FORMAT_B4G4R4A4_UNORM;
|
||||
case CELL_GCM_TEXTURE_R5G6B5:
|
||||
return DXGI_FORMAT_B5G6R5_UNORM;
|
||||
case CELL_GCM_TEXTURE_A8R8G8B8:
|
||||
return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT1:
|
||||
return DXGI_FORMAT_BC1_UNORM;
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT23:
|
||||
return DXGI_FORMAT_BC2_UNORM;
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT45:
|
||||
return DXGI_FORMAT_BC3_UNORM;
|
||||
case CELL_GCM_TEXTURE_G8B8:
|
||||
return DXGI_FORMAT_G8R8_G8B8_UNORM;
|
||||
case CELL_GCM_TEXTURE_R6G5B5:
|
||||
// Not native
|
||||
return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
case CELL_GCM_TEXTURE_DEPTH24_D8:
|
||||
return DXGI_FORMAT_R32_UINT;
|
||||
case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT:
|
||||
return DXGI_FORMAT_R32_FLOAT;
|
||||
case CELL_GCM_TEXTURE_DEPTH16:
|
||||
return DXGI_FORMAT_R16_UNORM;
|
||||
case CELL_GCM_TEXTURE_DEPTH16_FLOAT:
|
||||
return DXGI_FORMAT_R16_FLOAT;
|
||||
case CELL_GCM_TEXTURE_X16:
|
||||
return DXGI_FORMAT_R16_UNORM;
|
||||
case CELL_GCM_TEXTURE_Y16_X16:
|
||||
return DXGI_FORMAT_R16G16_UNORM;
|
||||
case CELL_GCM_TEXTURE_R5G5B5A1:
|
||||
return DXGI_FORMAT_B5G5R5A1_UNORM;
|
||||
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT:
|
||||
return DXGI_FORMAT_R16G16B16A16_FLOAT;
|
||||
case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT:
|
||||
return DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||
case CELL_GCM_TEXTURE_X32_FLOAT:
|
||||
return DXGI_FORMAT_R32_FLOAT;
|
||||
case CELL_GCM_TEXTURE_D1R5G5B5:
|
||||
return DXGI_FORMAT_B5G5R5A1_UNORM;
|
||||
case CELL_GCM_TEXTURE_D8R8G8B8:
|
||||
return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8:
|
||||
return DXGI_FORMAT_G8R8_G8B8_UNORM;
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8:
|
||||
return DXGI_FORMAT_R8G8_B8G8_UNORM;
|
||||
case CELL_GCM_TEXTURE_B8: return DXGI_FORMAT_R8_UNORM;
|
||||
case CELL_GCM_TEXTURE_A1R5G5B5: return DXGI_FORMAT_B5G5R5A1_UNORM;
|
||||
case CELL_GCM_TEXTURE_A4R4G4B4: return DXGI_FORMAT_B4G4R4A4_UNORM;
|
||||
case CELL_GCM_TEXTURE_R5G6B5: return DXGI_FORMAT_B5G6R5_UNORM;
|
||||
case CELL_GCM_TEXTURE_A8R8G8B8: return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT1: return DXGI_FORMAT_BC1_UNORM;
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT23: return DXGI_FORMAT_BC2_UNORM;
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT45: return DXGI_FORMAT_BC3_UNORM;
|
||||
case CELL_GCM_TEXTURE_G8B8: return DXGI_FORMAT_G8R8_G8B8_UNORM;
|
||||
case CELL_GCM_TEXTURE_R6G5B5: /*Not native*/ return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
case CELL_GCM_TEXTURE_DEPTH24_D8: return DXGI_FORMAT_R32_UINT;
|
||||
case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT: return DXGI_FORMAT_R32_FLOAT;
|
||||
case CELL_GCM_TEXTURE_DEPTH16: return DXGI_FORMAT_R16_UNORM;
|
||||
case CELL_GCM_TEXTURE_DEPTH16_FLOAT: return DXGI_FORMAT_R16_FLOAT;
|
||||
case CELL_GCM_TEXTURE_X16: return DXGI_FORMAT_R16_UNORM;
|
||||
case CELL_GCM_TEXTURE_Y16_X16: return DXGI_FORMAT_R16G16_UNORM;
|
||||
case CELL_GCM_TEXTURE_R5G5B5A1: return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT: return DXGI_FORMAT_R16G16B16A16_FLOAT;
|
||||
case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT: return DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||
case CELL_GCM_TEXTURE_X32_FLOAT: return DXGI_FORMAT_R32_FLOAT;
|
||||
case CELL_GCM_TEXTURE_D1R5G5B5: return DXGI_FORMAT_B5G5R5A1_UNORM;
|
||||
case CELL_GCM_TEXTURE_D8R8G8B8: return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8: return DXGI_FORMAT_G8R8_G8B8_UNORM;
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8: return DXGI_FORMAT_R8G8_B8G8_UNORM;
|
||||
case CELL_GCM_TEXTURE_Y16_X16_FLOAT:
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_HILO8:
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_HILO_S8:
|
||||
case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8:
|
||||
case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8:
|
||||
unreachable( "Unimplemented Texture format");
|
||||
unreachable("Unsupported texture format used %x, please report this to a developer.", format);
|
||||
}
|
||||
unreachable("Wrong Texture format");
|
||||
unreachable("Unimplemented texture format used %x, please report this to a developer.", format);
|
||||
}
|
||||
|
||||
UINT get_texture_max_aniso(u8 aniso) noexcept
|
||||
|
@ -210,7 +185,7 @@ UINT get_texture_max_aniso(u8 aniso) noexcept
|
|||
case CELL_GCM_TEXTURE_MAX_ANISO_12: return 12;
|
||||
case CELL_GCM_TEXTURE_MAX_ANISO_16: return 16;
|
||||
}
|
||||
unreachable("Wrong Texture max aniso");
|
||||
unreachable("Unimplemented texture max aniso used %x, please report this to a developer.", aniso);
|
||||
}
|
||||
|
||||
D3D12_TEXTURE_ADDRESS_MODE get_texture_wrap_mode(u8 wrap) noexcept
|
||||
|
@ -226,7 +201,7 @@ D3D12_TEXTURE_ADDRESS_MODE get_texture_wrap_mode(u8 wrap) noexcept
|
|||
case CELL_GCM_TEXTURE_MIRROR_ONCE_BORDER: return D3D12_TEXTURE_ADDRESS_MODE_MIRROR_ONCE;
|
||||
case CELL_GCM_TEXTURE_MIRROR_ONCE_CLAMP: return D3D12_TEXTURE_ADDRESS_MODE_MIRROR_ONCE;
|
||||
}
|
||||
unreachable("Wrong texture wrap mode");
|
||||
unreachable("Unimplemented texture wrap mode used %x, please report this to a developer.", wrap);
|
||||
}
|
||||
|
||||
namespace
|
||||
|
@ -260,12 +235,11 @@ namespace
|
|||
mip = D3D12_FILTER_TYPE_LINEAR;
|
||||
return;
|
||||
case CELL_GCM_TEXTURE_CONVOLUTION_MIN:
|
||||
LOG_WARNING(RSX, "CELL_GCM_TEXTURE_CONVOLUTION_MIN not supported, fallback to bilinear filtering");
|
||||
min = D3D12_FILTER_TYPE_LINEAR;
|
||||
mip = D3D12_FILTER_TYPE_POINT;
|
||||
return;
|
||||
}
|
||||
unreachable("Wrong min filter");
|
||||
unreachable("Unimplemented min filter used %x, please report this to a developer.", min_filter);
|
||||
}
|
||||
|
||||
D3D12_FILTER_TYPE get_mag_filter(u8 mag_filter) noexcept
|
||||
|
@ -275,9 +249,7 @@ namespace
|
|||
case CELL_GCM_TEXTURE_NEAREST: return D3D12_FILTER_TYPE_POINT;
|
||||
case CELL_GCM_TEXTURE_LINEAR: return D3D12_FILTER_TYPE_LINEAR;
|
||||
}
|
||||
// Catherine uses this
|
||||
LOG_WARNING(RSX, "Unknow mag filter used %x, fallback to bilinear filtering", mag_filter);
|
||||
return D3D12_FILTER_TYPE_LINEAR;
|
||||
unreachable("Unimplemented mag filter used %x, please report this to a developer.", mag_filter);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -299,44 +271,43 @@ D3D12_PRIMITIVE_TOPOLOGY get_primitive_topology(u8 draw_mode) noexcept
|
|||
case CELL_GCM_PRIMITIVE_LINE_STRIP: return D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
|
||||
case CELL_GCM_PRIMITIVE_TRIANGLES: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
|
||||
case CELL_GCM_PRIMITIVE_TRIANGLE_STRIP: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
|
||||
// Emulated
|
||||
case CELL_GCM_PRIMITIVE_TRIANGLE_FAN:
|
||||
case CELL_GCM_PRIMITIVE_TRIANGLE_FAN: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
|
||||
case CELL_GCM_PRIMITIVE_QUADS: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
|
||||
|
||||
case CELL_GCM_PRIMITIVE_QUAD_STRIP:
|
||||
case CELL_GCM_PRIMITIVE_QUAD_STRIP: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
|
||||
case CELL_GCM_PRIMITIVE_POLYGON: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
|
||||
}
|
||||
unreachable("Wrong draw mode");
|
||||
unreachable("Unimplemented draw mode used %x, please report this to a developer.", draw_mode);
|
||||
}
|
||||
|
||||
D3D12_PRIMITIVE_TOPOLOGY_TYPE get_primitive_topology_type(u8 draw_mode) noexcept
|
||||
{
|
||||
switch (draw_mode)
|
||||
{
|
||||
case CELL_GCM_PRIMITIVE_POINTS: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT;
|
||||
case CELL_GCM_PRIMITIVE_LINES:
|
||||
case CELL_GCM_PRIMITIVE_LINE_LOOP:
|
||||
case CELL_GCM_PRIMITIVE_LINES: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE;
|
||||
case CELL_GCM_PRIMITIVE_LINE_STRIP: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE;
|
||||
case CELL_GCM_PRIMITIVE_TRIANGLES:
|
||||
case CELL_GCM_PRIMITIVE_TRIANGLE_STRIP:
|
||||
case CELL_GCM_PRIMITIVE_TRIANGLES: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
|
||||
case CELL_GCM_PRIMITIVE_TRIANGLE_STRIP: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
|
||||
case CELL_GCM_PRIMITIVE_TRIANGLE_FAN: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
|
||||
case CELL_GCM_PRIMITIVE_QUADS:
|
||||
// unsupported
|
||||
case CELL_GCM_PRIMITIVE_QUAD_STRIP:
|
||||
case CELL_GCM_PRIMITIVE_QUADS: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
|
||||
case CELL_GCM_PRIMITIVE_QUAD_STRIP: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
|
||||
case CELL_GCM_PRIMITIVE_POLYGON: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
|
||||
case CELL_GCM_PRIMITIVE_LINE_LOOP:
|
||||
unreachable("Unsupported draw mode used %x, please report this to a developer.", draw_mode);
|
||||
}
|
||||
unreachable("Wrong draw mode");
|
||||
unreachable("Unimplemented draw mode used %x, please report this to a developer.", draw_mode);
|
||||
}
|
||||
|
||||
DXGI_FORMAT get_color_surface_format(u8 format) noexcept
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case CELL_GCM_SURFACE_R5G6B5: return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
case CELL_GCM_SURFACE_R5G6B5: return DXGI_FORMAT_B5G6R5_UNORM;
|
||||
case CELL_GCM_SURFACE_A8R8G8B8: return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
case CELL_GCM_SURFACE_F_W16Z16Y16X16: return DXGI_FORMAT_R16G16B16A16_FLOAT;
|
||||
case CELL_GCM_SURFACE_F_X32: return DXGI_FORMAT_R32_FLOAT;
|
||||
}
|
||||
unreachable("Wrong color surface format");
|
||||
unreachable("Unimplemented color surface format used %x, please report this to a developer.", format);
|
||||
}
|
||||
|
||||
DXGI_FORMAT get_depth_stencil_surface_format(u8 format) noexcept
|
||||
|
@ -346,7 +317,7 @@ DXGI_FORMAT get_depth_stencil_surface_format(u8 format) noexcept
|
|||
case CELL_GCM_SURFACE_Z16: return DXGI_FORMAT_D16_UNORM;
|
||||
case CELL_GCM_SURFACE_Z24S8: return DXGI_FORMAT_D24_UNORM_S8_UINT;
|
||||
}
|
||||
unreachable("Wrong depth stencil surface format");
|
||||
unreachable("Unimplemented depth stencil surface format used %x, please report this to a developer.", format);
|
||||
}
|
||||
|
||||
DXGI_FORMAT get_depth_stencil_surface_clear_format(u8 format) noexcept
|
||||
|
@ -356,7 +327,7 @@ DXGI_FORMAT get_depth_stencil_surface_clear_format(u8 format) noexcept
|
|||
case CELL_GCM_SURFACE_Z16: return DXGI_FORMAT_D16_UNORM;
|
||||
case CELL_GCM_SURFACE_Z24S8: return DXGI_FORMAT_D24_UNORM_S8_UINT;
|
||||
}
|
||||
unreachable("Wrong depth stencil surface format");
|
||||
unreachable("Unimplemented depth stencil surface format used %x, please report this to a developer.", format);
|
||||
}
|
||||
|
||||
DXGI_FORMAT get_depth_stencil_typeless_surface_format(u8 format) noexcept
|
||||
|
@ -366,7 +337,7 @@ DXGI_FORMAT get_depth_stencil_typeless_surface_format(u8 format) noexcept
|
|||
case CELL_GCM_SURFACE_Z16: return DXGI_FORMAT_R16_TYPELESS;
|
||||
case CELL_GCM_SURFACE_Z24S8: return DXGI_FORMAT_R24G8_TYPELESS;
|
||||
}
|
||||
unreachable("Wrong depth stencil surface format");
|
||||
unreachable("Unimplemented depth stencil surface format used %x, please report this to a developer.", format);
|
||||
}
|
||||
|
||||
DXGI_FORMAT get_depth_samplable_surface_format(u8 format) noexcept
|
||||
|
@ -376,7 +347,7 @@ DXGI_FORMAT get_depth_samplable_surface_format(u8 format) noexcept
|
|||
case CELL_GCM_SURFACE_Z16: return DXGI_FORMAT_R16_FLOAT;
|
||||
case CELL_GCM_SURFACE_Z24S8: return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
|
||||
}
|
||||
unreachable("Wrong depth stencil surface format");
|
||||
unreachable("Unimplemented depth stencil surface format used %x, please report this to a developer.", format);
|
||||
}
|
||||
|
||||
BOOL get_front_face_ccw(u32 set_front_face_value) noexcept
|
||||
|
@ -387,7 +358,7 @@ BOOL get_front_face_ccw(u32 set_front_face_value) noexcept
|
|||
case CELL_GCM_CW: return FALSE;
|
||||
case CELL_GCM_CCW: return TRUE;
|
||||
}
|
||||
unreachable("Wrong front face value");
|
||||
unreachable("Unimplemented front face value used %x, please report this to a developer.", set_front_face_value);
|
||||
}
|
||||
|
||||
DXGI_FORMAT get_index_type(u8 index_type) noexcept
|
||||
|
@ -397,7 +368,7 @@ DXGI_FORMAT get_index_type(u8 index_type) noexcept
|
|||
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16: return DXGI_FORMAT_R16_UINT;
|
||||
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32: return DXGI_FORMAT_R32_UINT;
|
||||
}
|
||||
unreachable("Wrong index type");
|
||||
unreachable("Unimplemented index type used %x, please report this to a developer.", index_type);
|
||||
}
|
||||
|
||||
DXGI_FORMAT get_vertex_attribute_format(u8 type, u8 size) noexcept
|
||||
|
@ -413,7 +384,7 @@ DXGI_FORMAT get_vertex_attribute_format(u8 type, u8 size) noexcept
|
|||
case 3: return DXGI_FORMAT_R16G16B16A16_SNORM; // No 3 channel type
|
||||
case 4: return DXGI_FORMAT_R16G16B16A16_SNORM;
|
||||
}
|
||||
unreachable("Wrong type size");
|
||||
unreachable("Unimplemented type size used %x, please report this to a developer.", size);
|
||||
}
|
||||
case CELL_GCM_VERTEX_F:
|
||||
{
|
||||
|
@ -424,7 +395,7 @@ DXGI_FORMAT get_vertex_attribute_format(u8 type, u8 size) noexcept
|
|||
case 3: return DXGI_FORMAT_R32G32B32_FLOAT;
|
||||
case 4: return DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||
}
|
||||
unreachable("Wrong type size");
|
||||
unreachable("Unimplemented type size used %x, please report this to a developer.", size);
|
||||
}
|
||||
case CELL_GCM_VERTEX_SF:
|
||||
{
|
||||
|
@ -435,7 +406,7 @@ DXGI_FORMAT get_vertex_attribute_format(u8 type, u8 size) noexcept
|
|||
case 3: return DXGI_FORMAT_R16G16B16A16_FLOAT; // No 3 channel type
|
||||
case 4: return DXGI_FORMAT_R16G16B16A16_FLOAT;
|
||||
}
|
||||
unreachable("Wrong type size");
|
||||
unreachable("Unimplemented type size used %x, please report this to a developer.", size);
|
||||
}
|
||||
case CELL_GCM_VERTEX_UB:
|
||||
{
|
||||
|
@ -446,7 +417,7 @@ DXGI_FORMAT get_vertex_attribute_format(u8 type, u8 size) noexcept
|
|||
case 3: return DXGI_FORMAT_R8G8B8A8_UNORM; // No 3 channel type
|
||||
case 4: return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
}
|
||||
unreachable("Wrong type size");
|
||||
unreachable("Unimplemented type size used %x, please report this to a developer.", size);
|
||||
}
|
||||
case CELL_GCM_VERTEX_S32K:
|
||||
{
|
||||
|
@ -457,7 +428,7 @@ DXGI_FORMAT get_vertex_attribute_format(u8 type, u8 size) noexcept
|
|||
case 3: return DXGI_FORMAT_R16G16B16A16_SINT; // No 3 channel type
|
||||
case 4: return DXGI_FORMAT_R16G16B16A16_SINT;
|
||||
}
|
||||
unreachable("Wrong type size");
|
||||
unreachable("Unimplemented type size used %x, please report this to a developer.", size);
|
||||
}
|
||||
case CELL_GCM_VERTEX_CMP:
|
||||
{
|
||||
|
@ -468,7 +439,7 @@ DXGI_FORMAT get_vertex_attribute_format(u8 type, u8 size) noexcept
|
|||
case 3: return DXGI_FORMAT_R32G32B32_FLOAT;
|
||||
case 4: return DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||
}
|
||||
unreachable("Wrong type size");
|
||||
unreachable("Unimplemented type size used %x, please report this to a developer.", size);
|
||||
}
|
||||
case CELL_GCM_VERTEX_UB256:
|
||||
{
|
||||
|
@ -479,10 +450,10 @@ DXGI_FORMAT get_vertex_attribute_format(u8 type, u8 size) noexcept
|
|||
case 3: return DXGI_FORMAT_R8G8B8A8_UINT; // No 3 channel type
|
||||
case 4: return DXGI_FORMAT_R8G8B8A8_UINT;
|
||||
}
|
||||
unreachable("Wrong type size");
|
||||
unreachable("Unimplemented type size used %x, please report this to a developer.", size);
|
||||
}
|
||||
}
|
||||
unreachable("Wrong type");
|
||||
unreachable("Unimplemented type used %x, please report this to a developer.", size);
|
||||
}
|
||||
|
||||
D3D12_RECT get_scissor(u32 horizontal, u32 vertical) noexcept
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
|
||||
D3D12FragmentDecompiler::D3D12FragmentDecompiler(u32 addr, u32& size, u32 ctrl) :
|
||||
FragmentProgramDecompiler(addr, size, ctrl)
|
||||
D3D12FragmentDecompiler::D3D12FragmentDecompiler(u32 addr, u32& size, u32 ctrl, const std::vector<texture_dimension> &texture_dimensions) :
|
||||
FragmentProgramDecompiler(addr, size, ctrl, texture_dimensions)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -88,10 +88,10 @@ void D3D12FragmentDecompiler::insertOutputs(std::stringstream & OS)
|
|||
OS << "{" << std::endl;
|
||||
const std::pair<std::string, std::string> table[] =
|
||||
{
|
||||
{ "ocol0", m_ctrl & 0x40 ? "r0" : "h0" },
|
||||
{ "ocol1", m_ctrl & 0x40 ? "r2" : "h4" },
|
||||
{ "ocol2", m_ctrl & 0x40 ? "r3" : "h6" },
|
||||
{ "ocol3", m_ctrl & 0x40 ? "r4" : "h8" },
|
||||
{ "ocol0", m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? "r0" : "h0" },
|
||||
{ "ocol1", m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? "r2" : "h4" },
|
||||
{ "ocol2", m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? "r3" : "h6" },
|
||||
{ "ocol3", m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? "r4" : "h8" },
|
||||
};
|
||||
|
||||
for (int i = 0; i < sizeof(table) / sizeof(*table); ++i)
|
||||
|
@ -99,6 +99,8 @@ void D3D12FragmentDecompiler::insertOutputs(std::stringstream & OS)
|
|||
if (m_parr.HasParam(PF_PARAM_NONE, "float4", table[i].second))
|
||||
OS << " " << "float4" << " " << table[i].first << " : SV_TARGET" << i << ";" << std::endl;
|
||||
}
|
||||
if (m_ctrl & CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT)
|
||||
OS << " float depth : SV_Depth;" << std::endl;
|
||||
OS << "};" << std::endl;
|
||||
}
|
||||
|
||||
|
@ -108,7 +110,7 @@ void D3D12FragmentDecompiler::insertConstants(std::stringstream & OS)
|
|||
OS << "{" << std::endl;
|
||||
for (ParamType PT : m_parr.params[PF_PARAM_UNIFORM])
|
||||
{
|
||||
if (PT.type == "sampler2D")
|
||||
if (PT.type == "sampler2D" || PT.type == "samplerCube")
|
||||
continue;
|
||||
for (ParamItem PI : PT.items)
|
||||
OS << " " << PT.type << " " << PI.name << ";" << std::endl;
|
||||
|
@ -117,13 +119,23 @@ void D3D12FragmentDecompiler::insertConstants(std::stringstream & OS)
|
|||
|
||||
for (ParamType PT : m_parr.params[PF_PARAM_UNIFORM])
|
||||
{
|
||||
if (PT.type != "sampler2D")
|
||||
continue;
|
||||
for (ParamItem PI : PT.items)
|
||||
if (PT.type == "sampler2D")
|
||||
{
|
||||
size_t textureIndex = atoi(PI.name.data() + 3);
|
||||
OS << "Texture2D " << PI.name << " : register(t" << textureIndex << ");" << std::endl;
|
||||
OS << "sampler " << PI.name << "sampler : register(s" << textureIndex << ");" << std::endl;
|
||||
for (ParamItem PI : PT.items)
|
||||
{
|
||||
size_t textureIndex = atoi(PI.name.data() + 3);
|
||||
OS << "Texture2D " << PI.name << " : register(t" << textureIndex << ");" << std::endl;
|
||||
OS << "sampler " << PI.name << "sampler : register(s" << textureIndex << ");" << std::endl;
|
||||
}
|
||||
}
|
||||
else if (PT.type == "samplerCube")
|
||||
{
|
||||
for (ParamItem PI : PT.items)
|
||||
{
|
||||
size_t textureIndex = atoi(PI.name.data() + 3);
|
||||
OS << "TextureCube " << PI.name << " : register(t" << textureIndex << ");" << std::endl;
|
||||
OS << "sampler " << PI.name << "sampler : register(s" << textureIndex << ");" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -166,19 +178,27 @@ void D3D12FragmentDecompiler::insertMainEnd(std::stringstream & OS)
|
|||
{
|
||||
const std::pair<std::string, std::string> table[] =
|
||||
{
|
||||
{ "ocol0", m_ctrl & 0x40 ? "r0" : "h0" },
|
||||
{ "ocol1", m_ctrl & 0x40 ? "r2" : "h4" },
|
||||
{ "ocol2", m_ctrl & 0x40 ? "r3" : "h6" },
|
||||
{ "ocol3", m_ctrl & 0x40 ? "r4" : "h8" },
|
||||
{ "ocol0", m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? "r0" : "h0" },
|
||||
{ "ocol1", m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? "r2" : "h4" },
|
||||
{ "ocol2", m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? "r3" : "h6" },
|
||||
{ "ocol3", m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? "r4" : "h8" },
|
||||
};
|
||||
|
||||
OS << " PixelOutput Out;" << std::endl;
|
||||
size_t num_output = 0;
|
||||
for (int i = 0; i < sizeof(table) / sizeof(*table); ++i)
|
||||
{
|
||||
if (m_parr.HasParam(PF_PARAM_NONE, "float4", table[i].second))
|
||||
{
|
||||
OS << " Out." << table[i].first << " = " << table[i].second << ";" << std::endl;
|
||||
num_output++;
|
||||
}
|
||||
}
|
||||
OS << " if (isAlphaTested && Out.ocol0.a <= alphaRef) discard;" << std::endl;
|
||||
if (m_ctrl & CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT)
|
||||
OS << " Out.depth = " << ((m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS) ? "r1.z;" : "h0.z;") << std::endl;
|
||||
// Shaders don't always output colors (for instance if they write to depth only)
|
||||
if (num_output > 0)
|
||||
OS << " if (isAlphaTested && Out.ocol0.a <= alphaRef) discard;" << std::endl;
|
||||
OS << " return Out;" << std::endl;
|
||||
OS << "}" << std::endl;
|
||||
}
|
||||
|
|
|
@ -20,5 +20,5 @@ protected:
|
|||
virtual void insertMainStart(std::stringstream &OS) override;
|
||||
virtual void insertMainEnd(std::stringstream &OS) override;
|
||||
public:
|
||||
D3D12FragmentDecompiler(u32 addr, u32& size, u32 ctrl);
|
||||
D3D12FragmentDecompiler(u32 addr, u32& size, u32 ctrl, const std::vector<texture_dimension> &texture_dimensions);
|
||||
};
|
||||
|
|
|
@ -56,6 +56,17 @@ bool D3D12GSRender::load_program()
|
|||
fragment_program.offset = shader_program & ~0x3;
|
||||
fragment_program.addr = rsx::get_address(fragment_program.offset, (shader_program & 0x3) - 1);
|
||||
fragment_program.ctrl = rsx::method_registers[NV4097_SET_SHADER_CONTROL];
|
||||
fragment_program.texture_dimensions.clear();
|
||||
|
||||
for (u32 i = 0; i < rsx::limits::textures_count; ++i)
|
||||
{
|
||||
if (!textures[i].enabled())
|
||||
fragment_program.texture_dimensions.push_back(texture_dimension::texture_dimension_2d);
|
||||
else if (textures[i].cubemap())
|
||||
fragment_program.texture_dimensions.push_back(texture_dimension::texture_dimension_cubemap);
|
||||
else
|
||||
fragment_program.texture_dimensions.push_back(texture_dimension::texture_dimension_2d);
|
||||
}
|
||||
|
||||
D3D12PipelineProperties prop = {};
|
||||
prop.Topology = get_primitive_topology_type(draw_mode);
|
||||
|
|
|
@ -147,7 +147,7 @@ struct D3D12Traits
|
|||
static
|
||||
void RecompileFragmentProgram(RSXFragmentProgram *RSXFP, FragmentProgramData& fragmentProgramData, size_t ID)
|
||||
{
|
||||
D3D12FragmentDecompiler FS(RSXFP->addr, RSXFP->size, RSXFP->ctrl);
|
||||
D3D12FragmentDecompiler FS(RSXFP->addr, RSXFP->size, RSXFP->ctrl, RSXFP->texture_dimensions);
|
||||
const std::string &shader = FS.Decompile();
|
||||
fragmentProgramData.Compile(shader, Shader::SHADER_TYPE::SHADER_TYPE_FRAGMENT);
|
||||
fragmentProgramData.m_textureCount = 0;
|
||||
|
@ -155,7 +155,7 @@ struct D3D12Traits
|
|||
{
|
||||
for (const ParamItem PI : PT.items)
|
||||
{
|
||||
if (PT.type == "sampler2D")
|
||||
if (PT.type == "sampler2D" || PT.type == "samplerCube")
|
||||
{
|
||||
size_t texture_unit = atoi(PI.name.c_str() + 3);
|
||||
fragmentProgramData.m_textureCount = std::max(texture_unit + 1, fragmentProgramData.m_textureCount);
|
||||
|
|
|
@ -375,6 +375,9 @@ namespace
|
|||
size_t row_pitch;
|
||||
switch (color_surface_format)
|
||||
{
|
||||
case CELL_GCM_SURFACE_R5G6B5:
|
||||
row_pitch = align(clip_w * 2, 256);
|
||||
break;
|
||||
case CELL_GCM_SURFACE_A8R8G8B8:
|
||||
row_pitch = align(clip_w * 4, 256);
|
||||
break;
|
||||
|
@ -571,6 +574,10 @@ void D3D12GSRender::copy_render_target_to_dma_location()
|
|||
size_t srcPitch, dstPitch;
|
||||
switch (m_surface.color_format)
|
||||
{
|
||||
case CELL_GCM_SURFACE_R5G6B5:
|
||||
srcPitch = align(clip_w * 2, 256);
|
||||
dstPitch = clip_w * 2;
|
||||
break;
|
||||
case CELL_GCM_SURFACE_A8R8G8B8:
|
||||
srcPitch = align(clip_w * 4, 256);
|
||||
dstPitch = clip_w * 4;
|
||||
|
@ -617,6 +624,10 @@ void D3D12GSRender::copy_render_targets_to_memory(void *buffer, u8 rtt)
|
|||
size_t srcPitch, dstPitch;
|
||||
switch (m_surface.color_format)
|
||||
{
|
||||
case CELL_GCM_SURFACE_R5G6B5:
|
||||
srcPitch = align(clip_w * 2, 256);
|
||||
dstPitch = clip_w * 2;
|
||||
break;
|
||||
case CELL_GCM_SURFACE_A8R8G8B8:
|
||||
srcPitch = align(clip_w * 4, 256);
|
||||
dstPitch = clip_w * 4;
|
||||
|
|
|
@ -52,6 +52,8 @@ ComPtr<ID3D12Resource> upload_single_texture(
|
|||
data_heap<ID3D12Resource, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT> &texture_buffer_heap)
|
||||
{
|
||||
size_t w = texture.width(), h = texture.height();
|
||||
size_t depth = texture.depth();
|
||||
if (texture.cubemap()) depth *= 6;
|
||||
|
||||
int format = texture.format() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
|
||||
DXGI_FORMAT dxgi_format = get_texture_format(format);
|
||||
|
@ -70,7 +72,7 @@ ComPtr<ID3D12Resource> upload_single_texture(
|
|||
ThrowIfFailed(device->CreateCommittedResource(
|
||||
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
|
||||
D3D12_HEAP_FLAG_NONE,
|
||||
&CD3DX12_RESOURCE_DESC::Tex2D(dxgi_format, (UINT)w, (UINT)h, 1, texture.mipmap()),
|
||||
&CD3DX12_RESOURCE_DESC::Tex2D(dxgi_format, (UINT)w, (UINT)h, depth, texture.mipmap()),
|
||||
D3D12_RESOURCE_STATE_COPY_DEST,
|
||||
nullptr,
|
||||
IID_PPV_ARGS(result.GetAddressOf())
|
||||
|
@ -131,9 +133,38 @@ void D3D12GSRender::upload_and_bind_textures(ID3D12GraphicsCommandList *command_
|
|||
|
||||
for (u32 i = 0; i < rsx::limits::textures_count; ++i)
|
||||
{
|
||||
if (!textures[i].enabled()) continue;
|
||||
if (!textures[i].enabled())
|
||||
{
|
||||
// Now fill remaining texture slots with dummy texture/sampler
|
||||
|
||||
D3D12_SHADER_RESOURCE_VIEW_DESC shader_resource_view_desc = {};
|
||||
shader_resource_view_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||
shader_resource_view_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
shader_resource_view_desc.Texture2D.MipLevels = 1;
|
||||
shader_resource_view_desc.Shader4ComponentMapping = D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING(
|
||||
D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0,
|
||||
D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0,
|
||||
D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0,
|
||||
D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0);
|
||||
m_device->CreateShaderResourceView(m_dummy_texture, &shader_resource_view_desc,
|
||||
CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().descriptors_heap->GetCPUDescriptorHandleForHeapStart())
|
||||
.Offset((INT)descriptor_index + (INT)used_texture, g_descriptor_stride_srv_cbv_uav)
|
||||
);
|
||||
|
||||
D3D12_SAMPLER_DESC sampler_desc = {};
|
||||
sampler_desc.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT;
|
||||
sampler_desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||
sampler_desc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||
sampler_desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||
m_device->CreateSampler(&sampler_desc,
|
||||
CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().sampler_descriptor_heap[get_current_resource_storage().sampler_descriptors_heap_index]->GetCPUDescriptorHandleForHeapStart())
|
||||
.Offset((INT)get_current_resource_storage().current_sampler_index + (INT)used_texture, g_descriptor_stride_samplers)
|
||||
);
|
||||
used_texture++;
|
||||
continue;
|
||||
}
|
||||
size_t w = textures[i].width(), h = textures[i].height();
|
||||
if (!w || !h) continue;
|
||||
// if (!w || !h) continue;
|
||||
|
||||
const u32 texaddr = rsx::get_address(textures[i].offset(), textures[i].location());
|
||||
|
||||
|
@ -174,9 +205,17 @@ void D3D12GSRender::upload_and_bind_textures(ID3D12GraphicsCommandList *command_
|
|||
}
|
||||
|
||||
D3D12_SHADER_RESOURCE_VIEW_DESC shared_resource_view_desc = {};
|
||||
shared_resource_view_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||
if (textures[i].cubemap())
|
||||
{
|
||||
shared_resource_view_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE;
|
||||
shared_resource_view_desc.TextureCube.MipLevels = textures[i].mipmap();
|
||||
}
|
||||
else
|
||||
{
|
||||
shared_resource_view_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||
shared_resource_view_desc.Texture2D.MipLevels = textures[i].mipmap();
|
||||
}
|
||||
shared_resource_view_desc.Format = get_texture_format(format);
|
||||
shared_resource_view_desc.Texture2D.MipLevels = textures[i].mipmap();
|
||||
|
||||
switch (format)
|
||||
{
|
||||
|
@ -200,6 +239,7 @@ void D3D12GSRender::upload_and_bind_textures(ID3D12GraphicsCommandList *command_
|
|||
shared_resource_view_desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
||||
break;
|
||||
case CELL_GCM_TEXTURE_A8R8G8B8:
|
||||
case CELL_GCM_TEXTURE_D8R8G8B8:
|
||||
{
|
||||
|
||||
|
||||
|
@ -273,28 +313,6 @@ void D3D12GSRender::upload_and_bind_textures(ID3D12GraphicsCommandList *command_
|
|||
case CELL_GCM_TEXTURE_D1R5G5B5:
|
||||
shared_resource_view_desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
||||
break;
|
||||
case CELL_GCM_TEXTURE_D8R8G8B8:
|
||||
{
|
||||
const int RemapValue[4] =
|
||||
{
|
||||
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1,
|
||||
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2,
|
||||
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_3,
|
||||
D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_1
|
||||
};
|
||||
|
||||
u8 remap_a = textures[i].remap() & 0x3;
|
||||
u8 remap_r = (textures[i].remap() >> 2) & 0x3;
|
||||
u8 remap_g = (textures[i].remap() >> 4) & 0x3;
|
||||
u8 remap_b = (textures[i].remap() >> 6) & 0x3;
|
||||
|
||||
shared_resource_view_desc.Shader4ComponentMapping = D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING(
|
||||
RemapValue[remap_a],
|
||||
RemapValue[remap_r],
|
||||
RemapValue[remap_g],
|
||||
RemapValue[remap_b]);
|
||||
break;
|
||||
}
|
||||
case CELL_GCM_TEXTURE_Y16_X16_FLOAT:
|
||||
shared_resource_view_desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
||||
break;
|
||||
|
@ -322,32 +340,6 @@ void D3D12GSRender::upload_and_bind_textures(ID3D12GraphicsCommandList *command_
|
|||
used_texture++;
|
||||
}
|
||||
|
||||
// Now fill remaining texture slots with dummy texture/sampler
|
||||
for (; used_texture < texture_count; used_texture++)
|
||||
{
|
||||
D3D12_SHADER_RESOURCE_VIEW_DESC shader_resource_view_desc = {};
|
||||
shader_resource_view_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||
shader_resource_view_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
shader_resource_view_desc.Texture2D.MipLevels = 1;
|
||||
shader_resource_view_desc.Shader4ComponentMapping = D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING(
|
||||
D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0,
|
||||
D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0,
|
||||
D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0,
|
||||
D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0);
|
||||
m_device->CreateShaderResourceView(m_dummy_texture, &shader_resource_view_desc,
|
||||
CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().descriptors_heap->GetCPUDescriptorHandleForHeapStart())
|
||||
.Offset((INT)descriptor_index + (INT)used_texture, g_descriptor_stride_srv_cbv_uav)
|
||||
);
|
||||
|
||||
D3D12_SAMPLER_DESC sampler_desc = {};
|
||||
sampler_desc.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT;
|
||||
sampler_desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||
sampler_desc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||
sampler_desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||
m_device->CreateSampler(&sampler_desc,
|
||||
CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().sampler_descriptor_heap[get_current_resource_storage().sampler_descriptors_heap_index]->GetCPUDescriptorHandleForHeapStart())
|
||||
.Offset((INT)get_current_resource_storage().current_sampler_index + (INT)used_texture, g_descriptor_stride_samplers)
|
||||
);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -262,9 +262,9 @@ void D3D12GSRender::initConvertShader()
|
|||
p.second->Release();
|
||||
}
|
||||
|
||||
void unreachable_internal(const char *msg, const char *file, unsigned line)
|
||||
|
||||
void unreachable_internal()
|
||||
{
|
||||
LOG_ERROR(RSX, "file %s line %d : %s", file, line, msg);
|
||||
abort();
|
||||
#ifdef LLVM_BUILTIN_UNREACHABLE
|
||||
LLVM_BUILTIN_UNREACHABLE;
|
||||
|
|
|
@ -45,7 +45,14 @@
|
|||
# define LLVM_BUILTIN_UNREACHABLE __assume(false)
|
||||
#endif
|
||||
|
||||
LLVM_ATTRIBUTE_NORETURN void unreachable_internal(const char *msg = nullptr, const char *file = nullptr, unsigned line = 0);
|
||||
LLVM_ATTRIBUTE_NORETURN void unreachable_internal();
|
||||
|
||||
template<typename... Args>
|
||||
void unreachable_internal_verbose(const char *file, unsigned line, const Args &...args)
|
||||
{
|
||||
LOG_ERROR(RSX, "file %s line %d : %s", file, line, fmt::format(args...));
|
||||
unreachable_internal();
|
||||
}
|
||||
|
||||
/// Marks that the current location is not supposed to be reachable.
|
||||
/// In !NDEBUG builds, prints the message and location info to stderr.
|
||||
|
@ -56,8 +63,8 @@ LLVM_ATTRIBUTE_NORETURN void unreachable_internal(const char *msg = nullptr, con
|
|||
/// Use this instead of assert(0). It conveys intent more clearly and
|
||||
/// allows compilers to omit some unnecessary code.
|
||||
#ifndef NDEBUG
|
||||
#define unreachable(msg) \
|
||||
unreachable_internal(msg, __FILE__, __LINE__)
|
||||
#define unreachable(...) \
|
||||
unreachable_internal_verbose(__FILE__, __LINE__, ##__VA_ARGS__)
|
||||
//#elif defined(LLVM_BUILTIN_UNREACHABLE)
|
||||
//#define unreachable(msg) LLVM_BUILTIN_UNREACHABLE
|
||||
#else
|
||||
|
|
|
@ -454,6 +454,12 @@ enum
|
|||
CELL_GCM_FALSE = 0
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT = 0xe, ///< shader program exports the depth of the shaded fragment
|
||||
CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS = 0x40 ///< shader program exports 32 bits registers values (instead of 16 bits ones)
|
||||
};
|
||||
|
||||
// GCM Reports
|
||||
enum
|
||||
{
|
||||
|
|
|
@ -42,6 +42,12 @@ std::string getFunctionImpl(FUNCTION f)
|
|||
return "fract($0)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE:
|
||||
return "texture($t, $0.xy)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE_PROJ:
|
||||
return "textureProj($t, $0.xyz, $1.x)"; // Note: $1.x is bias
|
||||
case FUNCTION::FUNCTION_TEXTURE_CUBE_SAMPLE:
|
||||
return "texture($t, $0.xyz)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_CUBE_SAMPLE_PROJ:
|
||||
return "textureProj($t, $0.xyzw, $1.x)"; // Note: $1.x is bias
|
||||
case FUNCTION::FUNCTION_DFDX:
|
||||
return "dFdx($0)";
|
||||
case FUNCTION::FUNCTION_DFDY:
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "GLFragmentProgram.h"
|
||||
|
||||
#include "GLCommonDecompiler.h"
|
||||
#include "../GCM.h"
|
||||
|
||||
std::string GLFragmentDecompilerThread::getFloatTypeName(size_t elementCount)
|
||||
{
|
||||
|
@ -44,10 +45,10 @@ void GLFragmentDecompilerThread::insertOutputs(std::stringstream & OS)
|
|||
{
|
||||
const std::pair<std::string, std::string> table[] =
|
||||
{
|
||||
{ "ocol0", m_ctrl & 0x40 ? "r0" : "h0" },
|
||||
{ "ocol1", m_ctrl & 0x40 ? "r2" : "h4" },
|
||||
{ "ocol2", m_ctrl & 0x40 ? "r3" : "h6" },
|
||||
{ "ocol3", m_ctrl & 0x40 ? "r4" : "h8" },
|
||||
{ "ocol0", m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? "r0" : "h0" },
|
||||
{ "ocol1", m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? "r2" : "h4" },
|
||||
{ "ocol2", m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? "r3" : "h6" },
|
||||
{ "ocol3", m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? "r4" : "h8" },
|
||||
};
|
||||
|
||||
for (int i = 0; i < sizeof(table) / sizeof(*table); ++i)
|
||||
|
@ -103,10 +104,10 @@ void GLFragmentDecompilerThread::insertMainEnd(std::stringstream & OS)
|
|||
{
|
||||
const std::pair<std::string, std::string> table[] =
|
||||
{
|
||||
{ "ocol0", m_ctrl & 0x40 ? "r0" : "h0" },
|
||||
{ "ocol1", m_ctrl & 0x40 ? "r2" : "h4" },
|
||||
{ "ocol2", m_ctrl & 0x40 ? "r3" : "h6" },
|
||||
{ "ocol3", m_ctrl & 0x40 ? "r4" : "h8" },
|
||||
{ "ocol0", m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? "r0" : "h0" },
|
||||
{ "ocol1", m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? "r2" : "h4" },
|
||||
{ "ocol2", m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? "r3" : "h6" },
|
||||
{ "ocol3", m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? "r4" : "h8" },
|
||||
};
|
||||
|
||||
for (int i = 0; i < sizeof(table) / sizeof(*table); ++i)
|
||||
|
@ -115,6 +116,9 @@ void GLFragmentDecompilerThread::insertMainEnd(std::stringstream & OS)
|
|||
OS << " " << table[i].first << " = " << table[i].second << ";" << std::endl;
|
||||
}
|
||||
|
||||
if (m_ctrl & CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT)
|
||||
OS << ((m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS) ? "\tgl_FragDepth = r1.z;\n" : "\tgl_FragDepth = h0.z;\n") << std::endl;
|
||||
|
||||
OS << "}" << std::endl;
|
||||
}
|
||||
|
||||
|
@ -152,9 +156,9 @@ GLFragmentProgram::~GLFragmentProgram()
|
|||
// }
|
||||
//}
|
||||
|
||||
void GLFragmentProgram::Decompile(RSXFragmentProgram& prog)
|
||||
void GLFragmentProgram::Decompile(RSXFragmentProgram& prog, const std::vector<texture_dimension> &td)
|
||||
{
|
||||
GLFragmentDecompilerThread decompiler(shader, parr, prog.addr, prog.size, prog.ctrl);
|
||||
GLFragmentDecompilerThread decompiler(shader, parr, prog.addr, prog.size, prog.ctrl, td);
|
||||
decompiler.Task();
|
||||
for (const ParamType& PT : decompiler.m_parr.params[PF_PARAM_UNIFORM])
|
||||
{
|
||||
|
|
|
@ -9,8 +9,8 @@ struct GLFragmentDecompilerThread : public FragmentProgramDecompiler
|
|||
std::string& m_shader;
|
||||
ParamArray& m_parrDummy;
|
||||
public:
|
||||
GLFragmentDecompilerThread(std::string& shader, ParamArray& parr, u32 addr, u32& size, u32 ctrl)
|
||||
: FragmentProgramDecompiler(addr, size, ctrl)
|
||||
GLFragmentDecompilerThread(std::string& shader, ParamArray& parr, u32 addr, u32& size, u32 ctrl, const std::vector<texture_dimension> &texture_dimensions)
|
||||
: FragmentProgramDecompiler(addr, size, ctrl, texture_dimensions)
|
||||
, m_shader(shader)
|
||||
, m_parrDummy(parr)
|
||||
{
|
||||
|
@ -49,8 +49,9 @@ public:
|
|||
/**
|
||||
* Decompile a fragment shader located in the PS3's Memory. This function operates synchronously.
|
||||
* @param prog RSXShaderProgram specifying the location and size of the shader in memory
|
||||
* @param td texture dimensions of input textures
|
||||
*/
|
||||
void Decompile(RSXFragmentProgram& prog);
|
||||
void Decompile(RSXFragmentProgram& prog, const std::vector<texture_dimension> &td);
|
||||
|
||||
/** Compile the decompiled fragment shader into a format we can use with OpenGL. */
|
||||
void Compile();
|
||||
|
|
|
@ -1231,6 +1231,16 @@ bool GLGSRender::load_program()
|
|||
fragment_program.addr = rsx::get_address(fragment_program.offset, (shader_program & 0x3) - 1);
|
||||
fragment_program.ctrl = rsx::method_registers[NV4097_SET_SHADER_CONTROL];
|
||||
|
||||
for (u32 i = 0; i < rsx::limits::textures_count; ++i)
|
||||
{
|
||||
if (!textures[i].enabled())
|
||||
fragment_program.texture_dimensions.push_back(texture_dimension::texture_dimension_2d);
|
||||
else if (textures[i].cubemap())
|
||||
fragment_program.texture_dimensions.push_back(texture_dimension::texture_dimension_cubemap);
|
||||
else
|
||||
fragment_program.texture_dimensions.push_back(texture_dimension::texture_dimension_2d);
|
||||
}
|
||||
|
||||
__glcheck m_program = m_prog_buffer.getGraphicPipelineState(&vertex_program, &fragment_program, nullptr, nullptr);
|
||||
__glcheck m_program->use();
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ struct GLTraits
|
|||
static
|
||||
void RecompileFragmentProgram(RSXFragmentProgram *RSXFP, FragmentProgramData& fragmentProgramData, size_t ID)
|
||||
{
|
||||
fragmentProgramData.Decompile(*RSXFP);
|
||||
fragmentProgramData.Decompile(*RSXFP, RSXFP->texture_dimensions);
|
||||
fragmentProgramData.Compile();
|
||||
//checkForGlError("m_fragment_prog.Compile");
|
||||
|
||||
|
|
|
@ -204,12 +204,20 @@ static const std::string rsx_fp_op_names[] =
|
|||
"NULL", "BRK", "CAL", "IFE", "LOOP", "REP", "RET"
|
||||
};
|
||||
|
||||
enum class texture_dimension
|
||||
{
|
||||
texture_dimension_2d,
|
||||
texture_dimension_2d_array,
|
||||
texture_dimension_cubemap,
|
||||
};
|
||||
|
||||
struct RSXFragmentProgram
|
||||
{
|
||||
u32 size;
|
||||
u32 addr;
|
||||
u32 offset;
|
||||
u32 ctrl;
|
||||
std::vector<texture_dimension> texture_dimensions;
|
||||
|
||||
RSXFragmentProgram()
|
||||
: size(0)
|
||||
|
|
Loading…
Add table
Reference in a new issue