diff --git a/rsx_tests/cellGcmSetDrawIndexArray offset/expected.txt b/rsx_tests/cellGcmSetDrawIndexArray offset/expected.txt new file mode 100644 index 0000000..326c3c1 --- /dev/null +++ b/rsx_tests/cellGcmSetDrawIndexArray offset/expected.txt @@ -0,0 +1 @@ +sample finished. \ No newline at end of file diff --git a/rsx_tests/cellGcmSetDrawIndexArray offset/mainfp.cg b/rsx_tests/cellGcmSetDrawIndexArray offset/mainfp.cg new file mode 100644 index 0000000..0c24253 --- /dev/null +++ b/rsx_tests/cellGcmSetDrawIndexArray offset/mainfp.cg @@ -0,0 +1,20 @@ +struct v2fConnector +{ + float2 texCoord : TEXCOORD0; +}; + +struct f2fConnector +{ + float4 COL : COLOR; +}; + +f2fConnector main +( + v2fConnector v2f, + uniform texobj2D texture +) +{ + f2fConnector f2f; + f2f.COL = tex2D( texture, v2f.texCoord ); + return f2f; +} \ No newline at end of file diff --git a/rsx_tests/cellGcmSetDrawIndexArray offset/mainfp.fpo b/rsx_tests/cellGcmSetDrawIndexArray offset/mainfp.fpo new file mode 100644 index 0000000..4823365 Binary files /dev/null and b/rsx_tests/cellGcmSetDrawIndexArray offset/mainfp.fpo differ diff --git a/rsx_tests/cellGcmSetDrawIndexArray offset/mainrsxcrap.cpp b/rsx_tests/cellGcmSetDrawIndexArray offset/mainrsxcrap.cpp new file mode 100644 index 0000000..1d858fa --- /dev/null +++ b/rsx_tests/cellGcmSetDrawIndexArray offset/mainrsxcrap.cpp @@ -0,0 +1,359 @@ +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../rsx_header.h" + +#define SYS_APP_HOME "/app_home" + +#define VP_PROGRAM SYS_APP_HOME "/mainvp.vpo" +#define FP_PROGRAM SYS_APP_HOME "/mainfp.fpo" + +// Set priority and stack size for the primary PPU thread. +// Priority : 1000 +// Stack : 64KB +SYS_PROCESS_PARAM(1000, 0x10000) + +static sys_memory_t mem_id; +static sys_addr_t addr; + +//shader static data +static char *vpFile = NULL; +static CellCgbProgram vp; +static CellCgbVertexProgramConfiguration vpConf; +static const void *vpUcode = NULL; + +static char *fpFile = NULL; +static CellCgbProgram fp; +static CellCgbFragmentProgramConfiguration fpConf; + +static void *vucode, *fucode; +static u32 fpUcodeSize, vpUcodeSize; + +static inline void LoadModules() +{ + int ret = cellSysmoduleLoadModule( CELL_SYSMODULE_GCM_SYS ); + ret |= cellSysmoduleLoadModule( CELL_SYSMODULE_FS ); + ret |= cellSysmoduleLoadModule( CELL_SYSMODULE_RESC ); + ENSURE_OK(ret != CELL_OK && ret != CELL_SYSMODULE_ERROR_DUPLICATED); +} + +static rsxCommandCompiler c; +static CellGcmContextData& Gcm = c.c; + +// CellGcmContextCallback +int GcmCallback(struct CellGcmContextData *, uint32_t){} + +namespace loc +{ + enum + { + video = 0, + fragment, + vertex, + varray, + color1, + + __enum_max, + }; +}; + +void* gLocations[static_cast(loc::__enum_max)] = +{ + ptr_cast(0xC0200000), // Video + ptr_cast(0xC0900000), // FP shader + NULL, // VP shader + ptr_cast(0xC0A00000), // Vertex array 1 + ptr_cast(0xC0D00000), // Color buffer 1 + +}; + +struct Vertex4D{float i[4];}; +static Vertex4D Varray[1] = +{ + {.1, .2, .3, .4} +}; + + +#define CELL_GCM_FUNCTION_MACROS +#include "cell/gcm/gcm_function_macros.h" +#include "cell/gcm/gcm_methods.h" +#define CELL_GCM_THIS thisContext +#define CELL_GCM_CURRENT CELL_GCM_THIS->current +#define CELL_GCM_END CELL_GCM_THIS->end +#define CELL_GCM_CALLBACK CELL_GCM_THIS->callback + +void SetDrawIndexArray(CELL_GCM_ARGS(uint8_t mode, + uint32_t count, uint8_t type, uint8_t location, uint32_t indicies)) +{ + uint32_t startOffset; + uint32_t startIndex; + uint32_t misalignedIndexCount; + + startOffset = indicies; + + // need to compute the number of indexes from starting + // address to next 128-byte alignment + + // type == 32 + if(type == CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32) + misalignedIndexCount = (((startOffset + 127) & ~127) - startOffset) >> 2; + // type == 16 + else + misalignedIndexCount = (((startOffset + 127) & ~127) - startOffset) >> 1; + + CELL_GCM_RESERVE(7); + + CELL_GCM_METHOD_INVALIDATE_VERTEX_FILE(CELL_GCM_CURRENT); + + // begin + CELL_GCM_METHOD_SET_INDEX_ARRAY_OFFSET_FORMAT(CELL_GCM_CURRENT, + CELL_GCM_COMMAND_CAST(location), startOffset, CELL_GCM_COMMAND_CAST(type)); + CELL_GCM_METHOD_SET_BEGIN_END(CELL_GCM_CURRENT, + CELL_GCM_COMMAND_CAST(mode)); + + startIndex = 0; + // starting address of first index is not 128 byte aligned + // send the mis-aligned indices thus aligning the rest to 128 byte boundary + if (misalignedIndexCount && (misalignedIndexCount < count)) + { + uint32_t tmp = misalignedIndexCount-1; + CELL_GCM_RESERVE(2); + CELL_GCM_METHOD_DRAW_INDEX_ARRAY(CELL_GCM_CURRENT, startIndex,tmp); + count -= misalignedIndexCount; + startIndex += misalignedIndexCount; + } + + // avoid writing more then 2047(0x7ff) words per inc method (hw limit) + CELL_GCM_ASSERT(count && (count <= 0xfffff)); // hw limit + while(count > 0x7FF00) + { + CELL_GCM_RESERVE(1+CELL_GCM_MAX_METHOD_COUNT); + + count -= 0x7ff00; + CELL_GCM_CURRENT[0] = CELL_GCM_METHOD_NI(CELL_GCM_NV4097_DRAW_INDEX_ARRAY, CELL_GCM_MAX_METHOD_COUNT); + CELL_GCM_CURRENT += 1; + for (uint32_t lcount = CELL_GCM_MAX_METHOD_COUNT; lcount; --lcount) + { + CELL_GCM_CURRENT[0] = CELL_GCM_ENDIAN_SWAP(0xFF000000 | startIndex); + CELL_GCM_CURRENT += 1; + startIndex += 0x100; + } + } + + // round up count to 256(0x100) counts + uint32_t mcount = (count + 0xff)>>8; + + CELL_GCM_RESERVE(1+mcount); + + // [startIndex, startIndex+0xff] range in DRAW_INDEX_ARRAY + CELL_GCM_CURRENT[0] = CELL_GCM_METHOD_NI(CELL_GCM_NV4097_DRAW_INDEX_ARRAY, mcount); + CELL_GCM_CURRENT += 1; + while(count > 0x100) + { + count -= 0x100; + CELL_GCM_CURRENT[0] = CELL_GCM_ENDIAN_SWAP(0xFF000000 | startIndex); + CELL_GCM_CURRENT += 1; + startIndex += 0x100; + } + + // remainder indices + if(count) + { + --count; + CELL_GCM_CURRENT[0] = CELL_GCM_ENDIAN_SWAP((count << 24) | startIndex); + CELL_GCM_CURRENT += 1; + } + + CELL_GCM_RESERVE(2); + CELL_GCM_METHOD_SET_BEGIN_END(CELL_GCM_CURRENT, 0); + + CELL_GCM_DEBUG_FINISH(CELL_GCM_THIS); +} +int main() { + + LoadModules(); + sys_memory_allocate(0x1000000, 0x400, &addr); + + ENSURE_OK(cellGcmInit(1<<16, 0x100000, ptr_cast(addr))); + GcmMapEaIoAddress(addr + (1<<20), 1<<20, 15<<20); + + u8 id; cellGcmGetCurrentDisplayBufferId(&id); + cellGcmSetDisplayBuffer(id, 2<<20, 1280*4, 1280, 720); + cellGcmGetOffsetTable(&offsetTable); + + const CellGcmDisplayInfo* disp_info = cellGcmGetDisplayInfo(); + CellGcmControl* ctrl = cellGcmGetControlRegister(); + + // Wait for RSX to complete previous operation + wait_for_fifo(ctrl); + + // Place a jump into io address 1mb + *OffsetToAddr(ctrl->get) = (1<<20) | RSX_METHOD_NEW_JUMP_CMD; + sys_timer_usleep(40); + + // Load Shaders binaries and configs + { + u32 size = readFile(VP_PROGRAM,&vpFile); + ENSURE_NVAL(size, 0); + + ENSURE_OK(cellCgbRead(vpFile, size, &vp)); + + //retrieve the vertex hardware configuration + cellCgbGetVertexConfiguration(&vp,&vpConf); + + vpUcodeSize = cellCgbGetUCodeSize(&vp); + + memcpy(gLocations[loc::vertex] = ptr_cast(addr + (1<<15)), cellCgbGetUCode(&vp), vpUcodeSize); + } + + { + u32 size = readFile(FP_PROGRAM,&fpFile); + ENSURE_NVAL(size, 0); + + ENSURE_OK(cellCgbRead(fpFile, size, &fp)); + + //retrieve the fragment program configuration + cellCgbGetFragmentConfiguration(&fp,&fpConf); + + fpUcodeSize = cellCgbGetUCodeSize(&fp); + + memcpy(gLocations[loc::fragment], cellCgbGetUCode(&fp), fpUcodeSize); + } + + struct VertexData3D { float i[6];}; + +#define MINX -0.9f +#define MINY -0.9f +#define MAXX 0.9f +#define MAXY 0.9f + VertexData3D vertices[4] = { + // vertex tex coord + { MINX,MINY,0.f,0, 0.f, 0.f }, + { MAXX,MINY,0.f,0, 1.f, 0.f }, + { MINX,MAXY,0.f,0, 0.f, 1.f }, + { MAXX,MAXY,0.f,0, 1.f, 1.f } + }; +#undef MINX +#undef MINY +#undef MAXX +#undef MAXY + + // Initial vertex array + memcpy(gLocations[loc::varray], &vertices, sizeof(VertexData3D) * 4); + + cellGcmSetupContextData(&Gcm, ptr_caste(addr + (1<<20), u32), 0x10000, GcmCallback); + gcmLabel start = c.newLabel(); + + static const u32 colorOffset = 0x400000; + static const u32 depthOffset = 0x140000; + + CellGcmSurface surface; + surface.type = CELL_GCM_SURFACE_PITCH; + surface.antialias = CELL_GCM_SURFACE_CENTER_1; + surface.colorFormat = CELL_GCM_SURFACE_X8R8G8B8_O8R8G8B8; + surface.colorTarget = CELL_GCM_SURFACE_TARGET_0; + for (u32 i = 0, pitch = cellGcmGetTiledPitchSize(1280*4); i < 4; i++) + { + surface.colorLocation[i] = CELL_GCM_LOCATION_MAIN; + surface.colorOffset[i] = colorOffset; + surface.colorPitch[i] = pitch; + } + surface.depthFormat = CELL_GCM_SURFACE_Z16; + surface.depthLocation = CELL_GCM_LOCATION_MAIN; + surface.depthOffset = depthOffset; + surface.depthPitch = 1280*2; + surface.width = 1280; + surface.height = 720; + surface.x = 0; + surface.y = 0; + cellGcmSetSurface(&Gcm, &surface); + + // Texture cache + cellGcmSetInvalidateTextureCache(&Gcm, CELL_GCM_INVALIDATE_TEXTURE); + + cellGcmSetTextureControl(&Gcm, 0, CELL_GCM_TRUE, 12, 12, CELL_GCM_TEXTURE_MAX_ANISO_1); + + cellGcmSetTextureAddress( &Gcm, 0, + CELL_GCM_TEXTURE_CLAMP_TO_EDGE, + CELL_GCM_TEXTURE_CLAMP_TO_EDGE, + CELL_GCM_TEXTURE_CLAMP_TO_EDGE, + CELL_GCM_TEXTURE_UNSIGNED_REMAP_NORMAL, + CELL_GCM_TEXTURE_ZFUNC_LESS, 0); + cellGcmSetTextureFilter( &Gcm, 0, 0, + CELL_GCM_TEXTURE_NEAREST, + CELL_GCM_TEXTURE_NEAREST, CELL_GCM_TEXTURE_CONVOLUTION_QUINCUNX); + + cellGcmSetVertexDataBase(&Gcm, 0, 0xFFFFF); + + CellGcmTexture tex; + tex.location = CELL_GCM_LOCATION_MAIN; + tex.format = CELL_GCM_TEXTURE_A8R8G8B8 | CELL_GCM_TEXTURE_NR| CELL_GCM_TEXTURE_LN; + tex.dimension = CELL_GCM_TEXTURE_DIMENSION_2; + tex.pitch = 1280*4; + tex.height = 720; + tex.width = 720; + tex.offset = 1<<31; + tex.depth = 1; + tex.cubemap = CELL_GCM_FALSE; + tex.mipmap = 1; + tex.remap = CELL_GCM_TEXTURE_REMAP_REMAP << 14 | + CELL_GCM_TEXTURE_REMAP_REMAP << 12 | + CELL_GCM_TEXTURE_REMAP_REMAP << 10 | + CELL_GCM_TEXTURE_REMAP_REMAP << 8 | + CELL_GCM_TEXTURE_REMAP_FROM_B << 6 | + CELL_GCM_TEXTURE_REMAP_FROM_G << 4 | + CELL_GCM_TEXTURE_REMAP_FROM_R << 2 | + CELL_GCM_TEXTURE_REMAP_FROM_A; + + cellGcmSetTexture(&Gcm, 0, &tex); + + // State setting + cellGcmSetDepthFunc(&Gcm, CELL_GCM_ALWAYS); + cellGcmSetDepthTestEnable( &Gcm, CELL_GCM_TRUE ); + cellGcmSetShadeMode(&Gcm, CELL_GCM_SMOOTH); + + cellGcmSetVertexProgramLoad(&Gcm, &vpConf, gLocations[loc::vertex]); + fpConf.offset = 0x00900000; + cellGcmSetFragmentProgramLoad(&Gcm, &fpConf); + cellGcmSetVertexDataArray(&Gcm, 0 /*??*/, 0, sizeof(VertexData3D), 2, + CELL_GCM_VERTEX_F, CELL_GCM_LOCATION_LOCAL, + 0x0A00000u ); + cellGcmSetVertexDataArray(&Gcm, 1 /*??*/, 0, sizeof(VertexData3D), 2, + CELL_GCM_VERTEX_F, CELL_GCM_LOCATION_LOCAL, + 0x0A00000u + (sizeof(float) * 4) ); + + SetDrawIndexArray(&Gcm, CELL_GCM_PRIMITIVE_TRIANGLE_STRIP, 4,CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32,CELL_GCM_LOCATION_LOCAL,0xE1900000); + ptr_caste(0xc1900000, u32)[0] = 0; + ptr_caste(0xc1900000, u32)[1] = 1; + ptr_caste(0xc1900000, u32)[2] = 2; + ptr_caste(0xc1900000, u32)[3] = 3; + + cellGcmSetFlip(&Gcm, id); + cellGcmSetReferenceCommand(&Gcm, 2); + c.jmp(start); + + c.flush(); + sys_timer_usleep(100); + + while (load_vol(ctrl->ref) != 2) sys_timer_usleep(1000); + + printf("sample finished.\n"); + + return 0; +} \ No newline at end of file diff --git a/rsx_tests/cellGcmSetDrawIndexArray offset/mainrsxcrap.self b/rsx_tests/cellGcmSetDrawIndexArray offset/mainrsxcrap.self new file mode 100644 index 0000000..f4db5d6 Binary files /dev/null and b/rsx_tests/cellGcmSetDrawIndexArray offset/mainrsxcrap.self differ diff --git a/rsx_tests/cellGcmSetDrawIndexArray offset/mainvp.cg b/rsx_tests/cellGcmSetDrawIndexArray offset/mainvp.cg new file mode 100644 index 0000000..2908497 --- /dev/null +++ b/rsx_tests/cellGcmSetDrawIndexArray offset/mainvp.cg @@ -0,0 +1,19 @@ +struct a2vConnector +{ + float4 objCoord; + float2 texCoord; +}; + +struct v2fConnector +{ + float4 projCoord : POSITION; + float2 texCoord : TEXCOORD0; +}; + +v2fConnector main ( a2vConnector a2v) +{ + v2fConnector v2f; + v2f.projCoord = a2v.objCoord; + v2f.texCoord = a2v.texCoord; + return v2f; +} diff --git a/rsx_tests/cellGcmSetDrawIndexArray offset/mainvp.vpo b/rsx_tests/cellGcmSetDrawIndexArray offset/mainvp.vpo new file mode 100644 index 0000000..739def0 Binary files /dev/null and b/rsx_tests/cellGcmSetDrawIndexArray offset/mainvp.vpo differ