VertexInputLayout::VertexInputLayout(SceGxmShaderPatcher* shaderPatcher, Program* program, int numAttribs, const pgn::VertexAttribDesc attribDescs[], const int strides[]) { this->shaderPatcher = shaderPatcher; SceGxmVertexAttribute attribs[maxNumAttribs]; SceGxmVertexStream streams[maxNumAttribs]; int numActiveAttribs = 0; for(int i = 0; i < maxNumAttribs; i++) inputSlotToRegisterIndexMap[i] = -1; auto& attribRegisterIndexMap = program->attribRegisterIndexMap; for (int i = 0; i < numAttribs; i++) { const pgn::VertexAttribDesc* desc = &attribDescs[i]; auto it = attribRegisterIndexMap.find(desc->name); if (it != attribRegisterIndexMap.end()) { SceGxmVertexAttribute* attrib = &attribs[numActiveAttribs]; SceGxmVertexStream* stream = &streams[numActiveAttribs]; int registerIndex = it->second; attrib->streamIndex = registerIndex; attrib->offset = 0; attrib->format = formats[desc->format].format; attrib->componentCount = formats[desc->format].componentCount; attrib->regIndex = registerIndex; stream->stride = strides[i]; stream->indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT; inputSlotToRegisterIndexMap[i] = registerIndex; numActiveAttribs++; } } sceGxmShaderPatcherCreateVertexProgram(shaderPatcher, program->vertexProgramId, attribs, numActiveAttribs, streams, numActiveAttribs, &vertexProgram); }
int vita2d_init_advanced(unsigned int temp_pool_size) { int err; unsigned int i, x, y; UNUSED(err); if (vita2d_initialized) { DEBUG("libvita2d is already initialized!\n"); return 1; } SceGxmInitializeParams initializeParams; memset(&initializeParams, 0, sizeof(SceGxmInitializeParams)); initializeParams.flags = 0; initializeParams.displayQueueMaxPendingCount = DISPLAY_MAX_PENDING_SWAPS; initializeParams.displayQueueCallback = display_callback; initializeParams.displayQueueCallbackDataSize = sizeof(vita2d_display_data); initializeParams.parameterBufferSize = SCE_GXM_DEFAULT_PARAMETER_BUFFER_SIZE; err = sceGxmInitialize(&initializeParams); DEBUG("sceGxmInitialize(): 0x%08X\n", err); // allocate ring buffer memory using default sizes void *vdmRingBuffer = gpu_alloc( SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, SCE_GXM_DEFAULT_VDM_RING_BUFFER_SIZE, 4, SCE_GXM_MEMORY_ATTRIB_READ, &vdmRingBufferUid); void *vertexRingBuffer = gpu_alloc( SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, SCE_GXM_DEFAULT_VERTEX_RING_BUFFER_SIZE, 4, SCE_GXM_MEMORY_ATTRIB_READ, &vertexRingBufferUid); void *fragmentRingBuffer = gpu_alloc( SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, SCE_GXM_DEFAULT_FRAGMENT_RING_BUFFER_SIZE, 4, SCE_GXM_MEMORY_ATTRIB_READ, &fragmentRingBufferUid); unsigned int fragmentUsseRingBufferOffset; void *fragmentUsseRingBuffer = fragment_usse_alloc( SCE_GXM_DEFAULT_FRAGMENT_USSE_RING_BUFFER_SIZE, &fragmentUsseRingBufferUid, &fragmentUsseRingBufferOffset); memset(&contextParams, 0, sizeof(SceGxmContextParams)); contextParams.hostMem = malloc(SCE_GXM_MINIMUM_CONTEXT_HOST_MEM_SIZE); contextParams.hostMemSize = SCE_GXM_MINIMUM_CONTEXT_HOST_MEM_SIZE; contextParams.vdmRingBufferMem = vdmRingBuffer; contextParams.vdmRingBufferMemSize = SCE_GXM_DEFAULT_VDM_RING_BUFFER_SIZE; contextParams.vertexRingBufferMem = vertexRingBuffer; contextParams.vertexRingBufferMemSize = SCE_GXM_DEFAULT_VERTEX_RING_BUFFER_SIZE; contextParams.fragmentRingBufferMem = fragmentRingBuffer; contextParams.fragmentRingBufferMemSize = SCE_GXM_DEFAULT_FRAGMENT_RING_BUFFER_SIZE; contextParams.fragmentUsseRingBufferMem = fragmentUsseRingBuffer; contextParams.fragmentUsseRingBufferMemSize = SCE_GXM_DEFAULT_FRAGMENT_USSE_RING_BUFFER_SIZE; contextParams.fragmentUsseRingBufferOffset = fragmentUsseRingBufferOffset; err = sceGxmCreateContext(&contextParams, &_vita2d_context); DEBUG("sceGxmCreateContext(): 0x%08X\n", err); // set up parameters SceGxmRenderTargetParams renderTargetParams; memset(&renderTargetParams, 0, sizeof(SceGxmRenderTargetParams)); renderTargetParams.flags = 0; renderTargetParams.width = DISPLAY_WIDTH; renderTargetParams.height = DISPLAY_HEIGHT; renderTargetParams.scenesPerFrame = 1; renderTargetParams.multisampleMode = MSAA_MODE; renderTargetParams.multisampleLocations = 0; renderTargetParams.driverMemBlock = -1; // Invalid UID // create the render target err = sceGxmCreateRenderTarget(&renderTargetParams, &renderTarget); DEBUG("sceGxmCreateRenderTarget(): 0x%08X\n", err); // allocate memory and sync objects for display buffers for (i = 0; i < DISPLAY_BUFFER_COUNT; i++) { // allocate memory for display displayBufferData[i] = gpu_alloc( SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW, 4*DISPLAY_STRIDE_IN_PIXELS*DISPLAY_HEIGHT, SCE_GXM_COLOR_SURFACE_ALIGNMENT, SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE, &displayBufferUid[i]); // memset the buffer to black for (y = 0; y < DISPLAY_HEIGHT; y++) { unsigned int *row = (unsigned int *)displayBufferData[i] + y*DISPLAY_STRIDE_IN_PIXELS; for (x = 0; x < DISPLAY_WIDTH; x++) { row[x] = 0xff000000; } } // initialize a color surface for this display buffer err = sceGxmColorSurfaceInit( &displaySurface[i], DISPLAY_COLOR_FORMAT, SCE_GXM_COLOR_SURFACE_LINEAR, (MSAA_MODE == SCE_GXM_MULTISAMPLE_NONE) ? SCE_GXM_COLOR_SURFACE_SCALE_NONE : SCE_GXM_COLOR_SURFACE_SCALE_MSAA_DOWNSCALE, SCE_GXM_OUTPUT_REGISTER_SIZE_32BIT, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_STRIDE_IN_PIXELS, displayBufferData[i]); // create a sync object that we will associate with this buffer err = sceGxmSyncObjectCreate(&displayBufferSync[i]); } // compute the memory footprint of the depth buffer const unsigned int alignedWidth = ALIGN(DISPLAY_WIDTH, SCE_GXM_TILE_SIZEX); const unsigned int alignedHeight = ALIGN(DISPLAY_HEIGHT, SCE_GXM_TILE_SIZEY); unsigned int sampleCount = alignedWidth*alignedHeight; unsigned int depthStrideInSamples = alignedWidth; if (MSAA_MODE == SCE_GXM_MULTISAMPLE_4X) { // samples increase in X and Y sampleCount *= 4; depthStrideInSamples *= 2; } else if (MSAA_MODE == SCE_GXM_MULTISAMPLE_2X) { // samples increase in Y only sampleCount *= 2; } // allocate the depth buffer void *depthBufferData = gpu_alloc( SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, 4*sampleCount, SCE_GXM_DEPTHSTENCIL_SURFACE_ALIGNMENT, SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE, &depthBufferUid); // create the SceGxmDepthStencilSurface structure err = sceGxmDepthStencilSurfaceInit( &depthSurface, SCE_GXM_DEPTH_STENCIL_FORMAT_S8D24, SCE_GXM_DEPTH_STENCIL_SURFACE_TILED, depthStrideInSamples, depthBufferData, NULL); // set buffer sizes for this sample const unsigned int patcherBufferSize = 64*1024; const unsigned int patcherVertexUsseSize = 64*1024; const unsigned int patcherFragmentUsseSize = 64*1024; // allocate memory for buffers and USSE code void *patcherBuffer = gpu_alloc( SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, patcherBufferSize, 4, SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE, &patcherBufferUid); unsigned int patcherVertexUsseOffset; void *patcherVertexUsse = vertex_usse_alloc( patcherVertexUsseSize, &patcherVertexUsseUid, &patcherVertexUsseOffset); unsigned int patcherFragmentUsseOffset; void *patcherFragmentUsse = fragment_usse_alloc( patcherFragmentUsseSize, &patcherFragmentUsseUid, &patcherFragmentUsseOffset); // create a shader patcher SceGxmShaderPatcherParams patcherParams; memset(&patcherParams, 0, sizeof(SceGxmShaderPatcherParams)); patcherParams.userData = NULL; patcherParams.hostAllocCallback = &patcher_host_alloc; patcherParams.hostFreeCallback = &patcher_host_free; patcherParams.bufferAllocCallback = NULL; patcherParams.bufferFreeCallback = NULL; patcherParams.bufferMem = patcherBuffer; patcherParams.bufferMemSize = patcherBufferSize; patcherParams.vertexUsseAllocCallback = NULL; patcherParams.vertexUsseFreeCallback = NULL; patcherParams.vertexUsseMem = patcherVertexUsse; patcherParams.vertexUsseMemSize = patcherVertexUsseSize; patcherParams.vertexUsseOffset = patcherVertexUsseOffset; patcherParams.fragmentUsseAllocCallback = NULL; patcherParams.fragmentUsseFreeCallback = NULL; patcherParams.fragmentUsseMem = patcherFragmentUsse; patcherParams.fragmentUsseMemSize = patcherFragmentUsseSize; patcherParams.fragmentUsseOffset = patcherFragmentUsseOffset; err = sceGxmShaderPatcherCreate(&patcherParams, &shaderPatcher); DEBUG("sceGxmShaderPatcherCreate(): 0x%08X\n", err); // check the shaders err = sceGxmProgramCheck(clearVertexProgramGxp); DEBUG("clear_v sceGxmProgramCheck(): 0x%08X\n", err); err = sceGxmProgramCheck(clearFragmentProgramGxp); DEBUG("clear_f sceGxmProgramCheck(): 0x%08X\n", err); err = sceGxmProgramCheck(colorVertexProgramGxp); DEBUG("color_v sceGxmProgramCheck(): 0x%08X\n", err); err = sceGxmProgramCheck(colorFragmentProgramGxp); DEBUG("color_f sceGxmProgramCheck(): 0x%08X\n", err); err = sceGxmProgramCheck(textureVertexProgramGxp); DEBUG("texture_v sceGxmProgramCheck(): 0x%08X\n", err); err = sceGxmProgramCheck(textureFragmentProgramGxp); DEBUG("texture_f sceGxmProgramCheck(): 0x%08X\n", err); err = sceGxmProgramCheck(textureTintFragmentProgramGxp); DEBUG("texture_tint_f sceGxmProgramCheck(): 0x%08X\n", err); // register programs with the patcher err = sceGxmShaderPatcherRegisterProgram(shaderPatcher, clearVertexProgramGxp, &clearVertexProgramId); DEBUG("clear_v sceGxmShaderPatcherRegisterProgram(): 0x%08X\n", err); err = sceGxmShaderPatcherRegisterProgram(shaderPatcher, clearFragmentProgramGxp, &clearFragmentProgramId); DEBUG("clear_f sceGxmShaderPatcherRegisterProgram(): 0x%08X\n", err); err = sceGxmShaderPatcherRegisterProgram(shaderPatcher, colorVertexProgramGxp, &colorVertexProgramId); DEBUG("color_v sceGxmShaderPatcherRegisterProgram(): 0x%08X\n", err); err = sceGxmShaderPatcherRegisterProgram(shaderPatcher, colorFragmentProgramGxp, &colorFragmentProgramId); DEBUG("color_f sceGxmShaderPatcherRegisterProgram(): 0x%08X\n", err); err = sceGxmShaderPatcherRegisterProgram(shaderPatcher, textureVertexProgramGxp, &textureVertexProgramId); DEBUG("texture_v sceGxmShaderPatcherRegisterProgram(): 0x%08X\n", err); err = sceGxmShaderPatcherRegisterProgram(shaderPatcher, textureFragmentProgramGxp, &textureFragmentProgramId); DEBUG("texture_f sceGxmShaderPatcherRegisterProgram(): 0x%08X\n", err); err = sceGxmShaderPatcherRegisterProgram(shaderPatcher, textureTintFragmentProgramGxp, &textureTintFragmentProgramId); DEBUG("texture_tint_f sceGxmShaderPatcherRegisterProgram(): 0x%08X\n", err); // Fill SceGxmBlendInfo static const SceGxmBlendInfo blend_info = { .colorFunc = SCE_GXM_BLEND_FUNC_ADD, .alphaFunc = SCE_GXM_BLEND_FUNC_ADD, .colorSrc = SCE_GXM_BLEND_FACTOR_SRC_ALPHA, .colorDst = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, .alphaSrc = SCE_GXM_BLEND_FACTOR_ONE, .alphaDst = SCE_GXM_BLEND_FACTOR_ZERO, .colorMask = SCE_GXM_COLOR_MASK_ALL }; // get attributes by name to create vertex format bindings const SceGxmProgramParameter *paramClearPositionAttribute = sceGxmProgramFindParameterByName(clearVertexProgramGxp, "aPosition"); // create clear vertex format SceGxmVertexAttribute clearVertexAttributes[1]; SceGxmVertexStream clearVertexStreams[1]; clearVertexAttributes[0].streamIndex = 0; clearVertexAttributes[0].offset = 0; clearVertexAttributes[0].format = SCE_GXM_ATTRIBUTE_FORMAT_F32; clearVertexAttributes[0].componentCount = 2; clearVertexAttributes[0].regIndex = sceGxmProgramParameterGetResourceIndex(paramClearPositionAttribute); clearVertexStreams[0].stride = sizeof(vita2d_clear_vertex); clearVertexStreams[0].indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT; // create clear programs err = sceGxmShaderPatcherCreateVertexProgram( shaderPatcher, clearVertexProgramId, clearVertexAttributes, 1, clearVertexStreams, 1, &clearVertexProgram); DEBUG("clear sceGxmShaderPatcherCreateVertexProgram(): 0x%08X\n", err); err = sceGxmShaderPatcherCreateFragmentProgram( shaderPatcher, clearFragmentProgramId, SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4, MSAA_MODE, NULL, clearVertexProgramGxp, &clearFragmentProgram); DEBUG("clear sceGxmShaderPatcherCreateFragmentProgram(): 0x%08X\n", err); // create the clear triangle vertex/index data clearVertices = (vita2d_clear_vertex *)gpu_alloc( SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, 3*sizeof(vita2d_clear_vertex), 4, SCE_GXM_MEMORY_ATTRIB_READ, &clearVerticesUid); clearIndices = (uint16_t *)gpu_alloc( SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, 3*sizeof(uint16_t), 2, SCE_GXM_MEMORY_ATTRIB_READ, &clearIndicesUid); clearVertices[0].x = -1.0f; clearVertices[0].y = -1.0f; clearVertices[1].x = 3.0f; clearVertices[1].y = -1.0f; clearVertices[2].x = -1.0f; clearVertices[2].y = 3.0f; clearIndices[0] = 0; clearIndices[1] = 1; clearIndices[2] = 2; const SceGxmProgramParameter *paramColorPositionAttribute = sceGxmProgramFindParameterByName(colorVertexProgramGxp, "aPosition"); DEBUG("aPosition sceGxmProgramFindParameterByName(): %p\n", paramColorPositionAttribute); const SceGxmProgramParameter *paramColorColorAttribute = sceGxmProgramFindParameterByName(colorVertexProgramGxp, "aColor"); DEBUG("aColor sceGxmProgramFindParameterByName(): %p\n", paramColorColorAttribute); // create color vertex format SceGxmVertexAttribute colorVertexAttributes[2]; SceGxmVertexStream colorVertexStreams[1]; /* x,y,z: 3 float 32 bits */ colorVertexAttributes[0].streamIndex = 0; colorVertexAttributes[0].offset = 0; colorVertexAttributes[0].format = SCE_GXM_ATTRIBUTE_FORMAT_F32; colorVertexAttributes[0].componentCount = 3; // (x, y, z) colorVertexAttributes[0].regIndex = sceGxmProgramParameterGetResourceIndex(paramColorPositionAttribute); /* color: 4 unsigned char = 32 bits */ colorVertexAttributes[1].streamIndex = 0; colorVertexAttributes[1].offset = 12; // (x, y, z) * 4 = 12 bytes colorVertexAttributes[1].format = SCE_GXM_ATTRIBUTE_FORMAT_U8N; colorVertexAttributes[1].componentCount = 4; // (color) colorVertexAttributes[1].regIndex = sceGxmProgramParameterGetResourceIndex(paramColorColorAttribute); // 16 bit (short) indices colorVertexStreams[0].stride = sizeof(vita2d_color_vertex); colorVertexStreams[0].indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT; // create color shaders err = sceGxmShaderPatcherCreateVertexProgram( shaderPatcher, colorVertexProgramId, colorVertexAttributes, 2, colorVertexStreams, 1, &_vita2d_colorVertexProgram); DEBUG("color sceGxmShaderPatcherCreateVertexProgram(): 0x%08X\n", err); err = sceGxmShaderPatcherCreateFragmentProgram( shaderPatcher, colorFragmentProgramId, SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4, MSAA_MODE, &blend_info, colorVertexProgramGxp, &_vita2d_colorFragmentProgram); DEBUG("color sceGxmShaderPatcherCreateFragmentProgram(): 0x%08X\n", err); const SceGxmProgramParameter *paramTexturePositionAttribute = sceGxmProgramFindParameterByName(textureVertexProgramGxp, "aPosition"); DEBUG("aPosition sceGxmProgramFindParameterByName(): %p\n", paramTexturePositionAttribute); const SceGxmProgramParameter *paramTextureTexcoordAttribute = sceGxmProgramFindParameterByName(textureVertexProgramGxp, "aTexcoord"); DEBUG("aTexcoord sceGxmProgramFindParameterByName(): %p\n", paramTextureTexcoordAttribute); // create texture vertex format SceGxmVertexAttribute textureVertexAttributes[2]; SceGxmVertexStream textureVertexStreams[1]; /* x,y,z: 3 float 32 bits */ textureVertexAttributes[0].streamIndex = 0; textureVertexAttributes[0].offset = 0; textureVertexAttributes[0].format = SCE_GXM_ATTRIBUTE_FORMAT_F32; textureVertexAttributes[0].componentCount = 3; // (x, y, z) textureVertexAttributes[0].regIndex = sceGxmProgramParameterGetResourceIndex(paramTexturePositionAttribute); /* u,v: 2 floats 32 bits */ textureVertexAttributes[1].streamIndex = 0; textureVertexAttributes[1].offset = 12; // (x, y, z) * 4 = 12 bytes textureVertexAttributes[1].format = SCE_GXM_ATTRIBUTE_FORMAT_F32; textureVertexAttributes[1].componentCount = 2; // (u, v) textureVertexAttributes[1].regIndex = sceGxmProgramParameterGetResourceIndex(paramTextureTexcoordAttribute); // 16 bit (short) indices textureVertexStreams[0].stride = sizeof(vita2d_texture_vertex); textureVertexStreams[0].indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT; // create texture shaders err = sceGxmShaderPatcherCreateVertexProgram( shaderPatcher, textureVertexProgramId, textureVertexAttributes, 2, textureVertexStreams, 1, &_vita2d_textureVertexProgram); DEBUG("texture sceGxmShaderPatcherCreateVertexProgram(): 0x%08X\n", err); err = sceGxmShaderPatcherCreateFragmentProgram( shaderPatcher, textureFragmentProgramId, SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4, MSAA_MODE, &blend_info, textureVertexProgramGxp, &_vita2d_textureFragmentProgram); DEBUG("texture sceGxmShaderPatcherCreateFragmentProgram(): 0x%08X\n", err); err = sceGxmShaderPatcherCreateFragmentProgram( shaderPatcher, textureTintFragmentProgramId, SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4, MSAA_MODE, &blend_info, textureVertexProgramGxp, &_vita2d_textureTintFragmentProgram); DEBUG("texture_tint sceGxmShaderPatcherCreateFragmentProgram(): 0x%08X\n", err); // find vertex uniforms by name and cache parameter information _vita2d_clearClearColorParam = sceGxmProgramFindParameterByName(clearFragmentProgramGxp, "uClearColor"); DEBUG("_vita2d_clearClearColorParam sceGxmProgramFindParameterByName(): %p\n", _vita2d_clearClearColorParam); _vita2d_colorWvpParam = sceGxmProgramFindParameterByName(colorVertexProgramGxp, "wvp"); DEBUG("color wvp sceGxmProgramFindParameterByName(): %p\n", _vita2d_colorWvpParam); _vita2d_textureWvpParam = sceGxmProgramFindParameterByName(textureVertexProgramGxp, "wvp"); DEBUG("texture wvp sceGxmProgramFindParameterByName(): %p\n", _vita2d_textureWvpParam); _vita2d_textureTintColorParam = sceGxmProgramFindParameterByName(textureTintFragmentProgramGxp, "uTintColor"); DEBUG("texture wvp sceGxmProgramFindParameterByName(): %p\n", _vita2d_textureWvpParam); // Allocate memory for the memory pool pool_size = temp_pool_size; pool_addr = gpu_alloc( SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, pool_size, sizeof(void *), SCE_GXM_MEMORY_ATTRIB_READ, &poolUid); matrix_init_orthographic(_vita2d_ortho_matrix, 0.0f, DISPLAY_WIDTH, DISPLAY_HEIGHT, 0.0f, 0.0f, 1.0f); backBufferIndex = 0; frontBufferIndex = 0; vita2d_initialized = 1; return 1; }
static bool loadVertexShader_PSVita(PE::GameContext &ctx, const char *filename, const char *name, EPEVertexFormat format, Effect *pEffect, const SceGxmProgram *gxmProgram, SceGxmShaderPatcherId &out_programId, SceGxmVertexProgram *out_programs[] ) { PEString::generatePathname(ctx, filename, "Default", "GPUPrograms", PEString::s_buf, PEString::BUF_SIZE); PEINFO("PE: PROGRESS: loading shader: %s from %s\n", name, PEString::s_buf); if (strcmp("main", name)) { assert(!"Only shaders programs with name \"main()\" are supported"); } PSVitaRenderer *pPSVitaRenderer = static_cast<PSVitaRenderer *>(ctx.getGPUScreen()); SceGxmErrorCode err = sceGxmShaderPatcherRegisterProgram(pPSVitaRenderer->m_shaderPatcher, gxmProgram, &out_programId); PEASSERT(err == SCE_OK, "Error creating shader patcher id"); pEffect->m_externalPerTechniqueData.initVertexAttributeBindings(pEffect); // need these to assign to vertex buffer infos for (int iBufferLayout = 0; iBufferLayout < PEVertexFormatLayout_Count; ++iBufferLayout) { PEVertexBufferInfo &bufferLayoutInfo = VertexBufferGPUManager::Instance()->m_vertexBufferInfos[iBufferLayout]; EPEVertexFormat iFormat = VertexBufferGPUManager::Instance()->m_layoutToFormatMap[iBufferLayout]; if (format == iFormat) { for (int iAttr = 0; iAttr < bufferLayoutInfo.m_apiVertexAttributes.m_size; ++iAttr) { bufferLayoutInfo.m_apiVertexAttributes[iAttr].regIndex = -1; } // set bindings in buffers infos, by going through raw api-abstract data of buffer infos // and figuring out which binding to use for destination api info int iApiAttrIndex = 0; for (int iBuf = 0; iBuf < bufferLayoutInfo.m_bufferInfos.m_size; ++iBuf) { PEVertexAttributeBufferInfo &bufInfo = bufferLayoutInfo.m_bufferInfos[iBuf]; for (int iSem = 0; iSem < bufInfo.m_numAttributes; ++iSem) { PEVertexAttributeInfo &attrInfo = bufInfo.m_attributeInfos[iSem]; // this does something like // for detailed_mesh's vertex attribute position, in this shader position is bound result of to sceGxmProgramParameterGetResourceIndex GLSLAttributeLocations::ApiBindingType resBinding = sceGxmProgramFindParameterBySemantic(gxmProgram, (SceGxmParameterSemantic)(attrInfo.m_apiSemantic), attrInfo.m_apiSemanticOrder); PEASSERT(resBinding && (sceGxmProgramParameterGetCategory(resBinding) == SCE_GXM_PARAMETER_CATEGORY_ATTRIBUTE), "Problem finding vertex attribute"); uint32_t regIndex = sceGxmProgramParameterGetResourceIndex(resBinding); PEASSERT(regIndex != -1, "Invalid Index\n"); bufferLayoutInfo.m_apiVertexAttributes[iApiAttrIndex].regIndex = regIndex; ++iApiAttrIndex; } } SceGxmVertexAttribute *pVertexAttribute = bufferLayoutInfo.m_apiVertexAttributes.getFirstPtr(); int numVertexAttrs = bufferLayoutInfo.m_apiVertexAttributes.m_size; SceGxmVertexStream *pVertexStream = bufferLayoutInfo.m_apiVertexStreams.getFirstPtr(); int numStreams = bufferLayoutInfo.m_apiVertexStreams.m_size; err = sceGxmShaderPatcherCreateVertexProgram( pPSVitaRenderer->m_shaderPatcher, out_programId, pVertexAttribute, numVertexAttrs, pVertexStream, numStreams, &out_programs[iBufferLayout]); checkErrCode(err); PEASSERT(err == SCE_OK, "Error creating shader"); } } return true; }