mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-29 22:20:48 +00:00
Common: Move generic upload texture code from d3d12
This commit is contained in:
parent
07e13b8613
commit
62d7bf2159
544
rpcs3/Emu/RSX/Common/TextureUtils.cpp
Normal file
544
rpcs3/Emu/RSX/Common/TextureUtils.cpp
Normal file
@ -0,0 +1,544 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
#include "Emu/Memory/vm.h"
|
||||||
|
#include "TextureUtils.h"
|
||||||
|
#include "../RSXThread.h"
|
||||||
|
#include "Utilities/Log.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define MAX2(a, b) ((a) > (b)) ? (a) : (b)
|
||||||
|
|
||||||
|
unsigned LinearToSwizzleAddress(unsigned x, unsigned y, unsigned z, unsigned log2_width, unsigned log2_height, unsigned log2_depth)
|
||||||
|
{
|
||||||
|
unsigned offset = 0;
|
||||||
|
unsigned shift_count = 0;
|
||||||
|
while (log2_width | log2_height | log2_depth) {
|
||||||
|
if (log2_width)
|
||||||
|
{
|
||||||
|
offset |= (x & 0x01) << shift_count;
|
||||||
|
x >>= 1;
|
||||||
|
++shift_count;
|
||||||
|
--log2_width;
|
||||||
|
}
|
||||||
|
if (log2_height)
|
||||||
|
{
|
||||||
|
offset |= (y & 0x01) << shift_count;
|
||||||
|
y >>= 1;
|
||||||
|
++shift_count;
|
||||||
|
--log2_height;
|
||||||
|
}
|
||||||
|
if (log2_depth)
|
||||||
|
{
|
||||||
|
offset |= (z & 0x01) << shift_count;
|
||||||
|
z >>= 1;
|
||||||
|
++shift_count;
|
||||||
|
--log2_depth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write data, assume src pixels are packed but not mipmaplevel
|
||||||
|
*/
|
||||||
|
inline std::vector<MipmapLevelInfo>
|
||||||
|
writeTexelsGeneric(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);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write data, assume src pixels are swizzled and but not mipmaplevel
|
||||||
|
*/
|
||||||
|
inline 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;
|
||||||
|
u32 log2width, log2height;
|
||||||
|
|
||||||
|
castedSrc = (u32*)src + offsetInSrc;
|
||||||
|
castedDst = (u32*)dst + offsetInDst;
|
||||||
|
|
||||||
|
log2width = (u32)(logf((float)currentWidth) / logf(2.f));
|
||||||
|
log2height = (u32)(logf((float)currentHeight) / logf(2.f));
|
||||||
|
|
||||||
|
for (int row = 0; row < currentHeight; row++)
|
||||||
|
for (int j = 0; j < currentWidth; j++)
|
||||||
|
castedDst[(row * rowPitch / 4) + j] = castedSrc[LinearToSwizzleAddress(j, row, 0, log2width, log2height, 0)];
|
||||||
|
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
inline 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
|
||||||
|
*/
|
||||||
|
inline std::vector<MipmapLevelInfo>
|
||||||
|
write16bTexelsSwizzled(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);
|
||||||
|
|
||||||
|
u16 *castedSrc, *castedDst;
|
||||||
|
u16 log2width, log2height;
|
||||||
|
|
||||||
|
castedSrc = (u16*)src + offsetInSrc;
|
||||||
|
castedDst = (u16*)dst + offsetInDst;
|
||||||
|
|
||||||
|
log2width = (u32)(logf((float)currentWidth) / logf(2.f));
|
||||||
|
log2height = (u32)(logf((float)currentHeight) / logf(2.f));
|
||||||
|
|
||||||
|
for (int row = 0; row < currentHeight; row++)
|
||||||
|
for (int j = 0; j < currentWidth; j++)
|
||||||
|
castedDst[(row * rowPitch / 2) + j] = castedSrc[LinearToSwizzleAddress(j, row, 0, log2width, log2height, 0)];
|
||||||
|
|
||||||
|
offsetInDst += currentHeight * rowPitch;
|
||||||
|
offsetInSrc += currentHeight * widthInBlock * blockSize;
|
||||||
|
currentHeight = MAX2(currentHeight / 2, 1);
|
||||||
|
currentWidth = MAX2(currentWidth / 2, 1);
|
||||||
|
}
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write 16 bytes pixel textures, assume src pixels are packed but not mipmaplevel
|
||||||
|
*/
|
||||||
|
inline 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++)
|
||||||
|
{
|
||||||
|
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++)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write 16 bytes pixel textures, assume src pixels are packed but not mipmaplevel
|
||||||
|
*/
|
||||||
|
inline std::vector<MipmapLevelInfo>
|
||||||
|
write16bX4TexelsGeneric(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++)
|
||||||
|
{
|
||||||
|
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 * 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);
|
||||||
|
}
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t getPlacedTextureStorageSpace(const RSXTexture &texture, size_t rowPitchAlignement)
|
||||||
|
{
|
||||||
|
size_t w = texture.GetWidth(), h = texture.GetHeight();
|
||||||
|
|
||||||
|
size_t blockSizeInByte, blockWidthInPixel, blockHeightInPixel;
|
||||||
|
int format = texture.GetFormat() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
|
||||||
|
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
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:
|
||||||
|
default:
|
||||||
|
LOG_ERROR(RSX, "Unimplemented Texture format : %x", format);
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_B8:
|
||||||
|
blockSizeInByte = 1;
|
||||||
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_A1R5G5B5:
|
||||||
|
blockSizeInByte = 2;
|
||||||
|
blockHeightInPixel = 1, blockWidthInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_A4R4G4B4:
|
||||||
|
blockSizeInByte = 2;
|
||||||
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_R5G6B5:
|
||||||
|
blockSizeInByte = 2;
|
||||||
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_A8R8G8B8:
|
||||||
|
blockSizeInByte = 4;
|
||||||
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_COMPRESSED_DXT1:
|
||||||
|
blockSizeInByte = 8;
|
||||||
|
blockWidthInPixel = 4, blockHeightInPixel = 4;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_COMPRESSED_DXT23:
|
||||||
|
blockSizeInByte = 16;
|
||||||
|
blockWidthInPixel = 4, blockHeightInPixel = 4;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_COMPRESSED_DXT45:
|
||||||
|
blockSizeInByte = 16;
|
||||||
|
blockWidthInPixel = 4, blockHeightInPixel = 4;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_G8B8:
|
||||||
|
blockSizeInByte = 2;
|
||||||
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_R6G5B5:
|
||||||
|
// Not native
|
||||||
|
blockSizeInByte = 4;
|
||||||
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_DEPTH24_D8:
|
||||||
|
blockSizeInByte = 4;
|
||||||
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT:
|
||||||
|
blockSizeInByte = 4;
|
||||||
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_DEPTH16:
|
||||||
|
blockSizeInByte = 2;
|
||||||
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_DEPTH16_FLOAT:
|
||||||
|
blockSizeInByte = 2;
|
||||||
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_X16:
|
||||||
|
blockSizeInByte = 2;
|
||||||
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_Y16_X16:
|
||||||
|
blockSizeInByte = 4;
|
||||||
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_R5G5B5A1:
|
||||||
|
blockSizeInByte = 2;
|
||||||
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT:
|
||||||
|
blockSizeInByte = 8;
|
||||||
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT:
|
||||||
|
blockSizeInByte = 16;
|
||||||
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_X32_FLOAT:
|
||||||
|
blockSizeInByte = 4;
|
||||||
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_D1R5G5B5:
|
||||||
|
blockSizeInByte = 2;
|
||||||
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_Y16_X16_FLOAT:
|
||||||
|
blockSizeInByte = 4;
|
||||||
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_D8R8G8B8:
|
||||||
|
blockSizeInByte = 4;
|
||||||
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8:
|
||||||
|
blockSizeInByte = 4;
|
||||||
|
blockWidthInPixel = 2, blockHeightInPixel = 2;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8:
|
||||||
|
blockSizeInByte = 4;
|
||||||
|
blockWidthInPixel = 2, blockHeightInPixel = 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t heightInBlocks = (h + blockHeightInPixel - 1) / blockHeightInPixel;
|
||||||
|
size_t widthInBlocks = (w + blockWidthInPixel - 1) / blockWidthInPixel;
|
||||||
|
|
||||||
|
size_t rowPitch = align(blockSizeInByte * widthInBlocks, rowPitchAlignement);
|
||||||
|
|
||||||
|
return rowPitch * heightInBlocks * 2; // * 2 for mipmap levels
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<MipmapLevelInfo> uploadPlacedTexture(const RSXTexture &texture, size_t rowPitchAlignement, void* textureData)
|
||||||
|
{
|
||||||
|
size_t w = texture.GetWidth(), h = texture.GetHeight();
|
||||||
|
|
||||||
|
int format = texture.GetFormat() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
|
||||||
|
|
||||||
|
size_t blockSizeInByte, blockWidthInPixel, blockHeightInPixel;
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
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:
|
||||||
|
default:
|
||||||
|
LOG_ERROR(RSX, "Unimplemented Texture format : %x", format);
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_B8:
|
||||||
|
blockSizeInByte = 1;
|
||||||
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_A1R5G5B5:
|
||||||
|
blockSizeInByte = 2;
|
||||||
|
blockHeightInPixel = 1, blockWidthInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_A4R4G4B4:
|
||||||
|
blockSizeInByte = 2;
|
||||||
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_R5G6B5:
|
||||||
|
blockSizeInByte = 2;
|
||||||
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_A8R8G8B8:
|
||||||
|
blockSizeInByte = 4;
|
||||||
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_COMPRESSED_DXT1:
|
||||||
|
blockSizeInByte = 8;
|
||||||
|
blockWidthInPixel = 4, blockHeightInPixel = 4;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_COMPRESSED_DXT23:
|
||||||
|
blockSizeInByte = 16;
|
||||||
|
blockWidthInPixel = 4, blockHeightInPixel = 4;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_COMPRESSED_DXT45:
|
||||||
|
blockSizeInByte = 16;
|
||||||
|
blockWidthInPixel = 4, blockHeightInPixel = 4;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_G8B8:
|
||||||
|
blockSizeInByte = 2;
|
||||||
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_R6G5B5:
|
||||||
|
// Not native
|
||||||
|
blockSizeInByte = 4;
|
||||||
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_DEPTH24_D8:
|
||||||
|
blockSizeInByte = 4;
|
||||||
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT:
|
||||||
|
blockSizeInByte = 4;
|
||||||
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_DEPTH16:
|
||||||
|
blockSizeInByte = 2;
|
||||||
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_DEPTH16_FLOAT:
|
||||||
|
blockSizeInByte = 2;
|
||||||
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_X16:
|
||||||
|
blockSizeInByte = 2;
|
||||||
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_Y16_X16:
|
||||||
|
blockSizeInByte = 4;
|
||||||
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_R5G5B5A1:
|
||||||
|
blockSizeInByte = 2;
|
||||||
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT:
|
||||||
|
blockSizeInByte = 8;
|
||||||
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT:
|
||||||
|
blockSizeInByte = 16;
|
||||||
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_X32_FLOAT:
|
||||||
|
blockSizeInByte = 4;
|
||||||
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_D1R5G5B5:
|
||||||
|
blockSizeInByte = 2;
|
||||||
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_Y16_X16_FLOAT:
|
||||||
|
blockSizeInByte = 4;
|
||||||
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_D8R8G8B8:
|
||||||
|
blockSizeInByte = 4;
|
||||||
|
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8:
|
||||||
|
blockSizeInByte = 4;
|
||||||
|
blockWidthInPixel = 2, blockHeightInPixel = 2;
|
||||||
|
break;
|
||||||
|
case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8:
|
||||||
|
blockSizeInByte = 4;
|
||||||
|
blockWidthInPixel = 2, blockHeightInPixel = 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t heightInBlocks = (h + blockHeightInPixel - 1) / blockHeightInPixel;
|
||||||
|
size_t widthInBlocks = (w + blockWidthInPixel - 1) / blockWidthInPixel;
|
||||||
|
|
||||||
|
std::vector<MipmapLevelInfo> mipInfos;
|
||||||
|
|
||||||
|
const u32 texaddr = GetAddress(texture.GetOffset(), texture.GetLocation());
|
||||||
|
auto pixels = vm::get_ptr<const u8>(texaddr);
|
||||||
|
bool is_swizzled = !(texture.GetFormat() & CELL_GCM_TEXTURE_LN);
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
case CELL_GCM_TEXTURE_A8R8G8B8:
|
||||||
|
if (is_swizzled)
|
||||||
|
return writeTexelsSwizzled((char*)pixels, (char*)textureData, w, h, 4, texture.GetMipmap());
|
||||||
|
else
|
||||||
|
return writeTexelsGeneric((char*)pixels, (char*)textureData, w, h, 4, texture.GetMipmap());
|
||||||
|
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.GetMipmap());
|
||||||
|
else
|
||||||
|
return write16bTexelsGeneric((char*)pixels, (char*)textureData, w, h, 2, texture.GetMipmap());
|
||||||
|
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT:
|
||||||
|
return write16bX4TexelsGeneric((char*)pixels, (char*)textureData, w, h, 8, texture.GetMipmap());
|
||||||
|
case CELL_GCM_TEXTURE_COMPRESSED_DXT1:
|
||||||
|
case CELL_GCM_TEXTURE_COMPRESSED_DXT23:
|
||||||
|
case CELL_GCM_TEXTURE_COMPRESSED_DXT45:
|
||||||
|
return writeCompressedTexel((char*)pixels, (char*)textureData, widthInBlocks, blockWidthInPixel, heightInBlocks, blockHeightInPixel, blockSizeInByte, texture.GetMipmap());
|
||||||
|
default:
|
||||||
|
return writeTexelsGeneric((char*)pixels, (char*)textureData, w, h, blockSizeInByte, texture.GetMipmap());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
26
rpcs3/Emu/RSX/Common/TextureUtils.h
Normal file
26
rpcs3/Emu/RSX/Common/TextureUtils.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "../RSXTexture.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
struct MipmapLevelInfo
|
||||||
|
{
|
||||||
|
size_t offset;
|
||||||
|
size_t width;
|
||||||
|
size_t height;
|
||||||
|
size_t rowPitch;
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned LinearToSwizzleAddress(unsigned x, unsigned y, unsigned z, unsigned log2_width, unsigned log2_height, unsigned log2_depth);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get size to store texture in a linear fashion.
|
||||||
|
* Storage is assumed to use a rowPitchAlignement boundary for every row of texture.
|
||||||
|
*/
|
||||||
|
size_t getPlacedTextureStorageSpace(const RSXTexture &texture, size_t rowPitchAlignement);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write texture data to textureData.
|
||||||
|
* Data are not packed, they are stored per rows using rowPitchAlignement.
|
||||||
|
* Similarly, offset for every mipmaplevel is aligned to rowPitchAlignement boundary.
|
||||||
|
*/
|
||||||
|
std::vector<MipmapLevelInfo> uploadPlacedTexture(const RSXTexture &texture, size_t rowPitchAlignement, void* textureData);
|
@ -2,40 +2,9 @@
|
|||||||
#if defined(DX12_SUPPORT)
|
#if defined(DX12_SUPPORT)
|
||||||
#include "D3D12GSRender.h"
|
#include "D3D12GSRender.h"
|
||||||
#include "d3dx12.h"
|
#include "d3dx12.h"
|
||||||
|
#include "../Common/TextureUtils.h"
|
||||||
// For clarity this code deals with texture but belongs to D3D12GSRender class
|
// For clarity this code deals with texture but belongs to D3D12GSRender class
|
||||||
|
|
||||||
|
|
||||||
static
|
|
||||||
u32 LinearToSwizzleAddress(u32 x, u32 y, u32 z, u32 log2_width, u32 log2_height, u32 log2_depth)
|
|
||||||
{
|
|
||||||
u32 offset = 0;
|
|
||||||
u32 shift_count = 0;
|
|
||||||
while (log2_width | log2_height | log2_depth) {
|
|
||||||
if (log2_width)
|
|
||||||
{
|
|
||||||
offset |= (x & 0x01) << shift_count;
|
|
||||||
x >>= 1;
|
|
||||||
++shift_count;
|
|
||||||
--log2_width;
|
|
||||||
}
|
|
||||||
if (log2_height)
|
|
||||||
{
|
|
||||||
offset |= (y & 0x01) << shift_count;
|
|
||||||
y >>= 1;
|
|
||||||
++shift_count;
|
|
||||||
--log2_height;
|
|
||||||
}
|
|
||||||
if (log2_depth)
|
|
||||||
{
|
|
||||||
offset |= (z & 0x01) << shift_count;
|
|
||||||
z >>= 1;
|
|
||||||
++shift_count;
|
|
||||||
--log2_depth;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
static
|
||||||
D3D12_COMPARISON_FUNC getSamplerCompFunc[] =
|
D3D12_COMPARISON_FUNC getSamplerCompFunc[] =
|
||||||
{
|
{
|
||||||
@ -151,239 +120,6 @@ D3D12_SAMPLER_DESC getSamplerDesc(const RSXTexture &texture)
|
|||||||
return samplerDesc;
|
return samplerDesc;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MipmapLevelInfo
|
|
||||||
{
|
|
||||||
size_t offset;
|
|
||||||
size_t width;
|
|
||||||
size_t height;
|
|
||||||
size_t rowPitch;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define MAX2(a, b) ((a) > (b)) ? (a) : (b)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write data, assume src pixels are packed but not mipmaplevel
|
|
||||||
*/
|
|
||||||
static std::vector<MipmapLevelInfo>
|
|
||||||
writeTexelsGeneric(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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write data, assume src pixels are swizzled and but not mipmaplevel
|
|
||||||
*/
|
|
||||||
static 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;
|
|
||||||
u32 log2width, log2height;
|
|
||||||
|
|
||||||
castedSrc = (u32*)src + offsetInSrc;
|
|
||||||
castedDst = (u32*)dst + offsetInDst;
|
|
||||||
|
|
||||||
log2width = (u32)(logf((float)currentWidth) / logf(2.f));
|
|
||||||
log2height = (u32)(logf((float)currentHeight) / logf(2.f));
|
|
||||||
|
|
||||||
for (int row = 0; row < currentHeight; row++)
|
|
||||||
for (int j = 0; j < currentWidth; j++)
|
|
||||||
castedDst[(row * rowPitch / 4) + j] = castedSrc[LinearToSwizzleAddress(j, row, 0, log2width, log2height, 0)];
|
|
||||||
|
|
||||||
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
|
|
||||||
*/
|
|
||||||
static 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
|
|
||||||
*/
|
|
||||||
static std::vector<MipmapLevelInfo>
|
|
||||||
write16bTexelsSwizzled(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);
|
|
||||||
|
|
||||||
u16 *castedSrc, *castedDst;
|
|
||||||
u16 log2width, log2height;
|
|
||||||
|
|
||||||
castedSrc = (u16*)src + offsetInSrc;
|
|
||||||
castedDst = (u16*)dst + offsetInDst;
|
|
||||||
|
|
||||||
log2width = (u32)(logf((float)currentWidth) / logf(2.f));
|
|
||||||
log2height = (u32)(logf((float)currentHeight) / logf(2.f));
|
|
||||||
|
|
||||||
for (int row = 0; row < currentHeight; row++)
|
|
||||||
for (int j = 0; j < currentWidth; j++)
|
|
||||||
castedDst[(row * rowPitch / 2) + j] = castedSrc[LinearToSwizzleAddress(j, row, 0, log2width, log2height, 0)];
|
|
||||||
|
|
||||||
offsetInDst += currentHeight * rowPitch;
|
|
||||||
offsetInSrc += currentHeight * widthInBlock * blockSize;
|
|
||||||
currentHeight = MAX2(currentHeight / 2, 1);
|
|
||||||
currentWidth = MAX2(currentWidth / 2, 1);
|
|
||||||
}
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write 16 bytes pixel textures, assume src pixels are packed but not mipmaplevel
|
|
||||||
*/
|
|
||||||
static 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++)
|
|
||||||
{
|
|
||||||
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++)
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write 16 bytes pixel textures, assume src pixels are packed but not mipmaplevel
|
|
||||||
*/
|
|
||||||
static std::vector<MipmapLevelInfo>
|
|
||||||
write16bX4TexelsGeneric(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++)
|
|
||||||
{
|
|
||||||
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 * 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);
|
|
||||||
}
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a texture residing in default heap and generate uploads commands in commandList,
|
* Create a texture residing in default heap and generate uploads commands in commandList,
|
||||||
@ -399,204 +135,17 @@ ID3D12Resource *uploadSingleTexture(
|
|||||||
ID3D12Resource *vramTexture;
|
ID3D12Resource *vramTexture;
|
||||||
size_t w = texture.GetWidth(), h = texture.GetHeight();
|
size_t w = texture.GetWidth(), h = texture.GetHeight();
|
||||||
|
|
||||||
size_t blockSizeInByte, blockWidthInPixel, blockHeightInPixel;
|
|
||||||
int format = texture.GetFormat() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
|
int format = texture.GetFormat() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
|
||||||
DXGI_FORMAT dxgiFormat = getTextureDXGIFormat(format);
|
DXGI_FORMAT dxgiFormat = getTextureDXGIFormat(format);
|
||||||
|
|
||||||
const u32 texaddr = GetAddress(texture.GetOffset(), texture.GetLocation());
|
size_t textureSize = getPlacedTextureStorageSpace(texture, 256);
|
||||||
|
|
||||||
bool is_swizzled = !(texture.GetFormat() & CELL_GCM_TEXTURE_LN);
|
|
||||||
size_t srcPitch;
|
|
||||||
switch (format)
|
|
||||||
{
|
|
||||||
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:
|
|
||||||
default:
|
|
||||||
LOG_ERROR(RSX, "Unimplemented Texture format : %x", format);
|
|
||||||
break;
|
|
||||||
case CELL_GCM_TEXTURE_B8:
|
|
||||||
blockSizeInByte = 1;
|
|
||||||
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
||||||
srcPitch = w;
|
|
||||||
break;
|
|
||||||
case CELL_GCM_TEXTURE_A1R5G5B5:
|
|
||||||
blockSizeInByte = 2;
|
|
||||||
blockHeightInPixel = 1, blockWidthInPixel = 1;
|
|
||||||
srcPitch = w * 2;
|
|
||||||
break;
|
|
||||||
case CELL_GCM_TEXTURE_A4R4G4B4:
|
|
||||||
blockSizeInByte = 2;
|
|
||||||
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
||||||
srcPitch = w * 2;
|
|
||||||
break;
|
|
||||||
case CELL_GCM_TEXTURE_R5G6B5:
|
|
||||||
blockSizeInByte = 2;
|
|
||||||
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
||||||
srcPitch = w * 2;
|
|
||||||
break;
|
|
||||||
case CELL_GCM_TEXTURE_A8R8G8B8:
|
|
||||||
blockSizeInByte = 4;
|
|
||||||
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
||||||
srcPitch = w * 4;
|
|
||||||
break;
|
|
||||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT1:
|
|
||||||
blockSizeInByte = 8;
|
|
||||||
blockWidthInPixel = 4, blockHeightInPixel = 4;
|
|
||||||
srcPitch = w * 2;
|
|
||||||
break;
|
|
||||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT23:
|
|
||||||
blockSizeInByte = 16;
|
|
||||||
blockWidthInPixel = 4, blockHeightInPixel = 4;
|
|
||||||
srcPitch = w * 4;
|
|
||||||
break;
|
|
||||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT45:
|
|
||||||
blockSizeInByte = 16;
|
|
||||||
blockWidthInPixel = 4, blockHeightInPixel = 4;
|
|
||||||
srcPitch = w * 4;
|
|
||||||
break;
|
|
||||||
case CELL_GCM_TEXTURE_G8B8:
|
|
||||||
blockSizeInByte = 2;
|
|
||||||
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
||||||
srcPitch = w * 2;
|
|
||||||
break;
|
|
||||||
case CELL_GCM_TEXTURE_R6G5B5:
|
|
||||||
// Not native
|
|
||||||
blockSizeInByte = 4;
|
|
||||||
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
||||||
srcPitch = w * 2;
|
|
||||||
break;
|
|
||||||
case CELL_GCM_TEXTURE_DEPTH24_D8:
|
|
||||||
blockSizeInByte = 4;
|
|
||||||
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
||||||
srcPitch = w * 4;
|
|
||||||
break;
|
|
||||||
case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT:
|
|
||||||
blockSizeInByte = 4;
|
|
||||||
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
||||||
srcPitch = w * 4;
|
|
||||||
break;
|
|
||||||
case CELL_GCM_TEXTURE_DEPTH16:
|
|
||||||
blockSizeInByte = 2;
|
|
||||||
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
||||||
srcPitch = w * 2;
|
|
||||||
break;
|
|
||||||
case CELL_GCM_TEXTURE_DEPTH16_FLOAT:
|
|
||||||
blockSizeInByte = 2;
|
|
||||||
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
||||||
srcPitch = w * 2;
|
|
||||||
break;
|
|
||||||
case CELL_GCM_TEXTURE_X16:
|
|
||||||
blockSizeInByte = 2;
|
|
||||||
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
||||||
srcPitch = w * 2;
|
|
||||||
break;
|
|
||||||
case CELL_GCM_TEXTURE_Y16_X16:
|
|
||||||
blockSizeInByte = 4;
|
|
||||||
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
||||||
srcPitch = w * 4;
|
|
||||||
break;
|
|
||||||
case CELL_GCM_TEXTURE_R5G5B5A1:
|
|
||||||
blockSizeInByte = 2;
|
|
||||||
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
||||||
srcPitch = w * 2;
|
|
||||||
break;
|
|
||||||
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT:
|
|
||||||
blockSizeInByte = 8;
|
|
||||||
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
||||||
srcPitch = w * 8;
|
|
||||||
break;
|
|
||||||
case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT:
|
|
||||||
blockSizeInByte = 16;
|
|
||||||
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
||||||
srcPitch = w * 16;
|
|
||||||
break;
|
|
||||||
case CELL_GCM_TEXTURE_X32_FLOAT:
|
|
||||||
blockSizeInByte = 4;
|
|
||||||
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
||||||
srcPitch = w * 4;
|
|
||||||
break;
|
|
||||||
case CELL_GCM_TEXTURE_D1R5G5B5:
|
|
||||||
blockSizeInByte = 2;
|
|
||||||
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
||||||
srcPitch = w * 2;
|
|
||||||
break;
|
|
||||||
case CELL_GCM_TEXTURE_Y16_X16_FLOAT:
|
|
||||||
blockSizeInByte = 4;
|
|
||||||
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
||||||
srcPitch = w * 4;
|
|
||||||
break;
|
|
||||||
case CELL_GCM_TEXTURE_D8R8G8B8:
|
|
||||||
blockSizeInByte = 4;
|
|
||||||
blockWidthInPixel = 1, blockHeightInPixel = 1;
|
|
||||||
srcPitch = w * 4;
|
|
||||||
break;
|
|
||||||
case CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8:
|
|
||||||
blockSizeInByte = 4;
|
|
||||||
blockWidthInPixel = 2, blockHeightInPixel = 2;
|
|
||||||
srcPitch = w * 4;
|
|
||||||
break;
|
|
||||||
case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8:
|
|
||||||
blockSizeInByte = 4;
|
|
||||||
blockWidthInPixel = 2, blockHeightInPixel = 2;
|
|
||||||
srcPitch = w * 4;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t heightInBlocks = (h + blockHeightInPixel - 1) / blockHeightInPixel;
|
|
||||||
size_t widthInBlocks = (w + blockWidthInPixel - 1) / blockWidthInPixel;
|
|
||||||
// Multiple of 256
|
|
||||||
size_t rowPitch = align(blockSizeInByte * widthInBlocks, 256);
|
|
||||||
|
|
||||||
size_t textureSize = rowPitch * heightInBlocks * 2; // * 4 for mipmap levels
|
|
||||||
assert(textureBuffersHeap.canAlloc(textureSize));
|
assert(textureBuffersHeap.canAlloc(textureSize));
|
||||||
size_t heapOffset = textureBuffersHeap.alloc(textureSize);
|
size_t heapOffset = textureBuffersHeap.alloc(textureSize);
|
||||||
|
|
||||||
auto pixels = vm::get_ptr<const u8>(texaddr);
|
|
||||||
void *buffer;
|
void *buffer;
|
||||||
ThrowIfFailed(textureBuffersHeap.m_heap->Map(0, &CD3DX12_RANGE(heapOffset, heapOffset + textureSize), &buffer));
|
ThrowIfFailed(textureBuffersHeap.m_heap->Map(0, &CD3DX12_RANGE(heapOffset, heapOffset + textureSize), &buffer));
|
||||||
void *textureData = (char*)buffer + heapOffset;
|
void *textureData = (char*)buffer + heapOffset;
|
||||||
std::vector<MipmapLevelInfo> mipInfos;
|
std::vector<MipmapLevelInfo> mipInfos = uploadPlacedTexture(texture, 256, textureData);
|
||||||
|
|
||||||
switch (format)
|
|
||||||
{
|
|
||||||
case CELL_GCM_TEXTURE_A8R8G8B8:
|
|
||||||
{
|
|
||||||
if (is_swizzled)
|
|
||||||
mipInfos = writeTexelsSwizzled((char*)pixels, (char*)textureData, w, h, 4, texture.GetMipmap());
|
|
||||||
else
|
|
||||||
mipInfos = writeTexelsGeneric((char*)pixels, (char*)textureData, w, h, 4, texture.GetMipmap());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CELL_GCM_TEXTURE_A1R5G5B5:
|
|
||||||
case CELL_GCM_TEXTURE_A4R4G4B4:
|
|
||||||
case CELL_GCM_TEXTURE_R5G6B5:
|
|
||||||
{
|
|
||||||
if (is_swizzled)
|
|
||||||
mipInfos = write16bTexelsSwizzled((char*)pixels, (char*)textureData, w, h, 2, texture.GetMipmap());
|
|
||||||
else
|
|
||||||
mipInfos = write16bTexelsGeneric((char*)pixels, (char*)textureData, w, h, 2, texture.GetMipmap());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT:
|
|
||||||
{
|
|
||||||
mipInfos = write16bX4TexelsGeneric((char*)pixels, (char*)textureData, w, h, 8, texture.GetMipmap());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT1:
|
|
||||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT23:
|
|
||||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT45:
|
|
||||||
{
|
|
||||||
mipInfos = writeCompressedTexel((char*)pixels, (char*)textureData, widthInBlocks, blockWidthInPixel, heightInBlocks, blockHeightInPixel, blockSizeInByte, texture.GetMipmap());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
mipInfos = writeTexelsGeneric((char*)pixels, (char*)textureData, w, h, blockSizeInByte, texture.GetMipmap());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
textureBuffersHeap.m_heap->Unmap(0, &CD3DX12_RANGE(heapOffset, heapOffset + textureSize));
|
textureBuffersHeap.m_heap->Unmap(0, &CD3DX12_RANGE(heapOffset, heapOffset + textureSize));
|
||||||
|
|
||||||
D3D12_RESOURCE_DESC texturedesc = CD3DX12_RESOURCE_DESC::Tex2D(dxgiFormat, (UINT)w, (UINT)h, 1, texture.GetMipmap());
|
D3D12_RESOURCE_DESC texturedesc = CD3DX12_RESOURCE_DESC::Tex2D(dxgiFormat, (UINT)w, (UINT)h, 1, texture.GetMipmap());
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include "Emu/Memory/Memory.h"
|
#include "Emu/Memory/Memory.h"
|
||||||
#include "Emu/System.h"
|
#include "Emu/System.h"
|
||||||
#include "GLGSRender.h"
|
#include "GLGSRender.h"
|
||||||
|
#include "../Common/TextureUtils.h"
|
||||||
|
|
||||||
#define CMD_DEBUG 0
|
#define CMD_DEBUG 0
|
||||||
#define DUMP_VERTEX_DATA 0
|
#define DUMP_VERTEX_DATA 0
|
||||||
@ -2152,34 +2153,4 @@ void GLGSRender::semaphorePGRAPHBackendRelease(u32 offset, u32 value)
|
|||||||
void GLGSRender::semaphorePFIFOAcquire(u32 offset, u32 value)
|
void GLGSRender::semaphorePFIFOAcquire(u32 offset, u32 value)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 LinearToSwizzleAddress(u32 x, u32 y, u32 z, u32 log2_width, u32 log2_height, u32 log2_depth)
|
|
||||||
{
|
|
||||||
u32 offset = 0;
|
|
||||||
u32 shift_count = 0;
|
|
||||||
while (log2_width | log2_height | log2_depth){
|
|
||||||
if (log2_width)
|
|
||||||
{
|
|
||||||
offset |= (x & 0x01) << shift_count;
|
|
||||||
x >>= 1;
|
|
||||||
++shift_count;
|
|
||||||
--log2_width;
|
|
||||||
}
|
|
||||||
if (log2_height)
|
|
||||||
{
|
|
||||||
offset |= (y & 0x01) << shift_count;
|
|
||||||
y >>= 1;
|
|
||||||
++shift_count;
|
|
||||||
--log2_height;
|
|
||||||
}
|
|
||||||
if (log2_depth)
|
|
||||||
{
|
|
||||||
offset |= (z & 0x01) << shift_count;
|
|
||||||
z >>= 1;
|
|
||||||
++shift_count;
|
|
||||||
--log2_depth;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return offset;
|
|
||||||
}
|
|
@ -18,7 +18,6 @@
|
|||||||
extern GLenum g_last_gl_error;
|
extern GLenum g_last_gl_error;
|
||||||
void printGlError(GLenum err, const char* situation);
|
void printGlError(GLenum err, const char* situation);
|
||||||
void printGlError(GLenum err, const std::string& situation);
|
void printGlError(GLenum err, const std::string& situation);
|
||||||
u32 LinearToSwizzleAddress(u32 x, u32 y, u32 z, u32 log2_width, u32 log2_height, u32 log2_depth);
|
|
||||||
|
|
||||||
|
|
||||||
class GLTexture
|
class GLTexture
|
||||||
|
@ -62,6 +62,7 @@
|
|||||||
<ClCompile Include="Emu\RSX\CgBinaryVertexProgram.cpp" />
|
<ClCompile Include="Emu\RSX\CgBinaryVertexProgram.cpp" />
|
||||||
<ClCompile Include="Emu\RSX\Common\FragmentProgramDecompiler.cpp" />
|
<ClCompile Include="Emu\RSX\Common\FragmentProgramDecompiler.cpp" />
|
||||||
<ClCompile Include="Emu\RSX\Common\ShaderParam.cpp" />
|
<ClCompile Include="Emu\RSX\Common\ShaderParam.cpp" />
|
||||||
|
<ClCompile Include="Emu\RSX\Common\TextureUtils.cpp" />
|
||||||
<ClCompile Include="Emu\RSX\Common\VertexProgramDecompiler.cpp" />
|
<ClCompile Include="Emu\RSX\Common\VertexProgramDecompiler.cpp" />
|
||||||
<ClCompile Include="Emu\RSX\D3D12\D3D12Buffer.cpp" />
|
<ClCompile Include="Emu\RSX\D3D12\D3D12Buffer.cpp" />
|
||||||
<ClCompile Include="Emu\RSX\D3D12\D3D12FragmentProgramDecompiler.cpp" />
|
<ClCompile Include="Emu\RSX\D3D12\D3D12FragmentProgramDecompiler.cpp" />
|
||||||
@ -532,6 +533,7 @@
|
|||||||
<ClInclude Include="Emu\RSX\Common\FragmentProgramDecompiler.h" />
|
<ClInclude Include="Emu\RSX\Common\FragmentProgramDecompiler.h" />
|
||||||
<ClInclude Include="Emu\RSX\Common\ProgramStateCache.h" />
|
<ClInclude Include="Emu\RSX\Common\ProgramStateCache.h" />
|
||||||
<ClInclude Include="Emu\RSX\Common\ShaderParam.h" />
|
<ClInclude Include="Emu\RSX\Common\ShaderParam.h" />
|
||||||
|
<ClInclude Include="Emu\RSX\Common\TextureManagement.h" />
|
||||||
<ClInclude Include="Emu\RSX\Common\VertexProgramDecompiler.h" />
|
<ClInclude Include="Emu\RSX\Common\VertexProgramDecompiler.h" />
|
||||||
<ClInclude Include="Emu\RSX\D3D12\D3D12.h" />
|
<ClInclude Include="Emu\RSX\D3D12\D3D12.h" />
|
||||||
<ClInclude Include="Emu\RSX\D3D12\D3D12Buffer.h" />
|
<ClInclude Include="Emu\RSX\D3D12\D3D12Buffer.h" />
|
||||||
|
@ -989,6 +989,9 @@
|
|||||||
<ClCompile Include="..\Utilities\SharedMutex.cpp">
|
<ClCompile Include="..\Utilities\SharedMutex.cpp">
|
||||||
<Filter>Utilities</Filter>
|
<Filter>Utilities</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="Emu\RSX\Common\TextureUtils.cpp">
|
||||||
|
<Filter>Emu\GPU\RSX\Common</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Crypto\aes.h">
|
<ClInclude Include="Crypto\aes.h">
|
||||||
@ -1882,5 +1885,8 @@
|
|||||||
<ClInclude Include="Emu\RSX\D3D12\d3dx12.h">
|
<ClInclude Include="Emu\RSX\D3D12\d3dx12.h">
|
||||||
<Filter>Emu\GPU\RSX\D3D12</Filter>
|
<Filter>Emu\GPU\RSX\D3D12</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="Emu\RSX\Common\TextureManagement.h">
|
||||||
|
<Filter>Emu\GPU\RSX\Common</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
Loading…
x
Reference in New Issue
Block a user