make gxm renderer work with new d3drm

This commit is contained in:
olebeck 2025-06-26 02:34:16 +02:00
parent b41e760d9d
commit 06f2179ea1
25 changed files with 948 additions and 322 deletions

View File

@ -67,7 +67,7 @@ if (DOWNLOAD_DEPENDENCIES)
include(FetchContent)
if(VITA)
set(SDL_PATCH "${CMAKE_CURRENT_LIST_DIR}/cmake/modules/sdl3_vita_shaders_fix.patch")
#set(SDL_PATCH "${CMAKE_CURRENT_LIST_DIR}/cmake/modules/sdl3_vita_shaders_fix.patch")
endif()
if(VITA_USE_OPENGLES2)
@ -88,7 +88,10 @@ if (DOWNLOAD_DEPENDENCIES)
set(VIDEO_VITA_PVR ON)
get_target_property(PVR_INCLUDES GLESv2 INTERFACE_INCLUDE_DIRECTORIES)
list(APPEND CMAKE_REQUIRED_INCLUDES ${PVR_INCLUDES})
else()
set(SDL_RENDER OFF)
endif()
FetchContent_MakeAvailable(SDL3)
if(VITA_USE_OPENGLES2)
target_include_directories(SDL3-static PRIVATE ${PVR_INCLUDES})

View File

@ -51,7 +51,6 @@
#endif
#ifdef __vita__
#include <SDL3/SDL_gxm.h>
#define USE_GXM
#endif

View File

@ -9,6 +9,7 @@ add_library(miniwin STATIC EXCLUDE_FROM_ALL
src/ddraw/ddpalette.cpp
src/ddraw/ddraw.cpp
src/ddraw/ddsurface.cpp
src/ddraw/framebuffer.cpp
# D3DRM
src/d3drm/d3drm.cpp

View File

@ -1,6 +1,5 @@
shaders += main.frag.gxp main.vert.gxp
shaders += main.frag.gxp main.vert.gxp image.frag.gxp
shaders += clear.frag.gxp clear.vert.gxp
shaders += blit.color.frag.gxp blit.tex.frag.gxp blit.vert.gxp
all: $(shaders)

View File

@ -1,11 +0,0 @@
void main(
float4 vPosition : POSITION,
float2 vTexCoord : TEXCOORD0,
uniform float4 uColor,
uniform int uUseTexture,
out float4 outColor : COLOR
) {
outColor = uColor;
}

View File

@ -1,12 +0,0 @@
void main(
float4 vPosition : POSITION,
float2 vTexCoord : TEXCOORD0,
uniform float4x4 uTexMatrix,
uniform sampler2D uTexture,
out float4 outColor : COLOR
) {
float2 samplingCoord = mul(uTexMatrix, float4(vTexCoord, 0, 1)).xy;
outColor = tex2D(uTexture, samplingCoord);
}

View File

@ -1,12 +0,0 @@
void main(
float2 aPosition : POSITION,
float2 aTexCoord : TEXCOORD0,
uniform float4x4 uScreenMatrix,
out float4 vPosition : POSITION,
out float2 vTexCoord : TEXCOORD0
) {
vPosition = mul(uScreenMatrix, float4(aPosition, 0, 1));
vTexCoord = aTexCoord;
}

View File

@ -1,5 +1,6 @@
void main(
uniform float4 uColor : COLOR,
out float4 outColor : COLOR
) {
outColor = float4(0.0, 0.0, 0.5, 1.0);
outColor = uColor;
}

View File

@ -0,0 +1,12 @@
void main(
float4 vPosition : POSITION,
float3 vViewPos : TEXCOORD1,
float3 vNormal : TEXCOORD2,
float2 vTexCoord : TEXCOORD3,
uniform sampler2D uTexture,
out float4 outColor : COLOR
) {
outColor = tex2D(uTexture, vTexCoord);
}

Binary file not shown.

View File

@ -0,0 +1,476 @@
/**
* @file incbin.h
* @author Dale Weiler
* @brief Utility for including binary files
*
* Facilities for including binary files into the current translation unit and
* making use from them externally in other translation units.
*/
#ifndef INCBIN_HDR
#define INCBIN_HDR
#include <limits.h>
#if defined(__AVX512BW__) || \
defined(__AVX512CD__) || \
defined(__AVX512DQ__) || \
defined(__AVX512ER__) || \
defined(__AVX512PF__) || \
defined(__AVX512VL__) || \
defined(__AVX512F__)
# define INCBIN_ALIGNMENT_INDEX 6
#elif defined(__AVX__) || \
defined(__AVX2__)
# define INCBIN_ALIGNMENT_INDEX 5
#elif defined(__SSE__) || \
defined(__SSE2__) || \
defined(__SSE3__) || \
defined(__SSSE3__) || \
defined(__SSE4_1__) || \
defined(__SSE4_2__) || \
defined(__neon__) || \
defined(__ARM_NEON) || \
defined(__ALTIVEC__)
# define INCBIN_ALIGNMENT_INDEX 4
#elif ULONG_MAX != 0xffffffffu
# define INCBIN_ALIGNMENT_INDEX 3
# else
# define INCBIN_ALIGNMENT_INDEX 2
#endif
/* Lookup table of (1 << n) where `n' is `INCBIN_ALIGNMENT_INDEX' */
#define INCBIN_ALIGN_SHIFT_0 1
#define INCBIN_ALIGN_SHIFT_1 2
#define INCBIN_ALIGN_SHIFT_2 4
#define INCBIN_ALIGN_SHIFT_3 8
#define INCBIN_ALIGN_SHIFT_4 16
#define INCBIN_ALIGN_SHIFT_5 32
#define INCBIN_ALIGN_SHIFT_6 64
/* Actual alignment value */
#define INCBIN_ALIGNMENT \
INCBIN_CONCATENATE( \
INCBIN_CONCATENATE(INCBIN_ALIGN_SHIFT, _), \
INCBIN_ALIGNMENT_INDEX)
/* Stringize */
#define INCBIN_STR(X) \
#X
#define INCBIN_STRINGIZE(X) \
INCBIN_STR(X)
/* Concatenate */
#define INCBIN_CAT(X, Y) \
X ## Y
#define INCBIN_CONCATENATE(X, Y) \
INCBIN_CAT(X, Y)
/* Deferred macro expansion */
#define INCBIN_EVAL(X) \
X
#define INCBIN_INVOKE(N, ...) \
INCBIN_EVAL(N(__VA_ARGS__))
/* Variable argument count for overloading by arity */
#define INCBIN_VA_ARG_COUNTER(_1, _2, _3, N, ...) N
#define INCBIN_VA_ARGC(...) INCBIN_VA_ARG_COUNTER(__VA_ARGS__, 3, 2, 1, 0)
/* Green Hills uses a different directive for including binary data */
#if defined(__ghs__)
# if (__ghs_asm == 2)
# define INCBIN_MACRO ".file"
/* Or consider the ".myrawdata" entry in the ld file */
# else
# define INCBIN_MACRO "\tINCBIN"
# endif
#else
# define INCBIN_MACRO ".incbin"
#endif
#ifndef _MSC_VER
# define INCBIN_ALIGN \
__attribute__((aligned(INCBIN_ALIGNMENT)))
#else
# define INCBIN_ALIGN __declspec(align(INCBIN_ALIGNMENT))
#endif
#if defined(__arm__) || /* GNU C and RealView */ \
defined(__arm) || /* Diab */ \
defined(_ARM) /* ImageCraft */
# define INCBIN_ARM
#endif
#ifdef __GNUC__
/* Utilize .balign where supported */
# define INCBIN_ALIGN_HOST ".balign " INCBIN_STRINGIZE(INCBIN_ALIGNMENT) "\n"
# define INCBIN_ALIGN_BYTE ".balign 1\n"
#elif defined(INCBIN_ARM)
/*
* On arm assemblers, the alignment value is calculated as (1 << n) where `n' is
* the shift count. This is the value passed to `.align'
*/
# define INCBIN_ALIGN_HOST ".align " INCBIN_STRINGIZE(INCBIN_ALIGNMENT_INDEX) "\n"
# define INCBIN_ALIGN_BYTE ".align 0\n"
#else
/* We assume other inline assembler's treat `.align' as `.balign' */
# define INCBIN_ALIGN_HOST ".align " INCBIN_STRINGIZE(INCBIN_ALIGNMENT) "\n"
# define INCBIN_ALIGN_BYTE ".align 1\n"
#endif
/* INCBIN_CONST is used by incbin.c generated files */
#if defined(__cplusplus)
# define INCBIN_EXTERNAL extern "C"
# define INCBIN_CONST extern const
#else
# define INCBIN_EXTERNAL extern
# define INCBIN_CONST const
#endif
/**
* @brief Optionally override the linker section into which size and data is
* emitted.
*
* @warning If you use this facility, you might have to deal with
* platform-specific linker output section naming on your own.
*/
#if !defined(INCBIN_OUTPUT_SECTION)
# if defined(__APPLE__)
# define INCBIN_OUTPUT_SECTION ".const_data"
# else
# define INCBIN_OUTPUT_SECTION ".rodata"
# endif
#endif
/**
* @brief Optionally override the linker section into which data is emitted.
*
* @warning If you use this facility, you might have to deal with
* platform-specific linker output section naming on your own.
*/
#if !defined(INCBIN_OUTPUT_DATA_SECTION)
# define INCBIN_OUTPUT_DATA_SECTION INCBIN_OUTPUT_SECTION
#endif
/**
* @brief Optionally override the linker section into which size is emitted.
*
* @warning If you use this facility, you might have to deal with
* platform-specific linker output section naming on your own.
*
* @note This is useful for Harvard architectures where program memory cannot
* be directly read from the program without special instructions. With this you
* can chose to put the size variable in RAM rather than ROM.
*/
#if !defined(INCBIN_OUTPUT_SIZE_SECTION)
# define INCBIN_OUTPUT_SIZE_SECTION INCBIN_OUTPUT_SECTION
#endif
#if defined(__APPLE__)
# include <TargetConditionals.h>
# if defined(TARGET_OS_IPHONE) && !defined(INCBIN_SILENCE_BITCODE_WARNING)
# warning "incbin is incompatible with bitcode. Using the library will break upload to App Store if you have bitcode enabled. Add `#define INCBIN_SILENCE_BITCODE_WARNING` before including this header to silence this warning."
# endif
/* The directives are different for Apple branded compilers */
# define INCBIN_SECTION INCBIN_OUTPUT_SECTION "\n"
# define INCBIN_GLOBAL(NAME) ".globl " INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME "\n"
# define INCBIN_INT ".long "
# define INCBIN_MANGLE "_"
# define INCBIN_BYTE ".byte "
# define INCBIN_TYPE(...)
#else
# define INCBIN_SECTION ".section " INCBIN_OUTPUT_SECTION "\n"
# define INCBIN_GLOBAL(NAME) ".global " INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME "\n"
# if defined(__ghs__)
# define INCBIN_INT ".word "
# else
# define INCBIN_INT ".int "
# endif
# if defined(__USER_LABEL_PREFIX__)
# define INCBIN_MANGLE INCBIN_STRINGIZE(__USER_LABEL_PREFIX__)
# else
# define INCBIN_MANGLE ""
# endif
# if defined(INCBIN_ARM)
/* On arm assemblers, `@' is used as a line comment token */
# define INCBIN_TYPE(NAME) ".type " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME ", %object\n"
# elif defined(__MINGW32__) || defined(__MINGW64__) || defined(__CYGWIN__)
/* Mingw and Cygwin don't support this directive either */
# define INCBIN_TYPE(NAME)
# else
/* It's safe to use `@' on other architectures */
# define INCBIN_TYPE(NAME) ".type " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME ", @object\n"
# endif
# define INCBIN_BYTE ".byte "
#endif
/* List of style types used for symbol names */
#define INCBIN_STYLE_CAMEL 0
#define INCBIN_STYLE_SNAKE 1
/**
* @brief Specify the prefix to use for symbol names.
*
* @note By default this is "g".
*
* @code
* #define INCBIN_PREFIX incbin
* #include "incbin.h"
* INCBIN(Foo, "foo.txt");
*
* // Now you have the following symbols instead:
* // const unsigned char incbinFoo<data>[];
* // const unsigned char *const incbinFoo<end>;
* // const unsigned int incbinFoo<size>;
* @endcode
*/
#if !defined(INCBIN_PREFIX)
# define INCBIN_PREFIX g
#endif
/**
* @brief Specify the style used for symbol names.
*
* Possible options are
* - INCBIN_STYLE_CAMEL "CamelCase"
* - INCBIN_STYLE_SNAKE "snake_case"
*
* @note By default this is INCBIN_STYLE_CAMEL
*
* @code
* #define INCBIN_STYLE INCBIN_STYLE_SNAKE
* #include "incbin.h"
* INCBIN(foo, "foo.txt");
*
* // Now you have the following symbols:
* // const unsigned char <prefix>foo_data[];
* // const unsigned char *const <prefix>foo_end;
* // const unsigned int <prefix>foo_size;
* @endcode
*/
#if !defined(INCBIN_STYLE)
# define INCBIN_STYLE INCBIN_STYLE_CAMEL
#endif
/* Style lookup tables */
#define INCBIN_STYLE_0_DATA Data
#define INCBIN_STYLE_0_END End
#define INCBIN_STYLE_0_SIZE Size
#define INCBIN_STYLE_1_DATA _data
#define INCBIN_STYLE_1_END _end
#define INCBIN_STYLE_1_SIZE _size
/* Style lookup: returning identifier */
#define INCBIN_STYLE_IDENT(TYPE) \
INCBIN_CONCATENATE( \
INCBIN_STYLE_, \
INCBIN_CONCATENATE( \
INCBIN_EVAL(INCBIN_STYLE), \
INCBIN_CONCATENATE(_, TYPE)))
/* Style lookup: returning string literal */
#define INCBIN_STYLE_STRING(TYPE) \
INCBIN_STRINGIZE( \
INCBIN_STYLE_IDENT(TYPE)) \
/* Generate the global labels by indirectly invoking the macro with our style
* type and concatenating the name against them. */
#define INCBIN_GLOBAL_LABELS(NAME, TYPE) \
INCBIN_INVOKE( \
INCBIN_GLOBAL, \
INCBIN_CONCATENATE( \
NAME, \
INCBIN_INVOKE( \
INCBIN_STYLE_IDENT, \
TYPE))) \
INCBIN_INVOKE( \
INCBIN_TYPE, \
INCBIN_CONCATENATE( \
NAME, \
INCBIN_INVOKE( \
INCBIN_STYLE_IDENT, \
TYPE)))
/**
* @brief Externally reference binary data included in another translation unit.
*
* Produces three external symbols that reference the binary data included in
* another translation unit.
*
* The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with
* "Data", as well as "End" and "Size" after. An example is provided below.
*
* @param TYPE Optional array type. Omitting this picks a default of `unsigned char`.
* @param NAME The name given for the binary data
*
* @code
* INCBIN_EXTERN(Foo);
*
* // Now you have the following symbols:
* // extern const unsigned char <prefix>Foo<data>[];
* // extern const unsigned char *const <prefix>Foo<end>;
* // extern const unsigned int <prefix>Foo<size>;
* @endcode
*
* You may specify a custom optional data type as well as the first argument.
* @code
* INCBIN_EXTERN(custom_type, Foo);
*
* // Now you have the following symbols:
* // extern const custom_type <prefix>Foo<data>[];
* // extern const custom_type *const <prefix>Foo<end>;
* // extern const unsigned int <prefix>Foo<size>;
* @endcode
*/
#define INCBIN_EXTERN(...) \
INCBIN_CONCATENATE(INCBIN_EXTERN_, INCBIN_VA_ARGC(__VA_ARGS__))(__VA_ARGS__)
#define INCBIN_EXTERN_1(NAME, ...) \
INCBIN_EXTERN_2(unsigned char, NAME)
#define INCBIN_EXTERN_2(TYPE, NAME) \
INCBIN_EXTERNAL const INCBIN_ALIGN TYPE \
INCBIN_CONCATENATE( \
INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
INCBIN_STYLE_IDENT(DATA))[]; \
INCBIN_EXTERNAL const INCBIN_ALIGN TYPE *const \
INCBIN_CONCATENATE( \
INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
INCBIN_STYLE_IDENT(END)); \
INCBIN_EXTERNAL const unsigned int \
INCBIN_CONCATENATE( \
INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
INCBIN_STYLE_IDENT(SIZE))
/**
* @brief Externally reference textual data included in another translation unit.
*
* Produces three external symbols that reference the textual data included in
* another translation unit.
*
* The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with
* "Data", as well as "End" and "Size" after. An example is provided below.
*
* @param NAME The name given for the textual data
*
* @code
* INCBIN_EXTERN(Foo);
*
* // Now you have the following symbols:
* // extern const char <prefix>Foo<data>[];
* // extern const char *const <prefix>Foo<end>;
* // extern const unsigned int <prefix>Foo<size>;
* @endcode
*/
#define INCTXT_EXTERN(NAME) \
INCBIN_EXTERN_2(char, NAME)
/**
* @brief Include a binary file into the current translation unit.
*
* Includes a binary file into the current translation unit, producing three symbols
* for objects that encode the data and size respectively.
*
* The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with
* "Data", as well as "End" and "Size" after. An example is provided below.
*
* @param TYPE Optional array type. Omitting this picks a default of `unsigned char`.
* @param NAME The name to associate with this binary data (as an identifier.)
* @param FILENAME The file to include (as a string literal.)
*
* @code
* INCBIN(Icon, "icon.png");
*
* // Now you have the following symbols:
* // const unsigned char <prefix>Icon<data>[];
* // const unsigned char *const <prefix>Icon<end>;
* // const unsigned int <prefix>Icon<size>;
* @endcode
*
* You may specify a custom optional data type as well as the first argument.
* These macros are specialized by arity.
* @code
* INCBIN(custom_type, Icon, "icon.png");
*
* // Now you have the following symbols:
* // const custom_type <prefix>Icon<data>[];
* // const custom_type *const <prefix>Icon<end>;
* // const unsigned int <prefix>Icon<size>;
* @endcode
*
* @warning This must be used in global scope
* @warning The identifiers may be different if INCBIN_STYLE is not default
*
* To externally reference the data included by this in another translation unit
* please @see INCBIN_EXTERN.
*/
#ifdef _MSC_VER
# define INCBIN(NAME, FILENAME) \
INCBIN_EXTERN(NAME)
#else
# define INCBIN(...) \
INCBIN_CONCATENATE(INCBIN_, INCBIN_VA_ARGC(__VA_ARGS__))(__VA_ARGS__)
# if defined(__GNUC__)
# define INCBIN_1(...) _Pragma("GCC error \"Single argument INCBIN not allowed\"")
# elif defined(__clang__)
# define INCBIN_1(...) _Pragma("clang error \"Single argument INCBIN not allowed\"")
# else
# define INCBIN_1(...) /* Cannot do anything here */
# endif
# define INCBIN_2(NAME, FILENAME) \
INCBIN_3(unsigned char, NAME, FILENAME)
# define INCBIN_3(TYPE, NAME, FILENAME) INCBIN_COMMON(TYPE, NAME, FILENAME, /* No terminator for binary data */)
# define INCBIN_COMMON(TYPE, NAME, FILENAME, TERMINATOR) \
__asm__(INCBIN_SECTION \
INCBIN_GLOBAL_LABELS(NAME, DATA) \
INCBIN_ALIGN_HOST \
INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(DATA) ":\n" \
INCBIN_MACRO " \"" FILENAME "\"\n" \
TERMINATOR \
INCBIN_GLOBAL_LABELS(NAME, END) \
INCBIN_ALIGN_BYTE \
INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(END) ":\n" \
INCBIN_BYTE "1\n" \
INCBIN_GLOBAL_LABELS(NAME, SIZE) \
INCBIN_ALIGN_HOST \
INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(SIZE) ":\n" \
INCBIN_INT INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(END) " - " \
INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(DATA) "\n" \
INCBIN_ALIGN_HOST \
".text\n" \
); \
INCBIN_EXTERN(TYPE, NAME)
#endif
/**
* @brief Include a textual file into the current translation unit.
*
* This behaves the same as INCBIN except it produces char compatible arrays
* and implicitly adds a null-terminator byte, thus the size of data included
* by this is one byte larger than that of INCBIN.
*
* Includes a textual file into the current translation unit, producing three
* symbols for objects that encode the data and size respectively.
*
* The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with
* "Data", as well as "End" and "Size" after. An example is provided below.
*
* @param NAME The name to associate with this binary data (as an identifier.)
* @param FILENAME The file to include (as a string literal.)
*
* @code
* INCTXT(Readme, "readme.txt");
*
* // Now you have the following symbols:
* // const char <prefix>Readme<data>[];
* // const char *const <prefix>Readme<end>;
* // const unsigned int <prefix>Readme<size>;
* @endcode
*
* @warning This must be used in global scope
* @warning The identifiers may be different if INCBIN_STYLE is not default
*
* To externally reference the data included by this in another translation unit
* please @see INCBIN_EXTERN.
*/
#if defined(_MSC_VER)
# define INCTXT(NAME, FILENAME) \
INCBIN_EXTERN(NAME)
#else
# define INCTXT(NAME, FILENAME) \
INCBIN_COMMON(char, NAME, FILENAME, INCBIN_BYTE "0\n")
#endif
#endif

View File

@ -54,13 +54,13 @@ void main(
specular += spec * lightColor;
}
}
}
outColor = uColor;
outColor.rgb = clamp(diffuse * uColor.rgb + specular, 0.0, 1.0);
if (uUseTexture != 0) {
float4 texel = tex2D(uTexture, vTexCoord);
outColor.rgb *= texel.rgb;
outColor.rgb = clamp(outColor.rgb, 0.0, 1.0);
}
outColor = uColor;
outColor.rgb = clamp(diffuse * uColor.rgb + specular, 0.0, 1.0);
if (uUseTexture != 0) {
float4 texel = tex2D(uTexture, vTexCoord);
outColor.rgb *= texel.rgb;
outColor.rgb = clamp(outColor.rgb, 0.0, 1.0);
}
}

View File

@ -6,6 +6,8 @@
#include <SDL3/SDL_stdinc.h>
static SceUID cdramPoolUID = -1;
static SceClibMspace cdramPool = NULL;
void *patcher_host_alloc(void *user_data, unsigned int size)
@ -126,3 +128,44 @@ void vita_mem_fragment_usse_free(SceUID uid)
sceGxmUnmapFragmentUsseMemory(mem);
sceKernelFreeMemBlock(uid);
}
bool cdramPool_init() {
if(cdramPool) {
return true;
}
int poolsize;
int ret;
void* mem;
SceKernelFreeMemorySizeInfo info;
info.size = sizeof(SceKernelFreeMemorySizeInfo);
sceKernelGetFreeMemorySize(&info);
poolsize = ALIGN(info.size_cdram, 256 * 1024);
if (poolsize > info.size_cdram) {
poolsize = ALIGN(info.size_cdram - 256 * 1024, 256 * 1024);
}
poolsize -= 16 * 1024 * 1024;
cdramPoolUID = sceKernelAllocMemBlock("gpu_cdram_pool", SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW, poolsize, NULL);
if (cdramPool < 0) {
return false;
}
ret = sceKernelGetMemBlockBase(cdramPoolUID, &mem);
if (ret < 0) {
return false;
}
cdramPool = sceClibMspaceCreate(mem, poolsize);
if (!cdramPool) {
return false;
}
ret = sceGxmMapMemory(mem, poolsize, (SceGxmMemoryAttribFlags)(SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE));
if (ret < 0) {
return false;
}
return true;
}
SceClibMspace cdramPool_get() {
return cdramPool;
}

View File

@ -23,3 +23,6 @@ void *vita_mem_vertex_usse_alloc(unsigned int size, SceUID *uid, unsigned int *u
void vita_mem_vertex_usse_free(SceUID uid);
void *vita_mem_fragment_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset);
void vita_mem_fragment_usse_free(SceUID uid);
bool cdramPool_init();
SceClibMspace cdramPool_get();

View File

@ -13,20 +13,20 @@
#include <psp2/types.h>
#include <psp2/kernel/modulemgr.h>
#include <SDL3/SDL_gxm.h>
#include "utils.h"
#include "memory.h"
#define INCBIN_PREFIX _inc_
#include "incbin.h"
bool with_razor = false;
#define VITA_GXM_SCREEN_WIDTH 960
#define VITA_GXM_SCREEN_HEIGHT 544
#define VITA_GXM_SCREEN_STRIDE 960
#define VITA_GXM_PENDING_SWAPS 2
#define VITA_GXM_SCREEN_WIDTH 960
#define VITA_GXM_SCREEN_HEIGHT 544
#define VITA_GXM_SCREEN_STRIDE 960
#define VITA_GXM_COLOR_FORMAT SCE_GXM_COLOR_FORMAT_A8B8G8R8
#define VITA_GXM_PIXEL_FORMAT SCE_DISPLAY_PIXELFORMAT_A8B8G8R8
#define VITA_GXM_COLOR_FORMAT SCE_GXM_COLOR_FORMAT_A8B8G8R8
#define VITA_GXM_PIXEL_FORMAT SCE_DISPLAY_PIXELFORMAT_A8B8G8R8
struct SceneLightGXM {
float color[4];
@ -41,40 +41,17 @@ typedef struct Vertex {
} Vertex;
static bool make_fragment_program(
GXMRendererData* data,
const SceGxmProgram* vertexProgramGxp,
const SceGxmBlendInfo *blendInfo,
SceGxmFragmentProgram** fragmentProgram
) {
return SCE_ERR(sceGxmShaderPatcherCreateFragmentProgram,
data->shaderPatcher,
data->mainFragmentProgramId,
SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4,
SCE_GXM_MULTISAMPLE_NONE,
blendInfo,
vertexProgramGxp,
fragmentProgram
);
}
INCBIN("main.vert.gxp", main_vert_gxp_start);
INCBIN("main.frag.gxp", main_frag_gxp_start);
INCBIN("clear.vert.gxp", clear_vert_gxp_start);
INCBIN("clear.frag.gxp", clear_frag_gxp_start);
INCBIN("blit.vert.gxp", blit_vert_gxp_start);
INCBIN("blit.color.frag.gxp", blit_color_frag_gxp_start);
INCBIN("blit.tex.frag.gxp", blit_tex_frag_gxp_start);
const SceGxmProgram* clearVertexProgramGxp = (const SceGxmProgram*)&clear_vert_gxp_start;
const SceGxmProgram* clearFragmentProgramGxp = (const SceGxmProgram*)&clear_frag_gxp_start;
const SceGxmProgram* mainVertexProgramGxp = (const SceGxmProgram*)&main_vert_gxp_start;
const SceGxmProgram* mainFragmentProgramGxp = (const SceGxmProgram*)&main_frag_gxp_start;
const SceGxmProgram* blitVertexProgramGxp = (const SceGxmProgram*)&blit_vert_gxp_start;
const SceGxmProgram* blitColorFragmentProgramGxp = (const SceGxmProgram*)&blit_color_frag_gxp_start;
const SceGxmProgram* blitTexFragmentProgramGxp = (const SceGxmProgram*)&blit_tex_frag_gxp_start;
INCBIN(main_vert_gxp, "main.vert.gxp");
INCBIN(main_frag_gxp, "main.frag.gxp");
INCBIN(clear_vert_gxp, "clear.vert.gxp");
INCBIN(clear_frag_gxp, "clear.frag.gxp");
INCBIN(image_frag_gxp, "image.frag.gxp");
const SceGxmProgram* mainVertexProgramGxp = (const SceGxmProgram*)_inc_main_vert_gxpData;
const SceGxmProgram* mainFragmentProgramGxp = (const SceGxmProgram*)_inc_main_frag_gxpData;
const SceGxmProgram* clearVertexProgramGxp = (const SceGxmProgram*)_inc_clear_vert_gxpData;
const SceGxmProgram* clearFragmentProgramGxp = (const SceGxmProgram*)_inc_clear_frag_gxpData;
const SceGxmProgram* imageFragmentProgramGxp = (const SceGxmProgram*)_inc_image_frag_gxpData;
extern "C" int sceRazorGpuCaptureSetTrigger(int frames, const char* path);
extern "C" int sceRazorGpuCaptureEnableSalvage(const char* path);
@ -82,15 +59,40 @@ extern "C" int sceRazorGpuCaptureSetTriggerNextFrame(const char* path);
static GXMRendererContext gxm_renderer_context;
static void display_callback(const void *callback_data) {
const GXMDisplayData *display_data = (const GXMDisplayData *)callback_data;
SceDisplayFrameBuf framebuf;
SDL_memset(&framebuf, 0x00, sizeof(SceDisplayFrameBuf));
framebuf.size = sizeof(SceDisplayFrameBuf);
framebuf.base = display_data->address;
framebuf.pitch = VITA_GXM_SCREEN_STRIDE;
framebuf.pixelformat = VITA_GXM_PIXEL_FORMAT;
framebuf.width = VITA_GXM_SCREEN_WIDTH;
framebuf.height = VITA_GXM_SCREEN_HEIGHT;
sceDisplaySetFrameBuf(&framebuf, SCE_DISPLAY_SETBUF_NEXTFRAME);
}
static void load_razor() {
int mod_id = _sceKernelLoadModule("app0:librazorcapture_es4.suprx", 0, nullptr);
int status;
if(!SCE_ERR(sceKernelStartModule, mod_id, 0, nullptr, 0, nullptr, &status)) {
with_razor = true;
}
if(with_razor) {
sceRazorGpuCaptureEnableSalvage("ux0:data/gpu_crash.sgx");
}
}
bool gxm_initialized = false;
bool gxm_init() {
if(SDL_gxm_is_init()) {
if(gxm_initialized) {
return true;
}
SDL_gxm_init();
load_razor();
/*
SceGxmInitializeParams initializeParams;
SDL_memset(&initializeParams, 0, sizeof(SceGxmInitializeParams));
initializeParams.flags = 0;
@ -104,8 +106,9 @@ bool gxm_init() {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "gxm init failed: %d", err);
return err;
}
*/
return true;
gxm_initialized = true;
return cdramPool_init();
}
static bool create_gxm_context() {
@ -122,7 +125,7 @@ static bool create_gxm_context() {
const unsigned int patcherVertexUsseSize = 64 * 1024;
const unsigned int patcherFragmentUsseSize = 64 * 1024;
data->cdramPool = SDL_gxm_get_cdramPool();
data->cdramPool = cdramPool_get();
if(!data->cdramPool) {
SDL_Log("failed to allocate cdramPool");
return false;
@ -253,8 +256,8 @@ bool get_gxm_context(SceGxmContext** context, SceGxmShaderPatcher** shaderPatche
static bool create_gxm_renderer(int width, int height, GXMRendererData* data) {
const unsigned int alignedWidth = ALIGN(width, SCE_GXM_TILE_SIZEX);
const unsigned int alignedHeight = ALIGN(height, SCE_GXM_TILE_SIZEY);
const unsigned int alignedWidth = ALIGN(VITA_GXM_SCREEN_WIDTH, SCE_GXM_TILE_SIZEX);
const unsigned int alignedHeight = ALIGN(VITA_GXM_SCREEN_HEIGHT, SCE_GXM_TILE_SIZEY);
unsigned int sampleCount = alignedWidth * alignedHeight;
unsigned int depthStrideInSamples = alignedWidth;
@ -283,13 +286,12 @@ static bool create_gxm_renderer(int width, int height, GXMRendererData* data) {
.alphaDst = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
};
/*
// render target
SceGxmRenderTargetParams renderTargetParams;
memset(&renderTargetParams, 0, sizeof(SceGxmRenderTargetParams));
renderTargetParams.flags = 0;
renderTargetParams.width = width;
renderTargetParams.height = height;
renderTargetParams.width = VITA_GXM_SCREEN_WIDTH;
renderTargetParams.height = VITA_GXM_SCREEN_HEIGHT;
renderTargetParams.scenesPerFrame = 1;
renderTargetParams.multisampleMode = 0;
renderTargetParams.multisampleLocations = 0;
@ -299,31 +301,31 @@ static bool create_gxm_renderer(int width, int height, GXMRendererData* data) {
return false;
}
data->renderBuffer = vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW,
4 * VITA_GXM_SCREEN_STRIDE * VITA_GXM_SCREEN_HEIGHT,
SCE_GXM_COLOR_SURFACE_ALIGNMENT,
SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE,
&data->renderBufferUid, "display", nullptr);
for(int i = 0; i < VITA_GXM_DISPLAY_BUFFER_COUNT; i++) {
data->displayBuffers[i] = vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW,
4 * VITA_GXM_SCREEN_STRIDE * VITA_GXM_SCREEN_HEIGHT,
SCE_GXM_COLOR_SURFACE_ALIGNMENT,
SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE,
&data->displayBuffersUid[i], "display", nullptr);
// color surface
if(SCE_ERR(sceGxmColorSurfaceInit,
&data->renderSurface,
SCE_GXM_COLOR_FORMAT_A8B8G8R8,
SCE_GXM_COLOR_SURFACE_LINEAR,
SCE_GXM_COLOR_SURFACE_SCALE_NONE,
SCE_GXM_OUTPUT_REGISTER_SIZE_32BIT,
width, height,
width,
data->renderBuffer
)) {
return false;
};
if(SCE_ERR(sceGxmColorSurfaceInit,
&data->displayBuffersSurface[i],
SCE_GXM_COLOR_FORMAT_A8B8G8R8,
SCE_GXM_COLOR_SURFACE_LINEAR,
SCE_GXM_COLOR_SURFACE_SCALE_NONE,
SCE_GXM_OUTPUT_REGISTER_SIZE_32BIT,
VITA_GXM_SCREEN_WIDTH, VITA_GXM_SCREEN_HEIGHT,
VITA_GXM_SCREEN_STRIDE,
data->displayBuffers[i]
)) {
return false;
};
if(SCE_ERR(sceGxmSyncObjectCreate, &data->renderBufferSync)) {
return false;
if(SCE_ERR(sceGxmSyncObjectCreate, &data->displayBuffersSync[i])) {
return false;
}
}
*/
// depth & stencil
@ -358,15 +360,26 @@ static bool create_gxm_renderer(int width, int height, GXMRendererData* data) {
return false;
}
// register shader programs
if(SCE_ERR(sceGxmShaderPatcherRegisterProgram, data->shaderPatcher, clearVertexProgramGxp, &data->clearVertexProgramId)) {
return false;
}
if(SCE_ERR(sceGxmShaderPatcherRegisterProgram, data->shaderPatcher, clearFragmentProgramGxp, &data->clearFragmentProgramId)) {
return false;
}
if(SCE_ERR(sceGxmShaderPatcherRegisterProgram, data->shaderPatcher, mainVertexProgramGxp, &data->mainVertexProgramId)) {
return false;
}
if(SCE_ERR(sceGxmShaderPatcherRegisterProgram, data->shaderPatcher, mainFragmentProgramGxp, &data->mainFragmentProgramId)) {
return false;
}
if(SCE_ERR(sceGxmShaderPatcherRegisterProgram, data->shaderPatcher, imageFragmentProgramGxp, &data->imageFragmentProgramId)) {
return false;
}
// clear shader
{
if(SCE_ERR(sceGxmShaderPatcherRegisterProgram, data->shaderPatcher, clearVertexProgramGxp, &data->clearVertexProgramId)) {
return false;
}
if(SCE_ERR(sceGxmShaderPatcherRegisterProgram, data->shaderPatcher, clearFragmentProgramGxp, &data->clearFragmentProgramId)) {
return false;
}
GET_SHADER_PARAM(positionAttribute, clearVertexProgramGxp, "aPosition", false);
SceGxmVertexAttribute vertexAttributes[1];
@ -380,37 +393,30 @@ static bool create_gxm_renderer(int width, int height, GXMRendererData* data) {
vertexStreams[0].indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT;
if(SCE_ERR(sceGxmShaderPatcherCreateVertexProgram,
data->shaderPatcher,
data->clearVertexProgramId,
vertexAttributes, 1,
vertexStreams, 1,
&data->clearVertexProgram
data->shaderPatcher,
data->clearVertexProgramId,
vertexAttributes, 1,
vertexStreams, 1,
&data->clearVertexProgram
)) {
return false;
}
if(SCE_ERR(sceGxmShaderPatcherCreateFragmentProgram,
data->shaderPatcher,
data->clearFragmentProgramId,
SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4,
SCE_GXM_MULTISAMPLE_NONE,
NULL,
clearVertexProgramGxp,
&data->clearFragmentProgram
if(SCE_ERR(sceGxmShaderPatcherCreateFragmentProgram,
data->shaderPatcher,
data->clearFragmentProgramId,
SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4,
SCE_GXM_MULTISAMPLE_NONE,
NULL,
clearVertexProgramGxp,
&data->clearFragmentProgram
)) {
return false;
return false;
}
}
// main shader
{
if(SCE_ERR(sceGxmShaderPatcherRegisterProgram, data->shaderPatcher, mainVertexProgramGxp, &data->mainVertexProgramId)) {
return false;
}
if(SCE_ERR(sceGxmShaderPatcherRegisterProgram, data->shaderPatcher, mainFragmentProgramGxp, &data->mainFragmentProgramId)) {
return false;
}
GET_SHADER_PARAM(positionAttribute, mainVertexProgramGxp, "aPosition", false);
GET_SHADER_PARAM(normalAttribute, mainVertexProgramGxp, "aNormal", false);
GET_SHADER_PARAM(texCoordAttribute, mainVertexProgramGxp, "aTexCoord", false);
@ -447,18 +453,41 @@ static bool create_gxm_renderer(int width, int height, GXMRendererData* data) {
vertexAttributes, 3,
vertexStreams, 1,
&data->mainVertexProgram
)) {
return false;
}
)) return false;
}
if(make_fragment_program(data, mainVertexProgramGxp, &blendInfoOpaque, &data->opaqueFragmentProgram)) {
return false;
}
// main opaque
if(SCE_ERR(sceGxmShaderPatcherCreateFragmentProgram,
data->shaderPatcher,
data->mainFragmentProgramId,
SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4,
SCE_GXM_MULTISAMPLE_NONE,
&blendInfoOpaque,
mainVertexProgramGxp,
&data->opaqueFragmentProgram
)) return false;
if(make_fragment_program(data, mainVertexProgramGxp, &blendInfoTransparent, &data->transparentFragmentProgram)) {
return false;
}
// main transparent
if(SCE_ERR(sceGxmShaderPatcherCreateFragmentProgram,
data->shaderPatcher,
data->mainFragmentProgramId,
SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4,
SCE_GXM_MULTISAMPLE_NONE,
&blendInfoTransparent,
mainVertexProgramGxp,
&data->transparentFragmentProgram
)) return false;
// image
if(SCE_ERR(sceGxmShaderPatcherCreateFragmentProgram,
data->shaderPatcher,
data->mainFragmentProgramId,
SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4,
SCE_GXM_MULTISAMPLE_NONE,
&blendInfoTransparent,
mainVertexProgramGxp,
&data->imageFragmentProgram
)) return false;
// vertex uniforms
data->uModelViewMatrixParam = sceGxmProgramFindParameterByName(mainVertexProgramGxp, "uModelViewMatrix");
@ -472,6 +501,8 @@ static bool create_gxm_renderer(int width, int height, GXMRendererData* data) {
data->uColor = sceGxmProgramFindParameterByName(mainFragmentProgramGxp, "uColor"); // vec4
data->uUseTexture = sceGxmProgramFindParameterByName(mainFragmentProgramGxp, "uUseTexture"); // int
// clear uniforms
data->clearShader_uColor = sceGxmProgramFindParameterByName(clearFragmentProgramGxp, "uColor"); // vec4
// clear mesh
const size_t clearMeshVerticiesSize = 3 * sizeof(float)*2;
@ -522,33 +553,10 @@ extern "C" {
}
*/
extern "C" void load_razor() {
int mod_id = _sceKernelLoadModule("app0:librazorcapture_es4.suprx", 0, nullptr);
int status;
if(!SCE_ERR(sceKernelStartModule, mod_id, 0, nullptr, 0, nullptr, &status)) {
with_razor = true;
}
if(with_razor) {
sceRazorGpuCaptureEnableSalvage("ux0:data/gpu_crash.sgx");
}
}
Direct3DRMRenderer* GXMRenderer::Create(IDirectDrawSurface* surface)
Direct3DRMRenderer* GXMRenderer::Create(DWORD width, DWORD height)
{
DDSURFACEDESC DDSDesc;
DDSDesc.dwSize = sizeof(DDSURFACEDESC);
surface->GetSurfaceDesc(&DDSDesc);
int width = DDSDesc.dwWidth;
int height = DDSDesc.dwHeight;
FrameBufferImpl* frameBuffer = static_cast<FrameBufferImpl*>(surface);
if(!frameBuffer) {
SDL_Log("cant create with something that isnt a framebuffer");
return nullptr;
}
SDL_Log("GXMRenderer::Create width=%d height=%d", width, height);
bool success = gxm_init();
@ -561,7 +569,6 @@ Direct3DRMRenderer* GXMRenderer::Create(IDirectDrawSurface* surface)
if(!success) {
return nullptr;
}
gxm_data.frameBuffer = frameBuffer;
return new GXMRenderer(width, height, gxm_data);
}
@ -571,6 +578,7 @@ GXMRenderer::GXMRenderer(
DWORD height,
GXMRendererData data
) : m_width(width), m_height(height), m_data(data) {
m_initialized = true;
}
GXMRenderer::~GXMRenderer() {
@ -578,11 +586,7 @@ GXMRenderer::~GXMRenderer() {
return;
}
/*
sceGxmDestroyRenderTarget(this->m_data.renderTarget);
vita_mem_free(this->m_data.renderBufferUid);
sceGxmSyncObjectDestroy(this->m_data.renderBufferSync);
*/
// todo free stuff
vita_mem_free(this->m_data.depthBufferUid);
this->m_data.depthBufferData = nullptr;
@ -590,13 +594,6 @@ GXMRenderer::~GXMRenderer() {
this->m_data.stencilBufferData = nullptr;
}
void* GXMRenderer::AllocateGpu(size_t size, size_t align) {
return sceClibMspaceMemalign(this->m_data.cdramPool, align, size);
}
void GXMRenderer::FreeGpu(void* ptr) {
sceClibMspaceFree(this->m_data.cdramPool, ptr);
}
void GXMRenderer::PushLights(const SceneLight* lightsArray, size_t count)
{
if (count > 3) {
@ -614,7 +611,7 @@ void GXMRenderer::SetFrustumPlanes(const Plane* frustumPlanes)
void GXMRenderer::SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back)
{
memcpy(&m_projection, projection, sizeof(D3DRMMATRIX4D));
m_projection[1][1] *= -1.0f; // OpenGL is upside down
//m_projection[1][1] *= -1.0f; // OpenGL is upside down
}
struct TextureDestroyContextGLS2 {
@ -630,7 +627,7 @@ void GXMRenderer::AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* textu
auto* ctx = static_cast<TextureDestroyContextGLS2*>(arg);
auto& cache = ctx->renderer->m_textures[ctx->textureId];
void* textureData = sceGxmTextureGetData(&cache.gxmTexture);
ctx->renderer->FreeGpu(textureData);
sceClibMspaceFree(ctx->renderer->m_data.cdramPool, textureData);
delete ctx;
},
ctx
@ -663,7 +660,7 @@ Uint32 GXMRenderer::GetTextureId(IDirect3DRMTexture* iTexture)
if (!surf) {
return NO_TEXTURE_ID;
}
void* textureData = this->AllocateGpu(surf->w*surf->h*4, SCE_GXM_TEXTURE_ALIGNMENT);
void* textureData = sceClibMspaceMemalign(this->m_data.cdramPool, SCE_GXM_TEXTURE_ALIGNMENT, surf->w*surf->h*4);
memcpy(textureData, surf->pixels, surf->w*surf->h*4);
SDL_DestroySurface(surf);
@ -717,7 +714,7 @@ GXMMeshCacheEntry GXMRenderer::GXMUploadMesh(const MeshGroup& meshGroup)
size_t vertexBufferSize = sizeof(Vertex)*vertices.size();
size_t indexBufferSize = sizeof(uint16_t)*indices.size();
void* meshData = this->AllocateGpu(vertexBufferSize+indexBufferSize);
void* meshData = sceClibMspaceMemalign(this->m_data.cdramPool, 4, vertexBufferSize+indexBufferSize);
Vertex* vertexBuffer = (Vertex*)meshData;
uint16_t* indexBuffer = (uint16_t*)((uint8_t*)meshData + vertexBufferSize);
@ -764,7 +761,7 @@ void GXMRenderer::AddMeshDestroyCallback(Uint32 id, IDirect3DRMMesh* mesh)
auto* ctx = static_cast<GXMMeshDestroyContext*>(arg);
auto& cache = ctx->renderer->m_meshes[ctx->id];
cache.meshGroup = nullptr;
ctx->renderer->FreeGpu(cache.meshData);
sceClibMspaceFree(ctx->renderer->m_data.cdramPool, cache.meshData);
delete ctx;
},
ctx
@ -799,16 +796,6 @@ Uint32 GXMRenderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup)
return (Uint32) (m_meshes.size() - 1);
}
DWORD GXMRenderer::GetWidth()
{
return m_width;
}
DWORD GXMRenderer::GetHeight()
{
return m_height;
}
void GXMRenderer::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc)
{
halDesc->dcmColorModel = D3DCOLORMODEL::RGB;
@ -831,34 +818,32 @@ const char* GXMRenderer::GetName()
bool razor_triggered = false;
void GXMRenderer::StartScene() {
if(sceneStarted) return;
sceGxmBeginScene(
this->m_data.context,
0,
this->m_data.renderTarget,
nullptr,
nullptr,
this->m_data.displayBuffersSync[this->backBufferIndex],
&this->m_data.displayBuffersSurface[this->backBufferIndex],
&this->m_data.depthSurface
);
sceGxmSetViewport(this->m_data.context, 0, m_width, 0, m_height, 0, 0);
this->sceneStarted = true;
}
HRESULT GXMRenderer::BeginFrame()
{
SDL_Log("GXMRenderer::BeginFrame");
if(with_razor && !razor_triggered) {
SDL_Log("trigger razor for next frame");
sceRazorGpuCaptureSetTriggerNextFrame("ux0:/data/capture.sgx");
razor_triggered = true;
}
this->transparencyEnabled = false;
SceGxmRenderTarget* renderTarget = this->m_data.frameBuffer->GetRenderTarget();
GXMDisplayBuffer* backBuffer = this->m_data.frameBuffer->backBuffer();
sceGxmBeginScene(
this->m_data.context,
0,
renderTarget,
//this->m_data.renderTarget,
nullptr,
nullptr,
backBuffer->sync,
&backBuffer->surface,
//this->m_data.renderBufferSync,
//&this->m_data.renderSurface,
&this->m_data.depthSurface
);
sceGxmSetViewport(this->m_data.context, 0, m_width, 0, m_height, 0, 0);
this->StartScene();
sceGxmSetFragmentUniformBuffer(this->m_data.context, 0, this->m_data.lightDataBuffer);
@ -874,17 +859,6 @@ HRESULT GXMRenderer::BeginFrame()
);
sceGxmSetFrontDepthFunc(this->m_data.context, SCE_GXM_DEPTH_FUNC_ALWAYS);
// clear screen
sceGxmSetVertexProgram(this->m_data.context, this->m_data.clearVertexProgram);
sceGxmSetFragmentProgram(this->m_data.context, this->m_data.clearFragmentProgram);
sceGxmSetVertexStream(this->m_data.context, 0, this->m_data.clearVerticies);
sceGxmDraw(
this->m_data.context,
SCE_GXM_PRIMITIVE_TRIANGLES,
SCE_GXM_INDEX_FORMAT_U16,
this->m_data.clearIndicies, 3
);
// set light data
int lightCount = std::min(static_cast<int>(m_lights.size()), 3);
@ -909,43 +883,44 @@ HRESULT GXMRenderer::BeginFrame()
lightData[i].direction[2] = src.direction.z;
lightData[i].direction[3] = src.directional;
}
sceGxmSetVertexProgram(this->m_data.context, this->m_data.mainVertexProgram);
sceGxmSetFragmentProgram(this->m_data.context, this->m_data.opaqueFragmentProgram);
return DD_OK;
}
void GXMRenderer::EnableTransparency()
{
sceGxmSetFragmentProgram(this->m_data.context, this->m_data.transparentFragmentProgram);
void GXMRenderer::EnableTransparency() {
this->transparencyEnabled = true;
}
void TransposeD3DRMMATRIX4D(const D3DRMMATRIX4D input, D3DRMMATRIX4D output) {
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
output[j][i] = input[i][j];
}
}
void transpose4x4(const float src[4][4], float dst[4][4]) {
for (int i = 0; i < 4; ++i)
for (int j = 0; j < 4; ++j)
dst[j][i] = src[i][j];
}
void GXMRenderer::SubmitDraw(
DWORD meshId,
const D3DRMMATRIX4D& modelViewMatrix,
const D3DRMMATRIX4D& worldMatrix,
const D3DRMMATRIX4D& viewMatrix,
const Matrix3x3& normalMatrix,
const Appearance& appearance
)
{
) {
auto& mesh = m_meshes[meshId];
sceGxmSetVertexProgram(this->m_data.context, this->m_data.mainVertexProgram);
if(this->transparencyEnabled) {
sceGxmSetFragmentProgram(this->m_data.context, this->m_data.transparentFragmentProgram);
} else {
sceGxmSetFragmentProgram(this->m_data.context, this->m_data.opaqueFragmentProgram);
}
void* vertUniforms;
void* fragUniforms;
sceGxmReserveVertexDefaultUniformBuffer(this->m_data.context, &vertUniforms);
sceGxmReserveFragmentDefaultUniformBuffer(this->m_data.context, &fragUniforms);
SET_UNIFORM(vertUniforms, this->m_data.uModelViewMatrixParam, modelViewMatrix);
SET_UNIFORM(vertUniforms, this->m_data.uNormalMatrixParam, normalMatrix);
SET_UNIFORM(vertUniforms, this->m_data.uProjectionMatrixParam, m_projection);
SET_UNIFORM(vertUniforms, this->m_data.uModelViewMatrixParam, modelViewMatrix, mainVertexProgramGxp);
SET_UNIFORM(vertUniforms, this->m_data.uNormalMatrixParam, normalMatrix, mainVertexProgramGxp);
SET_UNIFORM(vertUniforms, this->m_data.uProjectionMatrixParam, m_projection, mainVertexProgramGxp);
float color[4] = {
appearance.color.r / 255.0f,
@ -953,11 +928,11 @@ void GXMRenderer::SubmitDraw(
appearance.color.b / 255.0f,
appearance.color.a / 255.0f
};
SET_UNIFORM(fragUniforms, this->m_data.uColor, color);
SET_UNIFORM(fragUniforms, this->m_data.uShininess, appearance.shininess);
SET_UNIFORM(fragUniforms, this->m_data.uColor, color, mainFragmentProgramGxp);
SET_UNIFORM(fragUniforms, this->m_data.uShininess, appearance.shininess, mainFragmentProgramGxp);
int useTexture = appearance.textureId != NO_TEXTURE_ID ? 1 : 0;
SET_UNIFORM(fragUniforms, this->m_data.uUseTexture, useTexture);
SET_UNIFORM(fragUniforms, this->m_data.uUseTexture, useTexture, mainFragmentProgramGxp);
if(useTexture) {
auto& texture = m_textures[appearance.textureId];
sceGxmSetFragmentTexture(this->m_data.context, 0, &texture.gxmTexture);
@ -973,21 +948,174 @@ void GXMRenderer::SubmitDraw(
);
}
HRESULT GXMRenderer::FinalizeFrame()
{
sceGxmEndScene(
this->m_data.context,
nullptr, nullptr
);
/*
SDL_Surface* renderedImage = SDL_CreateSurfaceFrom(
m_width, m_height, SDL_PIXELFORMAT_ABGR8888,
this->m_data.renderBuffer, this->m_width*4
);
SDL_BlitSurface(renderedImage, nullptr, DDBackBuffer, nullptr);
SDL_DestroySurface(renderedImage);
*/
HRESULT GXMRenderer::FinalizeFrame() {
return DD_OK;
}
void GXMRenderer::Resize(int width, int height, const ViewportTransform& viewportTransform) {
m_width = width;
m_height = height;
m_viewportTransform = viewportTransform;
}
void GXMRenderer::Clear(float r, float g, float b) {
this->StartScene();
sceGxmSetVertexProgram(this->m_data.context, this->m_data.clearVertexProgram);
sceGxmSetFragmentProgram(this->m_data.context, this->m_data.clearFragmentProgram);
void* vertUniforms;
void* fragUniforms;
sceGxmReserveVertexDefaultUniformBuffer(this->m_data.context, &vertUniforms);
sceGxmReserveFragmentDefaultUniformBuffer(this->m_data.context, &fragUniforms);
float color[] = {r,g,b,1};
SET_UNIFORM(fragUniforms, this->m_data.clearShader_uColor, color, clearFragmentProgramGxp);
sceGxmSetVertexStream(this->m_data.context, 0, this->m_data.clearVerticies);
sceGxmDraw(
this->m_data.context,
SCE_GXM_PRIMITIVE_TRIANGLES,
SCE_GXM_INDEX_FORMAT_U16,
this->m_data.clearIndicies, 3
);
}
void GXMRenderer::Flip() {
if(this->sceneStarted) {
sceGxmEndScene(
this->m_data.context,
nullptr, nullptr
);
sceGxmPadHeartbeat(
&this->m_data.displayBuffersSurface[this->backBufferIndex],
this->m_data.displayBuffersSync[this->backBufferIndex]
);
this->sceneStarted = false;
}
GXMDisplayData displayData;
displayData.address = this->m_data.displayBuffers[this->backBufferIndex];
sceGxmDisplayQueueAddEntry(
this->m_data.displayBuffersSync[this->frontBufferIndex],
this->m_data.displayBuffersSync[this->backBufferIndex],
&displayData
);
this->frontBufferIndex = this->backBufferIndex;
this->backBufferIndex = (this->backBufferIndex + 1) % VITA_GXM_DISPLAY_BUFFER_COUNT;
}
void CreateOrthoMatrix(float left, float right, float bottom, float top, D3DRMMATRIX4D& outMatrix)
{
float near = -1.0f;
float far = 1.0f;
float rl = right - left;
float tb = top - bottom;
float fn = far - near;
outMatrix[0][0] = 2.0f / rl;
outMatrix[0][1] = 0.0f;
outMatrix[0][2] = 0.0f;
outMatrix[0][3] = 0.0f;
outMatrix[1][0] = 0.0f;
outMatrix[1][1] = 2.0f / tb;
outMatrix[1][2] = 0.0f;
outMatrix[1][3] = 0.0f;
outMatrix[2][0] = 0.0f;
outMatrix[2][1] = 0.0f;
outMatrix[2][2] = -2.0f / fn;
outMatrix[2][3] = 0.0f;
outMatrix[3][0] = -(right + left) / rl;
outMatrix[3][1] = -(top + bottom) / tb;
outMatrix[3][2] = -(far + near) / fn;
outMatrix[3][3] = 1.0f;
}
void GXMRenderer::Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect) {
this->StartScene();
sceGxmSetVertexProgram(this->m_data.context, this->m_data.mainVertexProgram);
sceGxmSetFragmentProgram(this->m_data.context, this->m_data.imageFragmentProgram);
void* vertUniforms;
void* fragUniforms;
sceGxmReserveVertexDefaultUniformBuffer(this->m_data.context, &vertUniforms);
sceGxmReserveFragmentDefaultUniformBuffer(this->m_data.context, &fragUniforms);
float left = -m_viewportTransform.offsetX / m_viewportTransform.scale;
float right = (m_width - m_viewportTransform.offsetX) / m_viewportTransform.scale;
float top = -m_viewportTransform.offsetY / m_viewportTransform.scale;
float bottom = (m_height - m_viewportTransform.offsetY) / m_viewportTransform.scale;
D3DRMMATRIX4D projection;
CreateOrthoMatrix(left, right, bottom, top, projection);
D3DRMMATRIX4D identity = {{1.f, 0.f, 0.f, 0.f}, {0.f, 1.f, 0.f, 0.f}, {0.f, 0.f, 1.f, 0.f}, {0.f, 0.f, 0.f, 1.f}};
SET_UNIFORM(vertUniforms, this->m_data.uModelViewMatrixParam, identity, mainVertexProgramGxp);
SET_UNIFORM(vertUniforms, this->m_data.uNormalMatrixParam, identity, mainVertexProgramGxp);
SET_UNIFORM(vertUniforms, this->m_data.uProjectionMatrixParam, m_projection, mainVertexProgramGxp);
const GXMTextureCacheEntry& texture = m_textures[textureId];
sceGxmSetFragmentTexture(this->m_data.context, 0, &texture.gxmTexture);
float texW = sceGxmTextureGetWidth(&texture.gxmTexture);
float texH = sceGxmTextureGetHeight(&texture.gxmTexture);
float u1 = srcRect.x / texW;
float v1 = srcRect.y / texH;
float u2 = (srcRect.x + srcRect.w) / texW;
float v2 = (srcRect.y + srcRect.h) / texH;
float x1 = static_cast<float>(dstRect.x);
float y1 = static_cast<float>(dstRect.y);
float x2 = x1 + dstRect.w;
float y2 = y1 + dstRect.h;
void* meshBuffer = sceClibMspaceMalloc(this->m_data.cdramPool, 4*sizeof(Vertex) + 4*sizeof(uint16_t));
Vertex* gpuVertices = (Vertex*)meshBuffer;
uint16_t* gpuIndices = (uint16_t*)(((uint8_t*)meshBuffer) + 4*sizeof(Vertex));
gpuVertices[0] = Vertex{ .position = {x1, y1, 0}, .normal = {0,0,0}, .texCoord = {u1, v1}};
gpuVertices[1] = Vertex{ .position = {x2, y1, 0}, .normal = {0,0,0}, .texCoord = {u2, v1}};
gpuVertices[2] = Vertex{ .position = {x1, y2, 0}, .normal = {0,0,0}, .texCoord = {u1, v2}};
gpuVertices[3] = Vertex{ .position = {x2, y2, 0}, .normal = {0,0,0}, .texCoord = {u2, v2}};
gpuIndices[0] = 0;
gpuIndices[1] = 1;
gpuIndices[2] = 2;
gpuIndices[3] = 3;
sceGxmSetVertexStream(this->m_data.context, 0, gpuVertices);
sceGxmDraw(
this->m_data.context,
SCE_GXM_PRIMITIVE_TRIANGLE_STRIP,
SCE_GXM_INDEX_FORMAT_U16,
gpuIndices, 4
);
sceClibMspaceFree(this->m_data.cdramPool, meshBuffer);
}
void GXMRenderer::Download(SDL_Surface* target) {
SDL_Surface* src = SDL_CreateSurfaceFrom(
this->m_width, this->m_height,
SDL_PIXELFORMAT_RGBA32,
this->m_data.displayBuffers[this->backBufferIndex], VITA_GXM_SCREEN_STRIDE
);
SDL_Rect srcRect = {
static_cast<int>(m_viewportTransform.offsetX),
static_cast<int>(m_viewportTransform.offsetY),
static_cast<int>(target->w * m_viewportTransform.scale),
static_cast<int>(target->h * m_viewportTransform.scale),
};
SDL_BlitSurfaceScaled(src, &srcRect, target, nullptr, SDL_SCALEMODE_NEAREST);
}

View File

@ -15,19 +15,14 @@
#define ALIGN(x, a) (((x) + ((a)-1)) & ~((a)-1))
#define INCBIN(filename, symbol) \
__asm__( \
".balign 16 \n" \
#symbol ":" \
".incbin \"" filename "\"" \
); \
extern const void* symbol
#define SET_UNIFORM(buffer, param, value) \
#define SET_UNIFORM(buffer, param, value, program) \
do { \
size_t __offset = sceGxmProgramParameterGetResourceIndex(param); \
void* __dst = (uint8_t*)(buffer) + (__offset * sizeof(uint32_t)); \
memcpy(__dst, reinterpret_cast<const void*>(&(value)), sizeof(value)); \
/*SDL_Log("set uniform param=%s offset=%d size=%d buffer_size=%d", \
sceGxmProgramParameterGetName(param), __offset*4, sizeof(value), sceGxmProgramGetDefaultUniformBufferSize(program));*/ \
} while (0)
#define GET_SHADER_PARAM(var, gxp, name, ret) \
@ -36,10 +31,3 @@
SDL_Log("Failed to find param %s", name); \
return ret; \
}
extern const SceGxmProgram* blitVertexProgramGxp;
extern const SceGxmProgram* blitColorFragmentProgramGxp;
extern const SceGxmProgram* blitTexFragmentProgramGxp;
bool get_gxm_context(SceGxmContext** context, SceGxmShaderPatcher** shaderPatcher, SceClibMspace* cdramPool);

View File

@ -173,7 +173,7 @@ HRESULT Direct3DRMImpl::CreateDeviceFromSurface(
#endif
#ifdef __vita__
else if (SDL_memcmp(&guid, &GXM_GUID, sizeof(GUID)) == 0) {
DDRenderer = GXMRenderer::Create(surface);
DDRenderer = GXMRenderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight);
}
#endif
else {

View File

@ -227,7 +227,7 @@ HRESULT DirectDrawImpl::EnumDevices(LPD3DENUMDEVICESCALLBACK cb, void* ctx)
Direct3DRMSDL3GPU_EnumDevice(cb, ctx);
#endif
#ifdef USE_OPENGLES2
//OpenGLES2Renderer_EnumDevice(cb, ctx);
OpenGLES2Renderer_EnumDevice(cb, ctx);
#endif
#ifdef USE_OPENGL1
OpenGL1Renderer_EnumDevice(cb, ctx);
@ -236,9 +236,9 @@ HRESULT DirectDrawImpl::EnumDevices(LPD3DENUMDEVICESCALLBACK cb, void* ctx)
DirectX9Renderer_EnumDevice(cb, ctx);
#endif
#ifdef __vita__
//GXMRenderer_EnumDevice(cb, ctx);
GXMRenderer_EnumDevice(cb, ctx);
#endif
Direct3DRMSoftware_EnumDevice(cb, ctx);
//Direct3DRMSoftware_EnumDevice(cb, ctx);
return S_OK;
}
@ -365,7 +365,7 @@ HRESULT DirectDrawImpl::CreateDevice(
#endif
#ifdef __vita__
else if (SDL_memcmp(&guid, &GXM_GUID, sizeof(GUID)) == 0) {
DDRenderer = GXMRenderer::Create(pBackBuffer);
DDRenderer = GXMRenderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight);
}
#endif
else if (SDL_memcmp(&guid, &SOFTWARE_GUID, sizeof(GUID)) == 0) {

View File

@ -32,6 +32,10 @@ struct GXMMeshCacheEntry {
uint16_t indexCount;
};
typedef struct GXMDisplayData {
void* address;
} GXMDisplayData;
typedef struct GXMRendererContext {
// context
SceUID vdmRingBufferUid;
@ -70,14 +74,11 @@ typedef struct GXMRendererData {
SceGxmShaderPatcher* shaderPatcher;
SceClibMspace cdramPool;
// color buffer
/*
SceGxmRenderTarget* renderTarget;
SceUID renderBufferUid;
void* renderBuffer;
SceGxmColorSurface renderSurface;
SceGxmSyncObject* renderBufferSync;
*/
void* displayBuffers[VITA_GXM_DISPLAY_BUFFER_COUNT];
SceUID displayBuffersUid[VITA_GXM_DISPLAY_BUFFER_COUNT];
SceGxmColorSurface displayBuffersSurface[VITA_GXM_DISPLAY_BUFFER_COUNT];
SceGxmSyncObject* displayBuffersSync[VITA_GXM_DISPLAY_BUFFER_COUNT];
// depth buffer
SceUID depthBufferUid;
@ -95,9 +96,11 @@ typedef struct GXMRendererData {
// main shader
SceGxmShaderPatcherId mainVertexProgramId;
SceGxmShaderPatcherId mainFragmentProgramId;
SceGxmShaderPatcherId imageFragmentProgramId;
SceGxmVertexProgram* mainVertexProgram;
SceGxmFragmentProgram* opaqueFragmentProgram;
SceGxmFragmentProgram* transparentFragmentProgram;
SceGxmFragmentProgram* opaqueFragmentProgram; // 3d with no transparency
SceGxmFragmentProgram* transparentFragmentProgram; // 3d with transparency
SceGxmFragmentProgram* imageFragmentProgram; // 2d images, no lighting
// main shader vertex uniforms
const SceGxmProgramParameter* uModelViewMatrixParam;
@ -111,6 +114,8 @@ typedef struct GXMRendererData {
const SceGxmProgramParameter* uColor;
const SceGxmProgramParameter* uUseTexture;
const SceGxmProgramParameter* clearShader_uColor;
// clear mesh
void* clearMeshBuffer;
float* clearVerticies;
@ -118,13 +123,11 @@ typedef struct GXMRendererData {
// scene light data
void* lightDataBuffer;
FrameBufferImpl* frameBuffer;
} GXMRendererData;
class GXMRenderer : public Direct3DRMRenderer {
public:
static Direct3DRMRenderer* Create(IDirectDrawSurface* surface);
static Direct3DRMRenderer* Create(DWORD width, DWORD height);
GXMRenderer(
DWORD width,
DWORD height,
@ -138,8 +141,6 @@ class GXMRenderer : public Direct3DRMRenderer {
void SetFrustumPlanes(const Plane* frustumPlanes) override;
Uint32 GetTextureId(IDirect3DRMTexture* texture) override;
Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override;
DWORD GetWidth() override;
DWORD GetHeight() override;
void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override;
const char* GetName() override;
HRESULT BeginFrame() override;
@ -147,26 +148,38 @@ class GXMRenderer : public Direct3DRMRenderer {
void SubmitDraw(
DWORD meshId,
const D3DRMMATRIX4D& modelViewMatrix,
const D3DRMMATRIX4D& worldMatrix,
const D3DRMMATRIX4D& viewMatrix,
const Matrix3x3& normalMatrix,
const Appearance& appearance
) override;
HRESULT FinalizeFrame() override;
void Resize(int width, int height, const ViewportTransform& viewportTransform) override;
void Clear(float r, float g, float b) override;
void Flip() override;
void Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect) override;
void Download(SDL_Surface* target) override;
private:
void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture);
void AddMeshDestroyCallback(Uint32 id, IDirect3DRMMesh* mesh);
void* AllocateGpu(size_t size, size_t align = 4);
void FreeGpu(void* ptr);
GXMMeshCacheEntry GXMUploadMesh(const MeshGroup& meshGroup);
void StartScene();
std::vector<GXMTextureCacheEntry> m_textures;
std::vector<GXMMeshCacheEntry> m_meshes;
D3DRMMATRIX4D m_projection;
DWORD m_width, m_height;
std::vector<SceneLight> m_lights;
bool transparencyEnabled = false;
bool sceneStarted = false;
int backBufferIndex = 0;
int frontBufferIndex = 1;
GXMRendererData m_data;
bool m_initialized = false;
};

View File

@ -1,9 +1,5 @@
#pragma once
#ifdef __vita__
#include "framebuffer_impl_vita.h"
#else
#include <SDL3/SDL.h>
#include <ddsurface_impl.h>
#include <miniwin/ddraw.h>
@ -46,4 +42,3 @@ struct FrameBufferImpl : public IDirectDrawSurface3 {
DirectDrawSurfaceImpl* m_transferBuffer;
IDirectDrawPalette* m_palette = nullptr;
};
#endif