Merge pull request #1344 from vlj/d3d12

D3d12: Refactoring and fix
This commit is contained in:
Ivan 2015-12-16 22:59:43 +03:00
commit 14123d67e1
25 changed files with 422 additions and 398 deletions

View file

@ -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();
}
}

View file

@ -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;

View file

@ -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;

View file

@ -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();
};

View file

@ -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 {

View file

@ -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());
}
}

View file

@ -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)

View file

@ -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));

View file

@ -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:

View file

@ -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

View file

@ -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;
}

View file

@ -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);
};

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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
{

View file

@ -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:

View file

@ -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])
{

View file

@ -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();

View file

@ -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();

View file

@ -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");

View file

@ -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)