mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-14 10:21:21 +00:00
Merge pull request #1806 from RPCS3/WIP
WIP Shaders Decompiler (OpenGL only)
This commit is contained in:
commit
d22ac91ee1
@ -46,7 +46,7 @@ before_install:
|
||||
fi;
|
||||
|
||||
before_script:
|
||||
- git submodule update --init asmjit 3rdparty/ffmpeg 3rdparty/pugixml 3rdparty/GSL 3rdparty/libpng Vulkan/glslang Vulkan/Vulkan-LoaderAndValidationLayers Utilities/yaml-cpp
|
||||
- git submodule update --init rsx_program_decompiler asmjit 3rdparty/ffmpeg 3rdparty/pugixml 3rdparty/GSL 3rdparty/libpng Vulkan/glslang Vulkan/Vulkan-LoaderAndValidationLayers Utilities/yaml-cpp
|
||||
- mkdir build
|
||||
- cd build
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then cmake ..; else cmake .. -DLLVM_DIR=/usr/local/opt/llvm36/lib/llvm-3.6/share/llvm/cmake; fi
|
||||
|
@ -23,4 +23,4 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${PROJECT_BINARY_DIR}/bin")
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${PROJECT_BINARY_DIR}/bin")
|
||||
add_subdirectory( Vulkan )
|
||||
add_subdirectory( rpcs3 )
|
||||
|
||||
add_subdirectory( rsx_program_decompiler )
|
||||
|
@ -10,7 +10,7 @@ test: off
|
||||
|
||||
before_build:
|
||||
# until git for win 2.5 release with commit checkout
|
||||
- git submodule update --init 3rdparty/ffmpeg 3rdparty/pugixml asmjit 3rdparty/GSL 3rdparty/libpng Vulkan/glslang Vulkan/Vulkan-LoaderAndValidationLayers Utilities/yaml-cpp
|
||||
- git submodule update --init 3rdparty/ffmpeg 3rdparty/pugixml asmjit 3rdparty/GSL 3rdparty/libpng Vulkan/glslang Vulkan/Vulkan-LoaderAndValidationLayers Utilities/yaml-cpp rsx_program_decompiler
|
||||
- 7z x wxWidgets.7z -aos -oC:\rpcs3\wxWidgets > null
|
||||
- 7z x zlib.7z -aos -oC:\rpcs3\ > null
|
||||
- if %configuration%==Release (cmake -G "Visual Studio 14 Win64" -DZLIB_ROOT=C:/rpcs3/zlib/)
|
||||
|
4
bin/data/.gitignore
vendored
Normal file
4
bin/data/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
# Ignore everything in this directory
|
||||
*
|
||||
# Except this file
|
||||
!.gitignore
|
4
bin/data/cache/.gitignore
vendored
Normal file
4
bin/data/cache/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
# Ignore everything in this directory
|
||||
*
|
||||
# Except this file
|
||||
!.gitignore
|
@ -18,6 +18,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rpcs3", "rpcs3\rpcs3.vcxpro
|
||||
{A1A8355B-0988-528E-9CC2-B971D6266669} = {A1A8355B-0988-528E-9CC2-B971D6266669}
|
||||
{09F2F96A-1CC6-5E43-AF1D-956EC2A4888D} = {09F2F96A-1CC6-5E43-AF1D-956EC2A4888D}
|
||||
{D6973076-9317-4EF2-A0B8-B7A18AC0713E} = {D6973076-9317-4EF2-A0B8-B7A18AC0713E}
|
||||
{97E17077-A21F-45EF-9C3A-73A0BC092D7E} = {97E17077-A21F-45EF-9C3A-73A0BC092D7E}
|
||||
{7D73447B-3D2D-4DFE-BF62-57E644C1D09F} = {7D73447B-3D2D-4DFE-BF62-57E644C1D09F}
|
||||
{8B867186-A0B5-5479-B824-E176EDD27C40} = {8B867186-A0B5-5479-B824-E176EDD27C40}
|
||||
{87B42A9C-3F5C-53D7-9017-2B1CAE39457D} = {87B42A9C-3F5C-53D7-9017-2B1CAE39457D}
|
||||
{8BC303AB-25BE-4276-8E57-73F171B2D672} = {8BC303AB-25BE-4276-8E57-73F171B2D672}
|
||||
|
@ -128,6 +128,8 @@ ${LLVM_INCLUDE_DIRS}
|
||||
# Includes 3rdparty stuff that isn't included yet
|
||||
"${RPCS3_SRC_DIR}/../3rdparty/GL"
|
||||
"${RPCS3_SRC_DIR}/../3rdparty/stblib"
|
||||
"${RPCS3_SRC_DIR}/../rsx_program_decompiler/rsx_decompiler"
|
||||
"${RPCS3_SRC_DIR}/../rsx_program_decompiler/shader_code"
|
||||
)
|
||||
if(WIN32)
|
||||
include_directories(BEFORE "${RPCS3_SRC_DIR}/../3rdparty/XAudio2_7") # Slimmed down version of minidx9 for XAudio2_7 only
|
||||
@ -205,5 +207,7 @@ if(LLVM_FOUND)
|
||||
target_link_libraries(rpcs3 ${LLVM_LIBS})
|
||||
endif()
|
||||
|
||||
target_link_libraries(rpcs3 rsx_decompiler shader_code)
|
||||
|
||||
set_target_properties(rpcs3 PROPERTIES COTIRE_CXX_PREFIX_HEADER_INIT "${RPCS3_SRC_DIR}/stdafx.h")
|
||||
cotire(rpcs3)
|
||||
|
@ -61,6 +61,31 @@
|
||||
<Import Project="..\rpcs3_llvm.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug - MemLeak|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\rsx_program_decompiler\rsx_decompiler;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\rsx_program_decompiler\rsx_decompiler;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\rsx_program_decompiler\rsx_decompiler;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\rsx_program_decompiler\rsx_decompiler;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\rsx_program_decompiler\rsx_decompiler;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Emu\RSX\D3D12\D3D12Utils.h" />
|
||||
<ClInclude Include="Emu\RSX\D3D12\D3D12CommonDecompiler.h" />
|
||||
|
@ -453,6 +453,10 @@ void stream_vector(void *dst, u32 x, u32 y, u32 z, u32 w)
|
||||
_mm_stream_si128((__m128i*)dst, vector);
|
||||
}
|
||||
|
||||
void stream_vector(void *dst, f32 x, f32 y, f32 z, f32 w)
|
||||
{
|
||||
stream_vector(dst, (u32&)x, (u32&)y, (u32&)z, (u32&)w);
|
||||
}
|
||||
void stream_vector_from_memory(void *dst, void *src)
|
||||
{
|
||||
const __m128i &vector = _mm_loadu_si128((__m128i*)src);
|
||||
|
@ -49,6 +49,7 @@ void write_index_array_for_non_indexed_non_native_primitive_to_buffer(char* dst,
|
||||
/**
|
||||
* Stream a 128 bits vector to dst.
|
||||
*/
|
||||
void stream_vector(void *dst, f32 x, f32 y, f32 z, f32 w);
|
||||
void stream_vector(void *dst, u32 x, u32 y, u32 z, u32 w);
|
||||
|
||||
/**
|
||||
|
@ -1,10 +1,11 @@
|
||||
#include "stdafx.h"
|
||||
#include "Utilities/Config.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
#include "GLGSRender.h"
|
||||
#include "rsx_gl_cache.h"
|
||||
#include "../rsx_methods.h"
|
||||
#include "../Common/BufferUtils.h"
|
||||
#include "../rsx_utils.h"
|
||||
|
||||
extern cfg::bool_entry g_cfg_rsx_debug_output;
|
||||
extern cfg::bool_entry g_cfg_rsx_overlay;
|
||||
@ -26,7 +27,7 @@ namespace
|
||||
|
||||
GLGSRender::GLGSRender() : GSRender(frame_type::OpenGL)
|
||||
{
|
||||
shaders_cache.load(rsx::shader_language::glsl);
|
||||
init_glsl_cache_program_context(programs_cache.context);
|
||||
}
|
||||
|
||||
u32 GLGSRender::enable(u32 condition, u32 cap)
|
||||
@ -151,7 +152,8 @@ void GLGSRender::begin()
|
||||
__glcheck glStencilOp(rsx::method_registers[NV4097_SET_STENCIL_OP_FAIL], rsx::method_registers[NV4097_SET_STENCIL_OP_ZFAIL],
|
||||
rsx::method_registers[NV4097_SET_STENCIL_OP_ZPASS]);
|
||||
|
||||
if (rsx::method_registers[NV4097_SET_TWO_SIDED_STENCIL_TEST_ENABLE]) {
|
||||
if (rsx::method_registers[NV4097_SET_TWO_SIDED_STENCIL_TEST_ENABLE])
|
||||
{
|
||||
__glcheck glStencilMaskSeparate(GL_BACK, rsx::method_registers[NV4097_SET_BACK_STENCIL_MASK]);
|
||||
__glcheck glStencilFuncSeparate(GL_BACK, rsx::method_registers[NV4097_SET_BACK_STENCIL_FUNC],
|
||||
rsx::method_registers[NV4097_SET_BACK_STENCIL_FUNC_REF], rsx::method_registers[NV4097_SET_BACK_STENCIL_FUNC_MASK]);
|
||||
@ -213,13 +215,42 @@ void GLGSRender::begin()
|
||||
u8 clip_plane_4 = (clip_plane_control >> 16) & 0xf;
|
||||
u8 clip_plane_5 = (clip_plane_control >> 20) & 0xf;
|
||||
|
||||
//TODO
|
||||
if (__glcheck enable(clip_plane_0, GL_CLIP_DISTANCE0)) {}
|
||||
if (__glcheck enable(clip_plane_1, GL_CLIP_DISTANCE1)) {}
|
||||
if (__glcheck enable(clip_plane_2, GL_CLIP_DISTANCE2)) {}
|
||||
if (__glcheck enable(clip_plane_3, GL_CLIP_DISTANCE3)) {}
|
||||
if (__glcheck enable(clip_plane_4, GL_CLIP_DISTANCE4)) {}
|
||||
if (__glcheck enable(clip_plane_5, GL_CLIP_DISTANCE5)) {}
|
||||
auto set_clip_plane_control = [&](int index, u8 control)
|
||||
{
|
||||
int value = 0;
|
||||
int location;
|
||||
if (m_program->uniforms.has_location("uc_m" + std::to_string(index), &location))
|
||||
{
|
||||
switch (control)
|
||||
{
|
||||
default:
|
||||
LOG_ERROR(RSX, "bad clip plane control (0x%x)", control);
|
||||
|
||||
case CELL_GCM_USER_CLIP_PLANE_DISABLE:
|
||||
value = 0;
|
||||
break;
|
||||
|
||||
case CELL_GCM_USER_CLIP_PLANE_ENABLE_GE:
|
||||
value = 1;
|
||||
break;
|
||||
|
||||
case CELL_GCM_USER_CLIP_PLANE_ENABLE_LT:
|
||||
value = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
__glcheck m_program->uniforms[location] = value;
|
||||
}
|
||||
|
||||
__glcheck enable(value, GL_CLIP_DISTANCE0 + index);
|
||||
};
|
||||
|
||||
set_clip_plane_control(0, clip_plane_0);
|
||||
set_clip_plane_control(1, clip_plane_1);
|
||||
set_clip_plane_control(2, clip_plane_2);
|
||||
set_clip_plane_control(3, clip_plane_3);
|
||||
set_clip_plane_control(4, clip_plane_4);
|
||||
set_clip_plane_control(5, clip_plane_5);
|
||||
|
||||
__glcheck enable(rsx::method_registers[NV4097_SET_POLY_OFFSET_FILL_ENABLE], GL_POLYGON_OFFSET_FILL);
|
||||
|
||||
@ -228,8 +259,6 @@ void GLGSRender::begin()
|
||||
__glcheck glCullFace(rsx::method_registers[NV4097_SET_CULL_FACE]);
|
||||
}
|
||||
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
__glcheck glFrontFace(rsx::method_registers[NV4097_SET_FRONT_FACE] ^ 1);
|
||||
|
||||
__glcheck enable(rsx::method_registers[NV4097_SET_POLY_SMOOTH_ENABLE], GL_POLYGON_SMOOTH);
|
||||
@ -246,7 +275,7 @@ void GLGSRender::begin()
|
||||
}
|
||||
|
||||
std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();
|
||||
m_begin_time += std::chrono::duration_cast<std::chrono::microseconds>(now - then).count();
|
||||
m_begin_time += (u32)std::chrono::duration_cast<std::chrono::microseconds>(now - then).count();
|
||||
m_draw_calls++;
|
||||
}
|
||||
|
||||
@ -277,46 +306,81 @@ void GLGSRender::end()
|
||||
m_program->use();
|
||||
|
||||
//setup textures
|
||||
for (int i = 0; i < rsx::limits::textures_count; ++i)
|
||||
{
|
||||
int location;
|
||||
if (m_program->uniforms.has_location("tex" + std::to_string(i), &location))
|
||||
int texture_index = 0;
|
||||
for (int i = 0; i < rsx::limits::textures_count; ++i)
|
||||
{
|
||||
if (!textures[i].enabled())
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + i);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glProgramUniform1i(m_program->id(), location, i);
|
||||
continue;
|
||||
}
|
||||
|
||||
m_gl_textures[i].set_target(get_gl_target_for_texture(textures[i]));
|
||||
int location;
|
||||
if (m_program->uniforms.has_location("texture" + std::to_string(i), &location))
|
||||
{
|
||||
__glcheck glProgramUniform1i(m_program->id(), location, texture_index);
|
||||
__glcheck m_gl_textures[i].init(texture_index, textures[i]);
|
||||
|
||||
__glcheck m_gl_texture_cache.upload_texture(i, textures[i], m_gl_textures[i], m_rtts);
|
||||
glProgramUniform1i(m_program->id(), location, i);
|
||||
texture_index++;
|
||||
|
||||
if (m_program->uniforms.has_location("texture" + std::to_string(i) + "_cm", &location))
|
||||
{
|
||||
if (textures[i].format() & CELL_GCM_TEXTURE_UN)
|
||||
{
|
||||
//glProgramUniform4f(m_program->id(), location, textures[i].width(), textures[i].height(), textures[i].depth(), 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
for (int i = 0; i < rsx::limits::vertex_textures_count; ++i)
|
||||
{
|
||||
if (vertex_textures[i].enabled())
|
||||
{
|
||||
int location;
|
||||
if (m_program->uniforms.has_location("vtexture" + std::to_string(i), &location))
|
||||
{
|
||||
glProgramUniform1i(m_program->id(), location, texture_index);
|
||||
m_gl_vertex_textures[i].init(texture_index, vertex_textures[i]);
|
||||
texture_index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
__glcheck 0;
|
||||
|
||||
u32 offset_in_index_buffer = set_vertex_buffer();
|
||||
m_vao.bind();
|
||||
|
||||
std::chrono::time_point<std::chrono::system_clock> then = std::chrono::system_clock::now();
|
||||
|
||||
if (g_cfg_rsx_debug_output)
|
||||
{
|
||||
m_program->validate();
|
||||
}
|
||||
|
||||
if (draw_command == rsx::draw_command::indexed)
|
||||
{
|
||||
rsx::index_array_type indexed_type = rsx::to_index_array_type(rsx::method_registers[NV4097_SET_INDEX_ARRAY_DMA] >> 4);
|
||||
|
||||
if (indexed_type == rsx::index_array_type::u32)
|
||||
__glcheck glDrawElements(gl::draw_mode(draw_mode), vertex_draw_count, GL_UNSIGNED_INT, (GLvoid *)(offset_in_index_buffer));
|
||||
if (indexed_type == rsx::index_array_type::u16)
|
||||
__glcheck glDrawElements(gl::draw_mode(draw_mode), vertex_draw_count, GL_UNSIGNED_SHORT, (GLvoid *)(offset_in_index_buffer));
|
||||
{
|
||||
__glcheck glDrawElements(gl::draw_mode(draw_mode), vertex_draw_count, GL_UNSIGNED_INT, (GLvoid *)(std::ptrdiff_t)offset_in_index_buffer);
|
||||
}
|
||||
else if (indexed_type == rsx::index_array_type::u16)
|
||||
{
|
||||
__glcheck glDrawElements(gl::draw_mode(draw_mode), vertex_draw_count, GL_UNSIGNED_SHORT, (GLvoid *)(std::ptrdiff_t)offset_in_index_buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::logic_error("bad index array type");
|
||||
}
|
||||
}
|
||||
else if (!is_primitive_native(draw_mode))
|
||||
{
|
||||
__glcheck glDrawElements(gl::draw_mode(draw_mode), vertex_draw_count, GL_UNSIGNED_SHORT, (GLvoid *)(offset_in_index_buffer));
|
||||
__glcheck glDrawElements(gl::draw_mode(draw_mode), vertex_draw_count, GL_UNSIGNED_SHORT, (GLvoid *)(std::ptrdiff_t)offset_in_index_buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -324,7 +388,7 @@ void GLGSRender::end()
|
||||
}
|
||||
|
||||
std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();
|
||||
m_draw_time += std::chrono::duration_cast<std::chrono::microseconds>(now - then).count();
|
||||
m_draw_time += (u32)std::chrono::duration_cast<std::chrono::microseconds>(now - then).count();
|
||||
|
||||
write_buffers();
|
||||
|
||||
@ -352,8 +416,7 @@ void GLGSRender::set_viewport()
|
||||
|
||||
rsx::window_origin shader_window_origin = rsx::to_window_origin((shader_window >> 12) & 0xf);
|
||||
|
||||
//TODO
|
||||
if (true || shader_window_origin == rsx::window_origin::bottom)
|
||||
if (shader_window_origin == rsx::window_origin::bottom)
|
||||
{
|
||||
__glcheck glViewport(viewport_x, viewport_y, viewport_w, viewport_h);
|
||||
__glcheck glScissor(scissor_x, scissor_y, scissor_w, scissor_h);
|
||||
@ -362,11 +425,13 @@ void GLGSRender::set_viewport()
|
||||
{
|
||||
u16 shader_window_height = shader_window & 0xfff;
|
||||
|
||||
__glcheck glViewport(viewport_x, shader_window_height - viewport_y - viewport_h - 1, viewport_w, viewport_h);
|
||||
__glcheck glScissor(scissor_x, shader_window_height - scissor_y - scissor_h - 1, scissor_w, scissor_h);
|
||||
__glcheck glViewport(viewport_x, shader_window_height - viewport_y - viewport_h + 1, viewport_w, viewport_h);
|
||||
__glcheck glScissor(scissor_x, shader_window_height - scissor_y - scissor_h + 1, scissor_w, scissor_h);
|
||||
}
|
||||
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
|
||||
__glcheck 0;
|
||||
}
|
||||
|
||||
void GLGSRender::on_init_thread()
|
||||
@ -381,6 +446,7 @@ void GLGSRender::on_init_thread()
|
||||
LOG_NOTICE(RSX, "%s", (const char*)glGetString(GL_VENDOR));
|
||||
|
||||
glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
|
||||
glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &m_uniform_buffer_offset_align);
|
||||
glGetIntegerv(GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT, &m_min_texbuffer_alignment);
|
||||
m_vao.create();
|
||||
|
||||
@ -390,11 +456,11 @@ void GLGSRender::on_init_thread()
|
||||
tex.set_target(gl::texture::target::textureBuffer);
|
||||
}
|
||||
|
||||
m_attrib_ring_buffer.reset(new gl::ring_buffer(16 * 0x100000, gl::buffer::target::texture));
|
||||
m_uniform_ring_buffer.reset(new gl::ring_buffer(16 * 0x100000, gl::buffer::target::uniform));
|
||||
m_index_ring_buffer.reset(new gl::ring_buffer(0x100000, gl::buffer::target::element_array));
|
||||
m_attrib_ring_buffer.create(gl::buffer::target::texture, 16 * 0x100000);
|
||||
m_uniform_ring_buffer.create(gl::buffer::target::uniform, 16 * 0x100000);
|
||||
m_index_ring_buffer.create(gl::buffer::target::element_array, 0x100000);
|
||||
|
||||
m_vao.element_array_buffer = m_index_ring_buffer->get_buffer();
|
||||
m_vao.element_array_buffer = m_index_ring_buffer;
|
||||
m_gl_texture_cache.initialize_rtt_cache();
|
||||
}
|
||||
|
||||
@ -402,7 +468,7 @@ void GLGSRender::on_exit()
|
||||
{
|
||||
glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
|
||||
|
||||
m_prog_buffer.clear();
|
||||
programs_cache.clear();
|
||||
|
||||
if (draw_fbo)
|
||||
draw_fbo.remove();
|
||||
@ -421,15 +487,18 @@ void GLGSRender::on_exit()
|
||||
tex.remove();
|
||||
}
|
||||
|
||||
m_attrib_ring_buffer->destroy();
|
||||
m_uniform_ring_buffer->destroy();
|
||||
m_index_ring_buffer->destroy();
|
||||
m_attrib_ring_buffer.remove();
|
||||
m_uniform_ring_buffer.remove();
|
||||
m_index_ring_buffer.remove();
|
||||
}
|
||||
|
||||
void nv4097_clear_surface(u32 arg, GLGSRender* renderer)
|
||||
{
|
||||
//LOG_NOTICE(Log::RSX, "nv4097_clear_surface(0x%x)", arg);
|
||||
if (!rsx::method_registers[NV4097_SET_SURFACE_FORMAT]) return;
|
||||
if (!rsx::method_registers[NV4097_SET_SURFACE_FORMAT])
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ((arg & 0xf3) == 0)
|
||||
{
|
||||
@ -450,9 +519,10 @@ void nv4097_clear_surface(u32 arg, GLGSRender* renderer)
|
||||
|
||||
GLbitfield mask = 0;
|
||||
|
||||
rsx::surface_depth_format surface_depth_format = rsx::to_surface_depth_format((rsx::method_registers[NV4097_SET_SURFACE_FORMAT] >> 5) & 0x7);
|
||||
|
||||
if (arg & 0x1)
|
||||
{
|
||||
rsx::surface_depth_format surface_depth_format = rsx::to_surface_depth_format((rsx::method_registers[NV4097_SET_SURFACE_FORMAT] >> 5) & 0x7);
|
||||
u32 max_depth_value = get_max_depth_value(surface_depth_format);
|
||||
|
||||
u32 clear_depth = rsx::method_registers[NV4097_SET_ZSTENCIL_CLEAR_VALUE] >> 8;
|
||||
@ -462,7 +532,7 @@ void nv4097_clear_surface(u32 arg, GLGSRender* renderer)
|
||||
mask |= GLenum(gl::buffers::depth);
|
||||
}
|
||||
|
||||
if (arg & 0x2)
|
||||
if (surface_depth_format == rsx::surface_depth_format::z24s8 && arg & 0x2)
|
||||
{
|
||||
u8 clear_stencil = rsx::method_registers[NV4097_SET_ZSTENCIL_CLEAR_VALUE] & 0xff;
|
||||
|
||||
@ -510,93 +580,147 @@ bool GLGSRender::do_method(u32 cmd, u32 arg)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GLGSRender::load_program()
|
||||
//binding 0
|
||||
struct alignas(4) glsl_matrix_buffer
|
||||
{
|
||||
#if 1
|
||||
RSXVertexProgram vertex_program = get_current_vertex_program();
|
||||
RSXFragmentProgram fragment_program = get_current_fragment_program();
|
||||
float viewport_matrix[4][4];
|
||||
float window_matrix[4][4];
|
||||
float normalize_matrix[4][4];
|
||||
};
|
||||
|
||||
__glcheck m_program = &m_prog_buffer.getGraphicPipelineState(vertex_program, fragment_program, nullptr);
|
||||
__glcheck m_program->use();
|
||||
//binding 1
|
||||
struct alignas(4) glsl_vertex_constants_buffer
|
||||
{
|
||||
float vc[468][4];
|
||||
};
|
||||
|
||||
#else
|
||||
std::vector<u32> vertex_program;
|
||||
u32 transform_program_start = rsx::method_registers[NV4097_SET_TRANSFORM_PROGRAM_START];
|
||||
vertex_program.reserve((512 - transform_program_start) * 4);
|
||||
//binding 2
|
||||
struct alignas(4) glsl_fragment_constants_buffer
|
||||
{
|
||||
float fc[2048][4];
|
||||
};
|
||||
|
||||
for (int i = transform_program_start; i < 512; ++i)
|
||||
static void fill_matrix_buffer(glsl_matrix_buffer *buffer)
|
||||
{
|
||||
rsx::fill_viewport_matrix(buffer->viewport_matrix, true);
|
||||
rsx::fill_window_matrix(buffer->window_matrix, true);
|
||||
|
||||
u32 viewport_horizontal = rsx::method_registers[NV4097_SET_VIEWPORT_HORIZONTAL];
|
||||
u32 viewport_vertical = rsx::method_registers[NV4097_SET_VIEWPORT_VERTICAL];
|
||||
|
||||
f32 viewport_x = f32(viewport_horizontal & 0xffff);
|
||||
f32 viewport_y = f32(viewport_vertical & 0xffff);
|
||||
f32 viewport_w = f32(viewport_horizontal >> 16);
|
||||
f32 viewport_h = f32(viewport_vertical >> 16);
|
||||
|
||||
u32 shader_window = rsx::method_registers[NV4097_SET_SHADER_WINDOW];
|
||||
|
||||
rsx::window_origin shader_window_origin = rsx::to_window_origin((shader_window >> 12) & 0xf);
|
||||
u16 shader_window_height = shader_window & 0xfff;
|
||||
|
||||
f32 left = viewport_x;
|
||||
f32 right = viewport_x + viewport_w;
|
||||
f32 top = viewport_y;
|
||||
f32 bottom = viewport_y + viewport_h;
|
||||
//f32 far_ = (f32&)rsx::method_registers[NV4097_SET_CLIP_MAX];
|
||||
//f32 near_ = (f32&)rsx::method_registers[NV4097_SET_CLIP_MIN];
|
||||
|
||||
if (shader_window_origin == rsx::window_origin::bottom)
|
||||
{
|
||||
vertex_program.resize((i - transform_program_start) * 4 + 4);
|
||||
memcpy(vertex_program.data() + (i - transform_program_start) * 4, transform_program + i * 4, 4 * sizeof(u32));
|
||||
|
||||
D3 d3;
|
||||
d3.HEX = transform_program[i * 4 + 3];
|
||||
|
||||
if (d3.end)
|
||||
break;
|
||||
top = shader_window_height - (viewport_y + viewport_h) + 1;
|
||||
bottom = shader_window_height - viewport_y + 1;
|
||||
}
|
||||
|
||||
u32 shader_program = rsx::method_registers[NV4097_SET_SHADER_PROGRAM];
|
||||
f32 scale_x = 2.0f / (right - left);
|
||||
f32 scale_y = 2.0f / (top - bottom);
|
||||
f32 scale_z = 2.0f;
|
||||
|
||||
std::string fp_shader; ParamArray fp_parr; u32 fp_size;
|
||||
GLFragmentDecompilerThread decompile_fp(fp_shader, fp_parr,
|
||||
rsx::get_address(shader_program & ~0x3, (shader_program & 0x3) - 1), fp_size, rsx::method_registers[NV4097_SET_SHADER_CONTROL]);
|
||||
f32 offset_x = -(right + left) / (right - left);
|
||||
f32 offset_y = -(top + bottom) / (top - bottom);
|
||||
f32 offset_z = -1.0;
|
||||
|
||||
std::string vp_shader; ParamArray vp_parr;
|
||||
GLVertexDecompilerThread decompile_vp(vertex_program, vp_shader, vp_parr);
|
||||
decompile_fp.Task();
|
||||
decompile_vp.Task();
|
||||
if (shader_window_origin == rsx::window_origin::top)
|
||||
{
|
||||
scale_y = -scale_y;
|
||||
offset_y = -offset_y;
|
||||
}
|
||||
|
||||
LOG_NOTICE(RSX, "fp: %s", fp_shader.c_str());
|
||||
LOG_NOTICE(RSX, "vp: %s", vp_shader.c_str());
|
||||
rsx::fill_scale_offset_matrix(buffer->normalize_matrix, true, offset_x, offset_y, offset_z, scale_x, scale_y, scale_z);
|
||||
}
|
||||
|
||||
static bool first = true;
|
||||
gl::glsl::shader fp(gl::glsl::shader::type::fragment, fp_shader);
|
||||
gl::glsl::shader vp(gl::glsl::shader::type::vertex, vp_shader);
|
||||
bool GLGSRender::load_program()
|
||||
{
|
||||
rsx::program_info info = programs_cache.get(get_raw_program(), rsx::decompile_language::glsl);
|
||||
m_program = (gl::glsl::program*)info.program;
|
||||
m_program->use();
|
||||
|
||||
(m_program.recreate() += { fp.compile(), vp.compile() }).make();
|
||||
#endif
|
||||
u32 fragment_constants_sz = m_prog_buffer.get_fragment_constants_buffer_size(fragment_program);
|
||||
fragment_constants_sz = std::max(32U, fragment_constants_sz);
|
||||
u32 max_buffer_sz = 8192 + 512 + fragment_constants_sz;
|
||||
u32 fragment_constants_count = info.fragment_shader.decompiled->constants.size();
|
||||
u32 fragment_constants_size = fragment_constants_count * sizeof(rsx::fragment_program::ucode_instr);
|
||||
|
||||
u32 is_alpha_tested = !!(rsx::method_registers[NV4097_SET_ALPHA_TEST_ENABLE]);
|
||||
u8 alpha_ref_raw = (u8)(rsx::method_registers[NV4097_SET_ALPHA_REF] & 0xFF);
|
||||
float alpha_ref = alpha_ref_raw / 255.f;
|
||||
u32 max_buffer_sz =
|
||||
align(sizeof(glsl_matrix_buffer), m_uniform_buffer_offset_align) +
|
||||
align(sizeof(glsl_vertex_constants_buffer), m_uniform_buffer_offset_align) +
|
||||
align(fragment_constants_size, m_uniform_buffer_offset_align);
|
||||
|
||||
m_uniform_ring_buffer.reserve_and_map(max_buffer_sz);
|
||||
|
||||
u8 *buf;
|
||||
u32 scale_offset_offset;
|
||||
u32 vertex_constants_offset;
|
||||
u32 fragment_constants_offset;
|
||||
|
||||
m_uniform_ring_buffer->reserve_and_map(max_buffer_sz);
|
||||
auto mapping = m_uniform_ring_buffer->alloc_from_reserve(512);
|
||||
buf = static_cast<u8*>(mapping.first);
|
||||
scale_offset_offset = mapping.second;
|
||||
{
|
||||
auto mapping = m_uniform_ring_buffer.alloc_from_reserve(sizeof(glsl_matrix_buffer), m_uniform_buffer_offset_align);
|
||||
fill_matrix_buffer((glsl_matrix_buffer *)mapping.first);
|
||||
scale_offset_offset = mapping.second;
|
||||
}
|
||||
|
||||
fill_scale_offset_data(buf, false);
|
||||
memcpy(buf + 16 * sizeof(float), &rsx::method_registers[NV4097_SET_FOG_PARAMS], sizeof(float));
|
||||
memcpy(buf + 17 * sizeof(float), &rsx::method_registers[NV4097_SET_FOG_PARAMS + 1], sizeof(float));
|
||||
memcpy(buf + 18 * sizeof(float), &is_alpha_tested, sizeof(u32));
|
||||
memcpy(buf + 19 * sizeof(float), &alpha_ref, sizeof(float));
|
||||
{
|
||||
auto mapping = m_uniform_ring_buffer.alloc_from_reserve(sizeof(glsl_vertex_constants_buffer), m_uniform_buffer_offset_align);
|
||||
fill_vertex_program_constants_data(mapping.first);
|
||||
vertex_constants_offset = mapping.second;
|
||||
}
|
||||
|
||||
mapping = m_uniform_ring_buffer->alloc_from_reserve(512 * 16);
|
||||
buf = static_cast<u8*>(mapping.first);
|
||||
vertex_constants_offset = mapping.second;
|
||||
if (fragment_constants_size)
|
||||
{
|
||||
auto mapping = m_uniform_ring_buffer.alloc_from_reserve(fragment_constants_size, m_uniform_buffer_offset_align);
|
||||
fragment_constants_offset = mapping.second;
|
||||
|
||||
fill_vertex_program_constants_data(buf);
|
||||
u32 buffer_offset = 0;
|
||||
|
||||
mapping = m_uniform_ring_buffer->alloc_from_reserve(fragment_constants_sz);
|
||||
buf = static_cast<u8*>(mapping.first);
|
||||
fragment_constants_offset = mapping.second;
|
||||
static const __m128i mask = _mm_set_epi8(
|
||||
0xE, 0xF, 0xC, 0xD,
|
||||
0xA, 0xB, 0x8, 0x9,
|
||||
0x6, 0x7, 0x4, 0x5,
|
||||
0x2, 0x3, 0x0, 0x1);
|
||||
|
||||
m_prog_buffer.fill_fragment_constans_buffer({ reinterpret_cast<float*>(buf), gsl::narrow<int>(fragment_constants_sz) }, fragment_program);
|
||||
auto ucode = (const rsx::fragment_program::ucode_instr *)info.fragment_shader.decompiled->raw->ucode_ptr;
|
||||
|
||||
m_uniform_ring_buffer->unmap();
|
||||
for (const auto& constant : info.fragment_shader.decompiled->constants)
|
||||
{
|
||||
const void *data = ucode + u32(constant.id / sizeof(rsx::fragment_program::ucode_instr));
|
||||
const __m128i &vector = _mm_loadu_si128((const __m128i*)data);
|
||||
const __m128i &shuffled_vector = _mm_shuffle_epi8(vector, mask);
|
||||
_mm_stream_si128((__m128i*)((char*)mapping.first + buffer_offset), shuffled_vector);
|
||||
|
||||
glBindBufferRange(GL_UNIFORM_BUFFER, 0, m_uniform_ring_buffer->get_buffer().id(), scale_offset_offset, 512);
|
||||
glBindBufferRange(GL_UNIFORM_BUFFER, 1, m_uniform_ring_buffer->get_buffer().id(), vertex_constants_offset, 512 * 16);
|
||||
glBindBufferRange(GL_UNIFORM_BUFFER, 2, m_uniform_ring_buffer->get_buffer().id(), fragment_constants_offset, fragment_constants_sz);
|
||||
//float x = ((float*)((char*)mapping.first + buffer_offset))[0];
|
||||
//float y = ((float*)((char*)mapping.first + buffer_offset))[1];
|
||||
//float z = ((float*)((char*)mapping.first + buffer_offset))[2];
|
||||
//float w = ((float*)((char*)mapping.first + buffer_offset))[3];
|
||||
|
||||
//LOG_WARNING(RSX, "fc%u = {%g, %g, %g, %g}", constant.id, x, y, z, w);
|
||||
buffer_offset += 4 * sizeof(f32);
|
||||
}
|
||||
}
|
||||
|
||||
m_uniform_ring_buffer.unmap();
|
||||
|
||||
m_uniform_ring_buffer.bind_range(0, scale_offset_offset, sizeof(glsl_matrix_buffer));
|
||||
m_uniform_ring_buffer.bind_range(1, vertex_constants_offset, sizeof(glsl_vertex_constants_buffer));
|
||||
|
||||
if (fragment_constants_size)
|
||||
{
|
||||
m_uniform_ring_buffer.bind_range(2, fragment_constants_offset, fragment_constants_size);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -14,8 +14,6 @@
|
||||
class GLGSRender : public GSRender
|
||||
{
|
||||
private:
|
||||
GLFragmentProgram m_fragment_prog;
|
||||
GLVertexProgram m_vertex_prog;
|
||||
|
||||
rsx::gl::texture m_gl_textures[rsx::limits::textures_count];
|
||||
rsx::gl::texture m_gl_vertex_textures[rsx::limits::vertex_textures_count];
|
||||
@ -28,9 +26,9 @@ private:
|
||||
gl::gl_texture_cache m_gl_texture_cache;
|
||||
|
||||
gl::texture m_gl_attrib_buffers[rsx::limits::vertex_count];
|
||||
std::unique_ptr<gl::ring_buffer> m_attrib_ring_buffer;
|
||||
std::unique_ptr<gl::ring_buffer> m_uniform_ring_buffer;
|
||||
std::unique_ptr<gl::ring_buffer> m_index_ring_buffer;
|
||||
gl::ring_buffer m_attrib_ring_buffer;
|
||||
gl::ring_buffer m_uniform_ring_buffer;
|
||||
gl::ring_buffer m_index_ring_buffer;
|
||||
|
||||
u32 m_draw_calls = 0;
|
||||
u32 m_begin_time = 0;
|
||||
@ -38,12 +36,12 @@ private:
|
||||
u32 m_vertex_upload_time = 0;
|
||||
|
||||
GLint m_min_texbuffer_alignment = 256;
|
||||
GLint m_uniform_buffer_offset_align = 256;
|
||||
|
||||
public:
|
||||
gl::fbo draw_fbo;
|
||||
|
||||
private:
|
||||
GLProgramBuffer m_prog_buffer;
|
||||
|
||||
//buffer
|
||||
gl::fbo m_flip_fbo;
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
namespace gl
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
#if 1//def _DEBUG
|
||||
struct __glcheck_impl_t
|
||||
{
|
||||
const char* file;
|
||||
@ -47,7 +47,7 @@ namespace gl
|
||||
}
|
||||
}
|
||||
};
|
||||
#define __glcheck gl::__glcheck_impl_t{ __FILE__, __FUNCTION__, __LINE__ },
|
||||
#define __glcheck ::gl::__glcheck_impl_t{ __FILE__, __FUNCTION__, __LINE__ },
|
||||
#else
|
||||
#define __glcheck
|
||||
#endif
|
||||
@ -496,6 +496,11 @@ namespace gl
|
||||
glBindBuffer((GLenum)target_, m_id);
|
||||
}
|
||||
|
||||
void bind() const
|
||||
{
|
||||
bind(current_target());
|
||||
}
|
||||
|
||||
target current_target() const
|
||||
{
|
||||
return m_target;
|
||||
@ -580,12 +585,9 @@ namespace gl
|
||||
}
|
||||
};
|
||||
|
||||
class ring_buffer
|
||||
class ring_buffer : public buffer
|
||||
{
|
||||
buffer storage_buffer;
|
||||
buffer::target m_target;
|
||||
u32 m_data_loc = 0;
|
||||
u32 m_size;
|
||||
|
||||
u32 m_mapped_block_size = 0;
|
||||
u32 m_mapped_block_offset;
|
||||
@ -594,50 +596,39 @@ namespace gl
|
||||
void *m_mapped_base = nullptr;
|
||||
|
||||
public:
|
||||
ring_buffer(u32 initial_size, buffer::target target)
|
||||
std::pair<void*, u32> alloc_and_map(u32 alloc_size)
|
||||
{
|
||||
storage_buffer.create();
|
||||
storage_buffer.data(initial_size);
|
||||
m_size = initial_size;
|
||||
m_target = target;
|
||||
}
|
||||
alloc_size = align(alloc_size, 0x100);
|
||||
|
||||
void destroy()
|
||||
{
|
||||
storage_buffer.remove();
|
||||
}
|
||||
|
||||
std::pair<void*, u32> alloc_and_map(u32 size)
|
||||
{
|
||||
size = (size + 255) & ~255;
|
||||
|
||||
glBindBuffer((GLenum)m_target, storage_buffer.id());
|
||||
u32 limit = m_data_loc + size;
|
||||
if (limit > m_size)
|
||||
buffer::bind();
|
||||
u32 limit = m_data_loc + alloc_size;
|
||||
if (limit > buffer::size())
|
||||
{
|
||||
if (size > m_size)
|
||||
m_size = size;
|
||||
if (alloc_size > buffer::size())
|
||||
{
|
||||
buffer::data(alloc_size);
|
||||
}
|
||||
|
||||
storage_buffer.data(m_size, nullptr);
|
||||
m_data_loc = 0;
|
||||
}
|
||||
|
||||
void *ptr = glMapBufferRange((GLenum)m_target, m_data_loc, size, GL_MAP_WRITE_BIT|GL_MAP_INVALIDATE_RANGE_BIT|GL_MAP_UNSYNCHRONIZED_BIT);
|
||||
void *ptr = glMapBufferRange((GLenum)buffer::current_target(), m_data_loc, alloc_size,
|
||||
GL_MAP_WRITE_BIT|GL_MAP_INVALIDATE_RANGE_BIT|GL_MAP_UNSYNCHRONIZED_BIT);
|
||||
u32 offset = m_data_loc;
|
||||
m_data_loc += size;
|
||||
m_data_loc += alloc_size;
|
||||
return std::make_pair(ptr, offset);
|
||||
}
|
||||
|
||||
void unmap()
|
||||
{
|
||||
glUnmapBuffer((GLenum)m_target);
|
||||
buffer::unmap();
|
||||
m_mapped_block_size = 0;
|
||||
m_mapped_base = 0;
|
||||
}
|
||||
|
||||
void reserve_and_map(u32 max_size)
|
||||
{
|
||||
max_size = (max_size + 4095) & ~4095;
|
||||
max_size = align(max_size, 0x1000);
|
||||
auto mapping = alloc_and_map(max_size);
|
||||
m_mapped_base = mapping.first;
|
||||
m_mapped_block_offset = mapping.second;
|
||||
@ -647,8 +638,7 @@ namespace gl
|
||||
|
||||
std::pair<void*, u32> alloc_from_reserve(u32 size, u32 alignment = 16)
|
||||
{
|
||||
alignment -= 1;
|
||||
size = (size + alignment) & ~alignment;
|
||||
size = align(size, alignment);
|
||||
|
||||
if (m_mapped_bytes_available < size || !m_mapped_base)
|
||||
{
|
||||
@ -670,13 +660,13 @@ namespace gl
|
||||
m_mapped_reserve_offset += size;
|
||||
m_mapped_bytes_available -= size;
|
||||
|
||||
EXPECTS((offset & alignment) == 0);
|
||||
EXPECTS((offset & (alignment - 1)) == 0);
|
||||
return std::make_pair(ptr, offset);
|
||||
}
|
||||
|
||||
buffer& get_buffer()
|
||||
void bind_range(u32 index, u32 offset, u32 size) const
|
||||
{
|
||||
return storage_buffer;
|
||||
glBindBufferRange((GLenum)current_target(), index, id(), offset, size);
|
||||
}
|
||||
};
|
||||
|
||||
|
424
rpcs3/Emu/RSX/GL/rsx_gl_cache.cpp
Normal file
424
rpcs3/Emu/RSX/GL/rsx_gl_cache.cpp
Normal file
@ -0,0 +1,424 @@
|
||||
#include "stdafx.h"
|
||||
#include "rsx_gl_cache.h"
|
||||
#include "gl_helpers.h"
|
||||
#include "../GCM.h"
|
||||
|
||||
rsx::complete_shader glsl_complete_shader(const rsx::decompiled_shader &shader, rsx::program_state state)
|
||||
{
|
||||
rsx::complete_shader result;
|
||||
result.decompiled = &shader;
|
||||
result.code = "#version 430\n\n";
|
||||
|
||||
if (shader.raw->type == rsx::program_type::vertex)
|
||||
{
|
||||
result.code += "layout(std140, binding = 0) uniform MatrixBuffer\n{\n"
|
||||
"\tmat4 viewport_matrix;\n"
|
||||
"\tmat4 window_matrix;\n"
|
||||
"\tmat4 normalize_matrix;\n"
|
||||
"};\n";
|
||||
}
|
||||
|
||||
if (!shader.constants.empty())
|
||||
{
|
||||
if (shader.raw->type == rsx::program_type::vertex)
|
||||
{
|
||||
result.code += "layout(std140, binding = 1) uniform VertexConstantsBuffer\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
result.code += "layout(std140, binding = 2) uniform FragmentConstantsBuffer\n";
|
||||
}
|
||||
|
||||
result.code += "{\n";
|
||||
|
||||
for (const rsx::constant_info& constant : shader.constants)
|
||||
{
|
||||
result.code += "\tvec4 " + constant.name + ";\n";
|
||||
}
|
||||
|
||||
result.code += "};\n\n";
|
||||
}
|
||||
|
||||
for (const rsx::register_info& temporary : shader.temporary_registers)
|
||||
{
|
||||
std::string value;
|
||||
std::string type;
|
||||
switch (temporary.type)
|
||||
{
|
||||
case rsx::register_type::half_float_point:
|
||||
case rsx::register_type::single_float_point:
|
||||
type = "vec4";
|
||||
if (temporary.name == "o0")
|
||||
{
|
||||
value = "vec4(vec3(0.0), 1.0)";
|
||||
}
|
||||
else
|
||||
{
|
||||
value = "vec4(0.0)";
|
||||
}
|
||||
break;
|
||||
|
||||
case rsx::register_type::integer:
|
||||
type = "ivec4";
|
||||
value = "ivec4(0)";
|
||||
break;
|
||||
|
||||
default:
|
||||
throw;
|
||||
}
|
||||
|
||||
result.code += type + " " + temporary.name + " = " + value + ";\n";
|
||||
}
|
||||
|
||||
result.code += "\n";
|
||||
|
||||
for (const rsx::texture_info& texture : shader.textures)
|
||||
{
|
||||
result.code += "uniform vec4 " + texture.name + "_cm = vec4(1.0);\n";
|
||||
result.code += "uniform sampler2D " + texture.name + ";\n";
|
||||
}
|
||||
|
||||
std::string prepare;
|
||||
std::string finalize;
|
||||
int location = 1;
|
||||
|
||||
switch (shader.raw->type)
|
||||
{
|
||||
case rsx::program_type::fragment:
|
||||
result.code += "layout(location = 0) out vec4 ocol;\n";
|
||||
|
||||
if (state.ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS)
|
||||
{
|
||||
if (0)
|
||||
{
|
||||
finalize += "\tocol = vec4(1.0, 0.0, 1.0, 1.0);\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
finalize += "\tocol = r0;\n";
|
||||
}
|
||||
|
||||
if (shader.temporary_registers.find({ "r2" }) != shader.temporary_registers.end())
|
||||
{
|
||||
result.code += "layout(location = 1) out vec4 ocol1;\n";
|
||||
finalize += "\tocol1 = r2;\n";
|
||||
}
|
||||
if (shader.temporary_registers.find({ "r3" }) != shader.temporary_registers.end())
|
||||
{
|
||||
result.code += "layout(location = 2) out vec4 ocol2;\n";
|
||||
finalize += "\tocol2 = r3;\n";
|
||||
}
|
||||
if (shader.temporary_registers.find({ "r4" }) != shader.temporary_registers.end())
|
||||
{
|
||||
result.code += "layout(location = 3) out vec4 ocol3;\n";
|
||||
finalize += "\tocol3 = r4;\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
finalize += "\tocol = h0;\n";
|
||||
|
||||
if (shader.temporary_registers.find({ "h4" }) != shader.temporary_registers.end())
|
||||
{
|
||||
result.code += "layout(location = 1) out vec4 ocol1;\n";
|
||||
finalize += "\tocol1 = h4;\n";
|
||||
}
|
||||
if (shader.temporary_registers.find({ "h6" }) != shader.temporary_registers.end())
|
||||
{
|
||||
result.code += "layout(location = 2) out vec4 ocol2;\n";
|
||||
finalize += "\tocol2 = h6;\n";
|
||||
}
|
||||
if (shader.temporary_registers.find({ "h8" }) != shader.temporary_registers.end())
|
||||
{
|
||||
result.code += "layout(location = 3) out vec4 ocol3;\n";
|
||||
finalize += "\tocol3 = h8;\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (state.ctrl & CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT)
|
||||
{
|
||||
if (state.ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS)
|
||||
{
|
||||
if (shader.temporary_registers.find({ "r1" }) != shader.temporary_registers.end())
|
||||
{
|
||||
finalize += "\tgl_FragDepth = r1.z;\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (shader.temporary_registers.find({ "h2" }) != shader.temporary_registers.end())
|
||||
{
|
||||
finalize += "\tgl_FragDepth = h2.z;\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
u32 diffuse_color = state.output_attributes & (CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTDIFFUSE | CELL_GCM_ATTRIB_OUTPUT_MASK_BACKDIFFUSE);
|
||||
u32 specular_color = state.output_attributes & (CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTSPECULAR | CELL_GCM_ATTRIB_OUTPUT_MASK_BACKSPECULAR);
|
||||
|
||||
if (diffuse_color)
|
||||
{
|
||||
result.code += "vec4 col0;\n";
|
||||
}
|
||||
|
||||
if (specular_color)
|
||||
{
|
||||
result.code += "vec4 col1;\n";
|
||||
}
|
||||
|
||||
if (diffuse_color == (CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTDIFFUSE | CELL_GCM_ATTRIB_OUTPUT_MASK_BACKDIFFUSE) &&
|
||||
specular_color == (CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTSPECULAR | CELL_GCM_ATTRIB_OUTPUT_MASK_BACKSPECULAR))
|
||||
{
|
||||
prepare += "\tif (gl_FrontFacing)\n\t{";
|
||||
prepare += "\t\tcol0 = front_diffuse_color;\n";
|
||||
prepare += "\t\tcol1 = front_specular_color;\n";
|
||||
prepare += "\t}\nelse\n\t{\n";
|
||||
prepare += "\t\tcol0 = back_diffuse_color;\n";
|
||||
prepare += "\t\tcol1 = back_specular_color;\n";
|
||||
prepare += "\t}";
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (diffuse_color)
|
||||
{
|
||||
case CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTDIFFUSE | CELL_GCM_ATTRIB_OUTPUT_MASK_BACKDIFFUSE:
|
||||
prepare += "\tcol0 = gl_FrontFacing ? front_diffuse_color : back_diffuse_color;\n";
|
||||
break;
|
||||
|
||||
case CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTDIFFUSE:
|
||||
prepare += "\tcol0 = front_diffuse_color;\n";
|
||||
break;
|
||||
|
||||
case CELL_GCM_ATTRIB_OUTPUT_MASK_BACKDIFFUSE:
|
||||
prepare += "\tcol0 = back_diffuse_color;\n";
|
||||
break;
|
||||
|
||||
default:
|
||||
if (shader.input_attributes & (1 << 1))
|
||||
{
|
||||
result.code += "vec4 col0 = vec4(0.0);\n";
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
switch (specular_color)
|
||||
{
|
||||
case CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTSPECULAR | CELL_GCM_ATTRIB_OUTPUT_MASK_BACKSPECULAR:
|
||||
prepare += "\tcol1 = gl_FrontFacing ? front_specular_color : back_specular_color;\n";
|
||||
break;
|
||||
|
||||
case CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTSPECULAR:
|
||||
prepare += "\tcol1 = front_specular_color;\n";
|
||||
break;
|
||||
|
||||
case CELL_GCM_ATTRIB_OUTPUT_MASK_BACKSPECULAR:
|
||||
prepare += "\tcol1 = back_specular_color;\n";
|
||||
break;
|
||||
|
||||
default:
|
||||
if (shader.input_attributes & (1 << 2))
|
||||
{
|
||||
result.code += "vec4 col1 = vec4(0.0);\n";
|
||||
|
||||
if (diffuse_color)
|
||||
{
|
||||
prepare += "\tcol1 = col0;\n";
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.code += "in vec4 " + rsx::fragment_program::input_attrib_names[0] + ";\n";
|
||||
|
||||
for (std::size_t index = 0; index < 22; ++index)
|
||||
{
|
||||
if (state.output_attributes & (1 << index))
|
||||
{
|
||||
result.code += "in vec4 " + rsx::vertex_program::output_attrib_names[index] + ";\n";
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case rsx::program_type::vertex:
|
||||
|
||||
result.code += "out vec4 wpos;\n";
|
||||
|
||||
// TODO
|
||||
if (0)
|
||||
{
|
||||
finalize += "\tgl_Position = o0;\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
finalize +=
|
||||
" wpos = window_matrix * viewport_matrix * vec4(o0.xyz, 1.0);\n"
|
||||
" gl_Position = normalize_matrix * vec4(wpos.xyz, 1.0);\n"
|
||||
" gl_Position.w = o0.w;\n";
|
||||
}
|
||||
|
||||
for (std::size_t index = 0; index < 16; ++index)
|
||||
{
|
||||
if (shader.input_attributes & (1 << index))
|
||||
{
|
||||
// result.code += "in vec4 " + rsx::vertex_program::input_attrib_names[index] + ";\n";
|
||||
|
||||
// TODO: use actual information about vertex inputs
|
||||
result.code += "layout(location=" + std::to_string(location++) + ") uniform samplerBuffer " + rsx::vertex_program::input_attrib_names[index] + "_buffer" + ";\n";
|
||||
result.code += "vec4 " + rsx::vertex_program::input_attrib_names[index]
|
||||
+ " = texelFetch(" + rsx::vertex_program::input_attrib_names[index] + "_buffer, gl_VertexID).rgba;\n";
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto map_register = [&](int to, int from)
|
||||
{
|
||||
if (shader.output_attributes & (1 << from))
|
||||
{
|
||||
result.code += "out vec4 " + rsx::vertex_program::output_attrib_names[to] + ";\n";
|
||||
finalize += "\t" + rsx::vertex_program::output_attrib_names[to] + " = o" + std::to_string(from) + ";\n";
|
||||
}
|
||||
else if (state.output_attributes & (1 << to))
|
||||
{
|
||||
result.code += "out vec4 " + rsx::vertex_program::output_attrib_names[to] + ";\n";
|
||||
|
||||
if ((1 << to) == CELL_GCM_ATTRIB_OUTPUT_MASK_BACKDIFFUSE && shader.output_attributes & (1 << 1))
|
||||
{
|
||||
finalize += "\t" + rsx::vertex_program::output_attrib_names[to] + " = o1;\n";
|
||||
}
|
||||
else if ((1 << to) == CELL_GCM_ATTRIB_OUTPUT_MASK_BACKSPECULAR && shader.output_attributes & (1 << 2))
|
||||
{
|
||||
finalize += "\t" + rsx::vertex_program::output_attrib_names[to] + " = o2;\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
finalize += "\t" + rsx::vertex_program::output_attrib_names[to] + " = vec4(0.0);\n";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
map_register(0, 1);
|
||||
map_register(1, 2);
|
||||
map_register(2, 3);
|
||||
map_register(3, 4);
|
||||
map_register(14, 7);
|
||||
map_register(15, 8);
|
||||
map_register(16, 9);
|
||||
map_register(17, 10);
|
||||
map_register(18, 11);
|
||||
map_register(19, 12);
|
||||
map_register(20, 13);
|
||||
map_register(21, 14);
|
||||
map_register(12, 15);
|
||||
|
||||
if (shader.output_attributes & (1 << 5))
|
||||
{
|
||||
if (state.output_attributes & CELL_GCM_ATTRIB_OUTPUT_MASK_UC0)
|
||||
{
|
||||
result.code += "uniform int uc_m0 = 0;\n";
|
||||
finalize += "\tgl_ClipDistance[0] = uc_m0 * o5.y;\n";
|
||||
}
|
||||
|
||||
if (state.output_attributes & CELL_GCM_ATTRIB_OUTPUT_MASK_UC1)
|
||||
{
|
||||
result.code += "uniform int uc_m1 = 0;\n";
|
||||
finalize += "\tgl_ClipDistance[1] = uc_m1 * o5.z;\n";
|
||||
}
|
||||
|
||||
if (state.output_attributes & CELL_GCM_ATTRIB_OUTPUT_MASK_UC2)
|
||||
{
|
||||
result.code += "uniform int uc_m2 = 0;\n";
|
||||
finalize += "\tgl_ClipDistance[2] = uc_m2 * o5.w;\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (shader.output_attributes & (1 << 6))
|
||||
{
|
||||
if (state.output_attributes & CELL_GCM_ATTRIB_OUTPUT_MASK_POINTSIZE)
|
||||
{
|
||||
finalize += "\tgl_PointSize = o6.x;\n";
|
||||
}
|
||||
|
||||
if (state.output_attributes & CELL_GCM_ATTRIB_OUTPUT_MASK_UC3)
|
||||
{
|
||||
result.code += "uniform int uc_m3 = 0;\n";
|
||||
finalize += "\tgl_ClipDistance[3] = uc_m3 * o6.y;\n";
|
||||
}
|
||||
|
||||
if (state.output_attributes & CELL_GCM_ATTRIB_OUTPUT_MASK_UC4)
|
||||
{
|
||||
result.code += "uniform int uc_m4 = 0;\n";
|
||||
finalize += "\tgl_ClipDistance[4] = uc_m4 * o6.z;\n";
|
||||
}
|
||||
|
||||
if (state.output_attributes & CELL_GCM_ATTRIB_OUTPUT_MASK_UC4)
|
||||
{
|
||||
result.code += "uniform int uc_m5 = 0;\n";
|
||||
finalize += "\tgl_ClipDistance[5] = uc_m5 * o6.w;\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (state.output_attributes & CELL_GCM_ATTRIB_OUTPUT_MASK_FOG)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw;
|
||||
}
|
||||
|
||||
result.code += "\n";
|
||||
result.code += shader.code;
|
||||
|
||||
result.code += "void main()\n{\n" + prepare + "\t" + shader.entry_function + "();\n" + finalize + "}";
|
||||
return result;
|
||||
}
|
||||
|
||||
void* glsl_compile_shader(rsx::program_type type, const std::string &code)
|
||||
{
|
||||
gl::glsl::shader *result = new gl::glsl::shader();
|
||||
|
||||
result->create(type == rsx::program_type::vertex ? ::gl::glsl::shader::type::vertex : ::gl::glsl::shader::type::fragment);
|
||||
result->source(code);
|
||||
result->compile();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void* glsl_make_program(const void *vertex_shader, const void *fragment_shader)
|
||||
{
|
||||
gl::glsl::program *result = new gl::glsl::program();
|
||||
|
||||
result->create();
|
||||
result->attach(*(gl::glsl::shader*)vertex_shader);
|
||||
result->attach(*(gl::glsl::shader*)fragment_shader);
|
||||
|
||||
result->link();
|
||||
result->validate();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void glsl_remove_program(void *buf)
|
||||
{
|
||||
delete (gl::glsl::program*)buf;
|
||||
}
|
||||
|
||||
void glsl_remove_shader(void *buf)
|
||||
{
|
||||
delete (gl::glsl::shader*)buf;
|
||||
}
|
||||
|
||||
void init_glsl_cache_program_context(rsx::program_cache_context &ctxt)
|
||||
{
|
||||
ctxt.compile_shader = glsl_compile_shader;
|
||||
ctxt.complete_shader = glsl_complete_shader;
|
||||
ctxt.make_program = glsl_make_program;
|
||||
ctxt.remove_program = glsl_remove_program;
|
||||
ctxt.remove_shader = glsl_remove_shader;
|
||||
ctxt.lang = rsx::decompile_language::glsl;
|
||||
}
|
11
rpcs3/Emu/RSX/GL/rsx_gl_cache.h
Normal file
11
rpcs3/Emu/RSX/GL/rsx_gl_cache.h
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
#include "../rsx_cache.h"
|
||||
|
||||
struct alignas(4) glsl_shader_matrix_buffer
|
||||
{
|
||||
float viewport_matrix[4 * 4];
|
||||
float window_matrix[4 * 4];
|
||||
float normalize_matrix[4 * 4];
|
||||
};
|
||||
|
||||
void init_glsl_cache_program_context(rsx::program_cache_context &ctxt);
|
@ -296,14 +296,14 @@ namespace rsx
|
||||
int mip_level = 0;
|
||||
if (dim == rsx::texture_dimension_extended::texture_dimension_1d)
|
||||
{
|
||||
glTexStorage1D(GL_TEXTURE_1D, mipmap_count, get_sized_internal_format(format), width);
|
||||
__glcheck glTexStorage1D(GL_TEXTURE_1D, mipmap_count, get_sized_internal_format(format), width);
|
||||
if (!is_compressed_format(format))
|
||||
{
|
||||
const auto &format_type = get_format_type(format);
|
||||
for (const rsx_subresource_layout &layout : input_layouts)
|
||||
{
|
||||
upload_texture_subresource(staging_buffer, layout, format, is_swizzled, 4);
|
||||
glTexSubImage1D(GL_TEXTURE_1D, mip_level++, 0, layout.width_in_block, std::get<0>(format_type), std::get<1>(format_type), staging_buffer.data());
|
||||
__glcheck upload_texture_subresource(staging_buffer, layout, format, is_swizzled, 4);
|
||||
__glcheck glTexSubImage1D(GL_TEXTURE_1D, mip_level++, 0, layout.width_in_block, std::get<0>(format_type), std::get<1>(format_type), staging_buffer.data());
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -311,7 +311,7 @@ namespace rsx
|
||||
for (const rsx_subresource_layout &layout : input_layouts)
|
||||
{
|
||||
u32 size = layout.width_in_block * ((format == CELL_GCM_TEXTURE_COMPRESSED_DXT1) ? 8 : 16);
|
||||
glCompressedTexSubImage1D(GL_TEXTURE_1D, mip_level++, 0, layout.width_in_block * 4, get_sized_internal_format(format), size, layout.data.data());
|
||||
__glcheck glCompressedTexSubImage1D(GL_TEXTURE_1D, mip_level++, 0, layout.width_in_block * 4, get_sized_internal_format(format), size, layout.data.data());
|
||||
}
|
||||
}
|
||||
return;
|
||||
@ -319,14 +319,14 @@ namespace rsx
|
||||
|
||||
if (dim == rsx::texture_dimension_extended::texture_dimension_2d)
|
||||
{
|
||||
glTexStorage2D(GL_TEXTURE_2D, mipmap_count, get_sized_internal_format(format), width, height);
|
||||
__glcheck glTexStorage2D(GL_TEXTURE_2D, mipmap_count, get_sized_internal_format(format), width, height);
|
||||
if (!is_compressed_format(format))
|
||||
{
|
||||
const auto &format_type = get_format_type(format);
|
||||
for (const rsx_subresource_layout &layout : input_layouts)
|
||||
{
|
||||
upload_texture_subresource(staging_buffer, layout, format, is_swizzled, 4);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, mip_level++, 0, 0, layout.width_in_block, layout.height_in_block, std::get<0>(format_type), std::get<1>(format_type), staging_buffer.data());
|
||||
__glcheck upload_texture_subresource(staging_buffer, layout, format, is_swizzled, 4);
|
||||
__glcheck glTexSubImage2D(GL_TEXTURE_2D, mip_level++, 0, 0, layout.width_in_block, layout.height_in_block, std::get<0>(format_type), std::get<1>(format_type), staging_buffer.data());
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -334,7 +334,7 @@ namespace rsx
|
||||
for (const rsx_subresource_layout &layout : input_layouts)
|
||||
{
|
||||
u32 size = layout.width_in_block * layout.height_in_block * ((format == CELL_GCM_TEXTURE_COMPRESSED_DXT1) ? 8 : 16);
|
||||
glCompressedTexSubImage2D(GL_TEXTURE_2D, mip_level++, 0, 0, layout.width_in_block * 4, layout.height_in_block * 4, get_sized_internal_format(format), size, layout.data.data());
|
||||
__glcheck glCompressedTexSubImage2D(GL_TEXTURE_2D, mip_level++, 0, 0, layout.width_in_block * 4, layout.height_in_block * 4, get_sized_internal_format(format), size, layout.data.data());
|
||||
}
|
||||
}
|
||||
return;
|
||||
@ -342,7 +342,7 @@ namespace rsx
|
||||
|
||||
if (dim == rsx::texture_dimension_extended::texture_dimension_cubemap)
|
||||
{
|
||||
glTexStorage2D(GL_TEXTURE_CUBE_MAP, mipmap_count, get_sized_internal_format(format), width, height);
|
||||
__glcheck glTexStorage2D(GL_TEXTURE_CUBE_MAP, mipmap_count, get_sized_internal_format(format), width, height);
|
||||
// Note : input_layouts size is get_exact_mipmap_count() for non cubemap texture, and 6 * get_exact_mipmap_count() for cubemap
|
||||
// Thus for non cubemap texture, mip_level / mipmap_per_layer will always be rounded to 0.
|
||||
// mip_level % mipmap_per_layer will always be equal to mip_level
|
||||
@ -352,7 +352,7 @@ namespace rsx
|
||||
for (const rsx_subresource_layout &layout : input_layouts)
|
||||
{
|
||||
upload_texture_subresource(staging_buffer, layout, format, is_swizzled, 4);
|
||||
glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + mip_level / mipmap_count, mip_level % mipmap_count, 0, 0, layout.width_in_block, layout.height_in_block, std::get<0>(format_type), std::get<1>(format_type), staging_buffer.data());
|
||||
__glcheck glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + mip_level / mipmap_count, mip_level % mipmap_count, 0, 0, layout.width_in_block, layout.height_in_block, std::get<0>(format_type), std::get<1>(format_type), staging_buffer.data());
|
||||
mip_level++;
|
||||
}
|
||||
}
|
||||
@ -361,7 +361,7 @@ namespace rsx
|
||||
for (const rsx_subresource_layout &layout : input_layouts)
|
||||
{
|
||||
u32 size = layout.width_in_block * layout.height_in_block * ((format == CELL_GCM_TEXTURE_COMPRESSED_DXT1) ? 8 : 16);
|
||||
glCompressedTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + mip_level / mipmap_count, mip_level % mipmap_count, 0, 0, layout.width_in_block * 4, layout.height_in_block * 4, get_sized_internal_format(format), size, layout.data.data());
|
||||
__glcheck glCompressedTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + mip_level / mipmap_count, mip_level % mipmap_count, 0, 0, layout.width_in_block * 4, layout.height_in_block * 4, get_sized_internal_format(format), size, layout.data.data());
|
||||
mip_level++;
|
||||
}
|
||||
}
|
||||
@ -370,14 +370,14 @@ namespace rsx
|
||||
|
||||
if (dim == rsx::texture_dimension_extended::texture_dimension_3d)
|
||||
{
|
||||
glTexStorage3D(GL_TEXTURE_3D, mipmap_count, get_sized_internal_format(format), width, height, depth);
|
||||
__glcheck glTexStorage3D(GL_TEXTURE_3D, mipmap_count, get_sized_internal_format(format), width, height, depth);
|
||||
if (!is_compressed_format(format))
|
||||
{
|
||||
const auto &format_type = get_format_type(format);
|
||||
for (const rsx_subresource_layout &layout : input_layouts)
|
||||
{
|
||||
upload_texture_subresource(staging_buffer, layout, format, is_swizzled, 4);
|
||||
glTexSubImage3D(GL_TEXTURE_3D, mip_level++, 0, 0, 0, layout.width_in_block, layout.height_in_block, depth, std::get<0>(format_type), std::get<1>(format_type), staging_buffer.data());
|
||||
__glcheck upload_texture_subresource(staging_buffer, layout, format, is_swizzled, 4);
|
||||
__glcheck glTexSubImage3D(GL_TEXTURE_3D, mip_level++, 0, 0, 0, layout.width_in_block, layout.height_in_block, depth, std::get<0>(format_type), std::get<1>(format_type), staging_buffer.data());
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -385,7 +385,7 @@ namespace rsx
|
||||
for (const rsx_subresource_layout &layout : input_layouts)
|
||||
{
|
||||
u32 size = layout.width_in_block * layout.height_in_block * layout.depth * ((format == CELL_GCM_TEXTURE_COMPRESSED_DXT1) ? 8 : 16);
|
||||
glCompressedTexSubImage3D(GL_TEXTURE_3D, mip_level++, 0, 0, 0, layout.width_in_block * 4, layout.height_in_block * 4, layout.depth, get_sized_internal_format(format), size, layout.data.data());
|
||||
__glcheck glCompressedTexSubImage3D(GL_TEXTURE_3D, mip_level++, 0, 0, 0, layout.width_in_block * 4, layout.height_in_block * 4, layout.depth, get_sized_internal_format(format), size, layout.data.data());
|
||||
}
|
||||
}
|
||||
return;
|
||||
@ -406,13 +406,39 @@ namespace rsx
|
||||
|
||||
void texture::init(int index, rsx::texture& tex)
|
||||
{
|
||||
switch (tex.dimension())
|
||||
{
|
||||
case rsx::texture_dimension::dimension3d:
|
||||
if (!tex.depth())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
case rsx::texture_dimension::dimension2d:
|
||||
if (!tex.height())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
case rsx::texture_dimension::dimension1d:
|
||||
if (!tex.width())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
const u32 texaddr = rsx::get_address(tex.offset(), tex.location());
|
||||
|
||||
//We can't re-use texture handles if using immutable storage
|
||||
if (m_id) remove();
|
||||
create();
|
||||
if (m_id)
|
||||
{
|
||||
__glcheck remove();
|
||||
}
|
||||
__glcheck create();
|
||||
|
||||
glActiveTexture(GL_TEXTURE0 + index);
|
||||
__glcheck glActiveTexture(GL_TEXTURE0 + index);
|
||||
bind();
|
||||
|
||||
u32 full_format = tex.format();
|
||||
@ -420,8 +446,8 @@ namespace rsx
|
||||
u32 format = full_format & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
|
||||
bool is_swizzled = !!(~full_format & CELL_GCM_TEXTURE_LN);
|
||||
|
||||
::gl::pixel_pack_settings().apply();
|
||||
::gl::pixel_unpack_settings().apply();
|
||||
__glcheck ::gl::pixel_pack_settings().apply();
|
||||
__glcheck ::gl::pixel_unpack_settings().apply();
|
||||
|
||||
u32 aligned_pitch = tex.pitch();
|
||||
|
||||
@ -429,8 +455,9 @@ namespace rsx
|
||||
std::vector<gsl::byte> data_upload_buf(texture_data_sz);
|
||||
u32 block_sz = get_pitch_modifier(format);
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
||||
create_and_fill_texture(tex.get_extended_texture_dimension(), tex.get_exact_mipmap_count(), format, tex.width(), tex.height(), tex.depth(), get_subresources_layout(tex), is_swizzled, data_upload_buf);
|
||||
__glcheck glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
||||
|
||||
__glcheck create_and_fill_texture(tex.get_extended_texture_dimension(), tex.get_exact_mipmap_count(), format, tex.width(), tex.height(), tex.depth(), get_subresources_layout(tex), is_swizzled, data_upload_buf);
|
||||
|
||||
const std::array<GLenum, 4>& glRemap = get_swizzle_remap(format);
|
||||
|
||||
@ -443,29 +470,28 @@ namespace rsx
|
||||
u8 remap_g = (tex.remap() >> 4) & 0x3;
|
||||
u8 remap_b = (tex.remap() >> 6) & 0x3;
|
||||
|
||||
glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_A, glRemap[remap_a]);
|
||||
glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_R, glRemap[remap_r]);
|
||||
glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_G, glRemap[remap_g]);
|
||||
glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_B, glRemap[remap_b]);
|
||||
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_A, glRemap[remap_a]);
|
||||
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_R, glRemap[remap_r]);
|
||||
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_G, glRemap[remap_g]);
|
||||
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_B, glRemap[remap_b]);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_A, glRemap[0]);
|
||||
glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_R, glRemap[1]);
|
||||
glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_G, glRemap[2]);
|
||||
glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_B, glRemap[3]);
|
||||
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_A, glRemap[0]);
|
||||
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_R, glRemap[1]);
|
||||
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_G, glRemap[2]);
|
||||
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_B, glRemap[3]);
|
||||
}
|
||||
|
||||
glTexParameteri(m_target, GL_TEXTURE_WRAP_S, gl_wrap(tex.wrap_s()));
|
||||
glTexParameteri(m_target, GL_TEXTURE_WRAP_T, gl_wrap(tex.wrap_t()));
|
||||
glTexParameteri(m_target, GL_TEXTURE_WRAP_R, gl_wrap(tex.wrap_r()));
|
||||
__glcheck glTexParameteri(m_target, GL_TEXTURE_WRAP_S, gl_wrap(tex.wrap_s()));
|
||||
__glcheck glTexParameteri(m_target, GL_TEXTURE_WRAP_T, gl_wrap(tex.wrap_t()));
|
||||
__glcheck glTexParameteri(m_target, GL_TEXTURE_WRAP_R, gl_wrap(tex.wrap_r()));
|
||||
|
||||
glTexParameteri(m_target, GL_TEXTURE_COMPARE_FUNC, gl_tex_zfunc[tex.zfunc()]);
|
||||
__glcheck glTexParameteri(m_target, GL_TEXTURE_COMPARE_FUNC, gl_tex_zfunc[tex.zfunc()]);
|
||||
|
||||
glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, tex.bias());
|
||||
glTexParameteri(m_target, GL_TEXTURE_MIN_LOD, (tex.min_lod() >> 8));
|
||||
glTexParameteri(m_target, GL_TEXTURE_MAX_LOD, (tex.max_lod() >> 8));
|
||||
__glcheck glTexParameterf(m_target, GL_TEXTURE_LOD_BIAS, tex.bias());
|
||||
__glcheck glTexParameteri(m_target, GL_TEXTURE_MIN_LOD, (tex.min_lod() >> 8));
|
||||
__glcheck glTexParameteri(m_target, GL_TEXTURE_MAX_LOD, (tex.max_lod() >> 8));
|
||||
|
||||
int min_filter = gl_tex_min_filter(tex.min_filter());
|
||||
|
||||
@ -478,9 +504,9 @@ namespace rsx
|
||||
}
|
||||
}
|
||||
|
||||
glTexParameteri(m_target, GL_TEXTURE_MIN_FILTER, min_filter);
|
||||
glTexParameteri(m_target, GL_TEXTURE_MAG_FILTER, gl_tex_mag_filter(tex.mag_filter()));
|
||||
glTexParameterf(m_target, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_aniso(tex.max_aniso()));
|
||||
__glcheck glTexParameteri(m_target, GL_TEXTURE_MIN_FILTER, min_filter);
|
||||
__glcheck glTexParameteri(m_target, GL_TEXTURE_MAG_FILTER, gl_tex_mag_filter(tex.mag_filter()));
|
||||
__glcheck glTexParameterf(m_target, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_aniso(tex.max_aniso()));
|
||||
}
|
||||
|
||||
void texture::bind()
|
||||
|
@ -203,14 +203,14 @@ u32 GLGSRender::set_vertex_buffer()
|
||||
vertex_draw_count = (u32)get_index_count(draw_mode, gsl::narrow<int>(vertex_draw_count));
|
||||
u32 block_sz = vertex_draw_count * type_size;
|
||||
|
||||
auto mapping = m_index_ring_buffer->alloc_and_map(block_sz);
|
||||
auto mapping = m_index_ring_buffer.alloc_and_map(block_sz);
|
||||
void *ptr = mapping.first;
|
||||
offset_in_index_buffer = mapping.second;
|
||||
|
||||
gsl::span<gsl::byte> dst{ reinterpret_cast<gsl::byte*>(ptr), gsl::narrow<u32>(block_sz) };
|
||||
std::tie(min_index, max_index) = write_index_array_data_to_buffer(dst, type, draw_mode, first_count_commands);
|
||||
|
||||
m_index_ring_buffer->unmap();
|
||||
m_index_ring_buffer.unmap();
|
||||
}
|
||||
|
||||
if (draw_command == rsx::draw_command::inlined_array)
|
||||
@ -228,14 +228,14 @@ u32 GLGSRender::set_vertex_buffer()
|
||||
}
|
||||
|
||||
vertex_draw_count = (u32)(inline_vertex_array.size() * sizeof(u32)) / stride;
|
||||
m_attrib_ring_buffer->reserve_and_map(vertex_draw_count * max_vertex_attrib_size);
|
||||
m_attrib_ring_buffer.reserve_and_map(vertex_draw_count * max_vertex_attrib_size);
|
||||
|
||||
for (int index = 0; index < rsx::limits::vertex_count; ++index)
|
||||
{
|
||||
auto &vertex_info = vertex_arrays_info[index];
|
||||
|
||||
int location;
|
||||
if (!m_program->uniforms.has_location(reg_table[index] + "_buffer", &location))
|
||||
if (!m_program->uniforms.has_location(rsx::vertex_program::input_attrib_names[index] + "_buffer", &location))
|
||||
continue;
|
||||
|
||||
if (!vertex_info.size) // disabled, bind a null sampler
|
||||
@ -253,7 +253,7 @@ u32 GLGSRender::set_vertex_buffer()
|
||||
auto &texture = m_gl_attrib_buffers[index];
|
||||
|
||||
u8 *src = reinterpret_cast<u8*>(inline_vertex_array.data());
|
||||
auto mapping = m_attrib_ring_buffer->alloc_from_reserve(data_size, m_min_texbuffer_alignment);
|
||||
auto mapping = m_attrib_ring_buffer.alloc_from_reserve(data_size, m_min_texbuffer_alignment);
|
||||
u8 *dst = static_cast<u8*>(mapping.first);
|
||||
|
||||
src += offsets[index];
|
||||
@ -276,13 +276,13 @@ u32 GLGSRender::set_vertex_buffer()
|
||||
dst += element_size;
|
||||
}
|
||||
|
||||
texture.copy_from(m_attrib_ring_buffer->get_buffer(), gl_type, mapping.second, data_size);
|
||||
texture.copy_from(m_attrib_ring_buffer, gl_type, mapping.second, data_size);
|
||||
|
||||
//Link texture to uniform
|
||||
m_program->uniforms.texture(location, index + rsx::limits::textures_count, texture);
|
||||
if (!is_primitive_native(draw_mode))
|
||||
{
|
||||
std::tie(vertex_draw_count, offset_in_index_buffer) = get_index_array_for_emulated_non_indexed_draw({ { 0, vertex_draw_count } }, draw_mode, *m_index_ring_buffer);
|
||||
std::tie(vertex_draw_count, offset_in_index_buffer) = get_index_array_for_emulated_non_indexed_draw({ { 0, vertex_draw_count } }, draw_mode, m_index_ring_buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -298,12 +298,12 @@ u32 GLGSRender::set_vertex_buffer()
|
||||
if (draw_command == rsx::draw_command::array || draw_command == rsx::draw_command::indexed)
|
||||
{
|
||||
u32 verts_allocated = std::max(vertex_draw_count, max_index + 1);
|
||||
m_attrib_ring_buffer->reserve_and_map(verts_allocated * max_vertex_attrib_size);
|
||||
m_attrib_ring_buffer.reserve_and_map(verts_allocated * max_vertex_attrib_size);
|
||||
|
||||
for (int index = 0; index < rsx::limits::vertex_count; ++index)
|
||||
{
|
||||
int location;
|
||||
if (!m_program->uniforms.has_location(reg_table[index] + "_buffer", &location))
|
||||
if (!m_program->uniforms.has_location(rsx::vertex_program::input_attrib_names[index] + "_buffer", &location))
|
||||
continue;
|
||||
|
||||
bool enabled = !!(input_mask & (1 << index));
|
||||
@ -337,7 +337,7 @@ u32 GLGSRender::set_vertex_buffer()
|
||||
|
||||
if (draw_command == rsx::draw_command::array)
|
||||
{
|
||||
auto mapping = m_attrib_ring_buffer->alloc_from_reserve(data_size, m_min_texbuffer_alignment);
|
||||
auto mapping = m_attrib_ring_buffer.alloc_from_reserve(data_size, m_min_texbuffer_alignment);
|
||||
gsl::byte *dst = static_cast<gsl::byte*>(mapping.first);
|
||||
buffer_offset = mapping.second;
|
||||
|
||||
@ -354,7 +354,7 @@ u32 GLGSRender::set_vertex_buffer()
|
||||
if (draw_command == rsx::draw_command::indexed)
|
||||
{
|
||||
data_size = (max_index + 1) * element_size;
|
||||
auto mapping = m_attrib_ring_buffer->alloc_from_reserve(data_size, m_min_texbuffer_alignment);
|
||||
auto mapping = m_attrib_ring_buffer.alloc_from_reserve(data_size, m_min_texbuffer_alignment);
|
||||
gsl::byte *dst = static_cast<gsl::byte*>(mapping.first);
|
||||
buffer_offset = mapping.second;
|
||||
|
||||
@ -364,7 +364,7 @@ u32 GLGSRender::set_vertex_buffer()
|
||||
write_vertex_array_data_to_buffer(dest_span, src_ptr, 0, max_index + 1, vertex_info.type, vertex_info.size, vertex_info.stride, rsx::get_vertex_type_size_on_host(vertex_info.type, vertex_info.size));
|
||||
}
|
||||
|
||||
texture.copy_from(m_attrib_ring_buffer->get_buffer(), gl_type, buffer_offset, data_size);
|
||||
texture.copy_from(m_attrib_ring_buffer, gl_type, buffer_offset, data_size);
|
||||
|
||||
//Link texture to uniform
|
||||
m_program->uniforms.texture(location, index + rsx::limits::textures_count, texture);
|
||||
@ -385,11 +385,11 @@ u32 GLGSRender::set_vertex_buffer()
|
||||
|
||||
auto &texture = m_gl_attrib_buffers[index];
|
||||
|
||||
auto mapping = m_attrib_ring_buffer->alloc_from_reserve(data_size, m_min_texbuffer_alignment);
|
||||
auto mapping = m_attrib_ring_buffer.alloc_from_reserve(data_size, m_min_texbuffer_alignment);
|
||||
u8 *dst = static_cast<u8*>(mapping.first);
|
||||
|
||||
memcpy(dst, vertex_data.data(), data_size);
|
||||
texture.copy_from(m_attrib_ring_buffer->get_buffer(), gl_type, mapping.second, data_size);
|
||||
texture.copy_from(m_attrib_ring_buffer, gl_type, mapping.second, data_size);
|
||||
|
||||
//Link texture to uniform
|
||||
m_program->uniforms.texture(location, index + rsx::limits::textures_count, texture);
|
||||
@ -411,11 +411,11 @@ u32 GLGSRender::set_vertex_buffer()
|
||||
|
||||
if (draw_command == rsx::draw_command::array && !is_primitive_native(draw_mode))
|
||||
{
|
||||
std::tie(vertex_draw_count, offset_in_index_buffer) = get_index_array_for_emulated_non_indexed_draw(first_count_commands, draw_mode, *m_index_ring_buffer);
|
||||
std::tie(vertex_draw_count, offset_in_index_buffer) = get_index_array_for_emulated_non_indexed_draw(first_count_commands, draw_mode, m_index_ring_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
m_attrib_ring_buffer->unmap();
|
||||
m_attrib_ring_buffer.unmap();
|
||||
std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();
|
||||
m_vertex_upload_time += std::chrono::duration_cast<std::chrono::microseconds>(now - then).count();
|
||||
|
||||
|
@ -35,12 +35,12 @@ namespace rsx
|
||||
{
|
||||
std::function<bool(u32 addr, bool is_writing)> g_access_violation_handler;
|
||||
|
||||
std::string shaders_cache::path_to_root()
|
||||
std::string old_shaders_cache::shaders_cache::path_to_root()
|
||||
{
|
||||
return fs::get_executable_dir() + "data/";
|
||||
}
|
||||
|
||||
void shaders_cache::load(const std::string &path, shader_language lang)
|
||||
void old_shaders_cache::shaders_cache::load(const std::string &path, shader_language lang)
|
||||
{
|
||||
const std::string lang_name(::unveil<shader_language>::get(lang));
|
||||
|
||||
@ -82,7 +82,7 @@ namespace rsx
|
||||
}
|
||||
}
|
||||
|
||||
void shaders_cache::load(shader_language lang)
|
||||
void old_shaders_cache::shaders_cache::load(shader_language lang)
|
||||
{
|
||||
std::string root = path_to_root();
|
||||
|
||||
@ -745,6 +745,24 @@ namespace rsx
|
||||
return result;
|
||||
}
|
||||
|
||||
raw_program thread::get_raw_program() const
|
||||
{
|
||||
raw_program result;
|
||||
|
||||
u32 fp_info = rsx::method_registers[NV4097_SET_SHADER_PROGRAM];
|
||||
|
||||
result.state.output_attributes = rsx::method_registers[NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK];
|
||||
result.state.ctrl = rsx::method_registers[NV4097_SET_SHADER_CONTROL];
|
||||
|
||||
result.vertex_shader.ucode_ptr = transform_program;
|
||||
result.vertex_shader.offset = rsx::method_registers[NV4097_SET_TRANSFORM_PROGRAM_START];
|
||||
|
||||
result.fragment_shader.ucode_ptr = vm::base(rsx::get_address(fp_info & ~0x3, (fp_info & 0x3) - 1));
|
||||
result.fragment_shader.offset = 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void thread::reset()
|
||||
{
|
||||
//setup method registers
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <set>
|
||||
#include <mutex>
|
||||
#include "GCM.h"
|
||||
#include "rsx_cache.h"
|
||||
#include "RSXTexture.h"
|
||||
#include "RSXVertexProgram.h"
|
||||
#include "RSXFragmentProgram.h"
|
||||
@ -45,22 +46,25 @@ extern frame_capture_data frame_debug;
|
||||
|
||||
namespace rsx
|
||||
{
|
||||
enum class shader_language
|
||||
namespace old_shaders_cache
|
||||
{
|
||||
glsl,
|
||||
hlsl,
|
||||
};
|
||||
enum class shader_language
|
||||
{
|
||||
glsl,
|
||||
hlsl,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
struct unveil<rsx::shader_language>
|
||||
struct unveil<rsx::old_shaders_cache::shader_language>
|
||||
{
|
||||
static inline const char* get(rsx::shader_language in)
|
||||
static inline const char* get(rsx::old_shaders_cache::shader_language in)
|
||||
{
|
||||
switch (in)
|
||||
{
|
||||
case rsx::shader_language::glsl: return "glsl";
|
||||
case rsx::shader_language::hlsl: return "hlsl";
|
||||
case rsx::old_shaders_cache::shader_language::glsl: return "glsl";
|
||||
case rsx::old_shaders_cache::shader_language::hlsl: return "hlsl";
|
||||
}
|
||||
|
||||
return "";
|
||||
@ -83,52 +87,55 @@ namespace rsx
|
||||
};
|
||||
}
|
||||
|
||||
struct decompiled_shader
|
||||
namespace old_shaders_cache
|
||||
{
|
||||
std::string code;
|
||||
};
|
||||
|
||||
struct finalized_shader
|
||||
{
|
||||
u64 ucode_hash;
|
||||
std::string code;
|
||||
};
|
||||
|
||||
template<typename Type, typename KeyType = u64, typename Hasher = std::hash<KeyType>>
|
||||
struct cache
|
||||
{
|
||||
private:
|
||||
std::unordered_map<KeyType, Type, Hasher> m_entries;
|
||||
|
||||
public:
|
||||
const Type* find(u64 key) const
|
||||
struct decompiled_shader
|
||||
{
|
||||
auto found = m_entries.find(key);
|
||||
std::string code;
|
||||
};
|
||||
|
||||
if (found == m_entries.end())
|
||||
return nullptr;
|
||||
|
||||
return &found->second;
|
||||
}
|
||||
|
||||
void insert(KeyType key, const Type &shader)
|
||||
struct finalized_shader
|
||||
{
|
||||
m_entries.insert({ key, shader });
|
||||
}
|
||||
};
|
||||
u64 ucode_hash;
|
||||
std::string code;
|
||||
};
|
||||
|
||||
struct shaders_cache
|
||||
{
|
||||
cache<decompiled_shader> decompiled_fragment_shaders;
|
||||
cache<decompiled_shader> decompiled_vertex_shaders;
|
||||
cache<finalized_shader> finailized_fragment_shaders;
|
||||
cache<finalized_shader> finailized_vertex_shaders;
|
||||
template<typename Type, typename KeyType = u64, typename Hasher = std::hash<KeyType>>
|
||||
struct cache
|
||||
{
|
||||
private:
|
||||
std::unordered_map<KeyType, Type, Hasher> m_entries;
|
||||
|
||||
void load(const std::string &path, shader_language lang);
|
||||
void load(shader_language lang);
|
||||
public:
|
||||
const Type* find(u64 key) const
|
||||
{
|
||||
auto found = m_entries.find(key);
|
||||
|
||||
static std::string path_to_root();
|
||||
};
|
||||
if (found == m_entries.end())
|
||||
return nullptr;
|
||||
|
||||
return &found->second;
|
||||
}
|
||||
|
||||
void insert(KeyType key, const Type &shader)
|
||||
{
|
||||
m_entries.insert({ key, shader });
|
||||
}
|
||||
};
|
||||
|
||||
struct shaders_cache
|
||||
{
|
||||
cache<decompiled_shader> decompiled_fragment_shaders;
|
||||
cache<decompiled_shader> decompiled_vertex_shaders;
|
||||
cache<finalized_shader> finailized_fragment_shaders;
|
||||
cache<finalized_shader> finailized_vertex_shaders;
|
||||
|
||||
void load(const std::string &path, shader_language lang);
|
||||
void load(shader_language lang);
|
||||
|
||||
static std::string path_to_root();
|
||||
};
|
||||
}
|
||||
|
||||
u32 get_vertex_type_size_on_host(vertex_base_type type, u32 size);
|
||||
|
||||
@ -201,7 +208,8 @@ namespace rsx
|
||||
std::stack<u32> m_call_stack;
|
||||
|
||||
public:
|
||||
struct shaders_cache shaders_cache;
|
||||
old_shaders_cache::shaders_cache shaders_cache;
|
||||
rsx::programs_cache programs_cache;
|
||||
|
||||
CellGcmControl* ctrl = nullptr;
|
||||
|
||||
@ -376,6 +384,7 @@ namespace rsx
|
||||
|
||||
virtual std::pair<std::string, std::string> get_programs() const { return std::make_pair("", ""); };
|
||||
|
||||
struct raw_program get_raw_program() const;
|
||||
public:
|
||||
void reset();
|
||||
void init(const u32 ioAddress, const u32 ioSize, const u32 ctrlAddress, const u32 localAddress);
|
||||
|
@ -418,7 +418,7 @@ namespace
|
||||
|
||||
VKGSRender::VKGSRender() : GSRender(frame_type::Vulkan)
|
||||
{
|
||||
shaders_cache.load(rsx::shader_language::glsl);
|
||||
shaders_cache.load(rsx::old_shaders_cache::shader_language::glsl);
|
||||
|
||||
m_thread_context.createInstance("RPCS3");
|
||||
m_thread_context.makeCurrentInstance(1);
|
||||
|
114
rpcs3/Emu/RSX/rsx_cache.cpp
Normal file
114
rpcs3/Emu/RSX/rsx_cache.cpp
Normal file
@ -0,0 +1,114 @@
|
||||
#include "stdafx.h"
|
||||
#include "rsx_cache.h"
|
||||
#include "Emu/System.h"
|
||||
|
||||
namespace rsx
|
||||
{
|
||||
shader_info shaders_cache::get(const program_cache_context &ctxt, raw_shader &raw_shader, const program_state& state)
|
||||
{
|
||||
auto found_entry = m_entries.find(raw_shader);
|
||||
|
||||
shader_info info;
|
||||
entry_t *entry;
|
||||
|
||||
static const std::string &path = fs::get_executable_dir() + "data/cache/";
|
||||
|
||||
if (found_entry != m_entries.end())
|
||||
{
|
||||
entry = &found_entry->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
//analyze_raw_shader(raw_shader);
|
||||
|
||||
fs::file{ path + fmt::format("%016llx.", raw_shader.hash()) + (raw_shader.type == rsx::program_type::fragment ? "fp" : "vp") + ".ucode", fs::rewrite }
|
||||
.write(raw_shader.ucode.data(), raw_shader.ucode.size());
|
||||
|
||||
rsx::decompiled_shader decompiled_shader = decompile(raw_shader, ctxt.lang);
|
||||
auto inserted = m_entries.insert({ raw_shader, entry_t{ decompiled_shader } }).first;
|
||||
inserted->second.decompiled.raw = &inserted->first;
|
||||
entry = &inserted->second;
|
||||
}
|
||||
|
||||
info.decompiled = &entry->decompiled;
|
||||
|
||||
auto found_complete = entry->complete.find(state);
|
||||
|
||||
if (found_complete != entry->complete.end())
|
||||
{
|
||||
info.complete = &found_complete->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
rsx::complete_shader complete_shader = ctxt.complete_shader(entry->decompiled, state);
|
||||
complete_shader.decompiled = info.decompiled;
|
||||
info.complete = &entry->complete.insert({ state, complete_shader }).first->second;
|
||||
info.complete->user_data = nullptr;
|
||||
|
||||
fs::file{ path + fmt::format("%016llx.", raw_shader.hash()) + (raw_shader.type == rsx::program_type::fragment ? "fp" : "vp") + "." + (ctxt.lang == rsx::decompile_language::glsl ? "glsl" : "hlsl"), fs::rewrite }.write(info.complete->code);
|
||||
}
|
||||
|
||||
if (info.complete->user_data == nullptr)
|
||||
{
|
||||
info.complete->user_data = ctxt.compile_shader(raw_shader.type, info.complete->code);
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
void shaders_cache::clear(const program_cache_context& context)
|
||||
{
|
||||
for (auto &entry : m_entries)
|
||||
{
|
||||
for (auto &shader : entry.second.complete)
|
||||
{
|
||||
context.remove_shader(shader.second.user_data);
|
||||
}
|
||||
}
|
||||
|
||||
m_entries.clear();
|
||||
}
|
||||
|
||||
programs_cache::~programs_cache()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
program_info programs_cache::get(raw_program raw_program_, decompile_language lang)
|
||||
{
|
||||
raw_program_.vertex_shader.type = program_type::vertex;
|
||||
raw_program_.fragment_shader.type = program_type::fragment;
|
||||
|
||||
analyze_raw_shader(raw_program_.vertex_shader);
|
||||
analyze_raw_shader(raw_program_.fragment_shader);
|
||||
|
||||
auto found = m_program_cache.find(raw_program_);
|
||||
|
||||
if (found != m_program_cache.end())
|
||||
{
|
||||
return found->second;
|
||||
}
|
||||
|
||||
program_info result;
|
||||
|
||||
result.vertex_shader = m_vertex_shaders_cache.get(context, raw_program_.vertex_shader, raw_program_.state);
|
||||
result.fragment_shader = m_vertex_shaders_cache.get(context, raw_program_.fragment_shader, raw_program_.state);
|
||||
result.program = context.make_program(result.vertex_shader.complete->user_data, result.fragment_shader.complete->user_data);
|
||||
m_program_cache.insert({ raw_program_, result });
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void programs_cache::clear()
|
||||
{
|
||||
for (auto &entry : m_program_cache)
|
||||
{
|
||||
context.remove_program(entry.second.program);
|
||||
}
|
||||
|
||||
m_program_cache.clear();
|
||||
|
||||
m_vertex_shaders_cache.clear(context);
|
||||
m_fragment_shader_cache.clear(context);
|
||||
}
|
||||
}
|
61
rpcs3/Emu/RSX/rsx_cache.h
Normal file
61
rpcs3/Emu/RSX/rsx_cache.h
Normal file
@ -0,0 +1,61 @@
|
||||
#pragma once
|
||||
#include <rsx_decompiler.h>
|
||||
|
||||
namespace rsx
|
||||
{
|
||||
struct shader_info
|
||||
{
|
||||
decompiled_shader *decompiled;
|
||||
complete_shader *complete;
|
||||
};
|
||||
|
||||
struct program_info
|
||||
{
|
||||
shader_info vertex_shader;
|
||||
shader_info fragment_shader;
|
||||
|
||||
void *program;
|
||||
};
|
||||
|
||||
struct program_cache_context
|
||||
{
|
||||
decompile_language lang;
|
||||
|
||||
void*(*compile_shader)(program_type type, const std::string &code);
|
||||
rsx::complete_shader(*complete_shader)(const decompiled_shader &shader, program_state state);
|
||||
void*(*make_program)(const void *vertex_shader, const void *fragment_shader);
|
||||
void(*remove_program)(void *ptr);
|
||||
void(*remove_shader)(void *ptr);
|
||||
};
|
||||
|
||||
struct shaders_cache
|
||||
{
|
||||
struct entry_t
|
||||
{
|
||||
decompiled_shader decompiled;
|
||||
std::unordered_map<program_state, complete_shader, hasher> complete;
|
||||
};
|
||||
|
||||
std::unordered_map<raw_shader, entry_t, hasher> m_entries;
|
||||
|
||||
public:
|
||||
shader_info get(const program_cache_context &ctxt, raw_shader &raw_shader, const program_state& state);
|
||||
void clear(const program_cache_context& context);
|
||||
};
|
||||
|
||||
class programs_cache
|
||||
{
|
||||
std::unordered_map<raw_program, program_info, hasher> m_program_cache;
|
||||
|
||||
shaders_cache m_vertex_shaders_cache;
|
||||
shaders_cache m_fragment_shader_cache;
|
||||
|
||||
public:
|
||||
program_cache_context context;
|
||||
|
||||
~programs_cache();
|
||||
|
||||
program_info get(raw_program raw_program_, decompile_language lang);
|
||||
void clear();
|
||||
};
|
||||
}
|
@ -1,5 +1,8 @@
|
||||
#include "stdafx.h"
|
||||
#include "rsx_utils.h"
|
||||
#include "rsx_methods.h"
|
||||
#include "Emu/RSX/GCM.h"
|
||||
#include "Common/BufferUtils.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
@ -42,4 +45,66 @@ namespace rsx
|
||||
dst.reset(new u8[clip_h * dst_pitch]);
|
||||
clip_image(dst.get(), src, clip_x, clip_y, clip_w, clip_h, bpp, src_pitch, dst_pitch);
|
||||
}
|
||||
|
||||
void fill_scale_offset_matrix(void *dest_, bool transpose,
|
||||
float offset_x, float offset_y, float offset_z,
|
||||
float scale_x, float scale_y, float scale_z)
|
||||
{
|
||||
char *dest = (char*)dest_;
|
||||
|
||||
if (transpose)
|
||||
{
|
||||
stream_vector(dest + 4 * sizeof(f32) * 0, scale_x, 0, 0, 0);
|
||||
stream_vector(dest + 4 * sizeof(f32) * 1, 0, scale_y, 0, 0);
|
||||
stream_vector(dest + 4 * sizeof(f32) * 2, 0, 0, scale_z, 0);
|
||||
stream_vector(dest + 4 * sizeof(f32) * 3, offset_x, offset_y, offset_z, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
stream_vector(dest + 4 * sizeof(f32) * 0, scale_x, 0, 0, offset_x);
|
||||
stream_vector(dest + 4 * sizeof(f32) * 1, 0, scale_y, 0, offset_y);
|
||||
stream_vector(dest + 4 * sizeof(f32) * 2, 0, 0, scale_z, offset_z);
|
||||
stream_vector(dest + 4 * sizeof(f32) * 3, 0.f, 0.f, 0.f, 1.f);
|
||||
}
|
||||
}
|
||||
|
||||
void fill_window_matrix(void *dest, bool transpose)
|
||||
{
|
||||
u32 shader_window = method_registers[NV4097_SET_SHADER_WINDOW];
|
||||
|
||||
u16 height = shader_window & 0xfff;
|
||||
window_origin origin = to_window_origin((shader_window >> 12) & 0xf);
|
||||
window_pixel_center pixelCenter = to_window_pixel_center(shader_window >> 16);
|
||||
|
||||
f32 offset_x = f32(method_registers[NV4097_SET_WINDOW_OFFSET] & 0xffff);
|
||||
f32 offset_y = f32(method_registers[NV4097_SET_WINDOW_OFFSET] >> 16);
|
||||
f32 scale_y = 1.0;
|
||||
|
||||
if (origin == window_origin::bottom)
|
||||
{
|
||||
offset_y = height - offset_y + 1;
|
||||
scale_y = -1.0f;
|
||||
}
|
||||
|
||||
if (false && pixelCenter == window_pixel_center::half)
|
||||
{
|
||||
offset_x += 0.5f;
|
||||
offset_y += 0.5f;
|
||||
}
|
||||
|
||||
fill_scale_offset_matrix(dest, transpose, offset_x, offset_y, 0.0f, 1.0f, scale_y, 1.0f);
|
||||
}
|
||||
|
||||
void fill_viewport_matrix(void *buffer, bool transpose)
|
||||
{
|
||||
f32 offset_x = (f32&)method_registers[NV4097_SET_VIEWPORT_OFFSET + 0];
|
||||
f32 offset_y = (f32&)method_registers[NV4097_SET_VIEWPORT_OFFSET + 1];
|
||||
f32 offset_z = (f32&)method_registers[NV4097_SET_VIEWPORT_OFFSET + 2];
|
||||
|
||||
f32 scale_x = (f32&)method_registers[NV4097_SET_VIEWPORT_SCALE + 0];
|
||||
f32 scale_y = (f32&)method_registers[NV4097_SET_VIEWPORT_SCALE + 1];
|
||||
f32 scale_z = (f32&)method_registers[NV4097_SET_VIEWPORT_SCALE + 2];
|
||||
|
||||
fill_scale_offset_matrix(buffer, transpose, offset_x, offset_y, offset_z, scale_x, scale_y, scale_z);
|
||||
}
|
||||
}
|
||||
|
@ -114,4 +114,10 @@ namespace rsx
|
||||
|
||||
void clip_image(u8 *dst, const u8 *src, int clip_x, int clip_y, int clip_w, int clip_h, int bpp, int src_pitch, int dst_pitch);
|
||||
void clip_image(std::unique_ptr<u8[]>& dst, const u8 *src, int clip_x, int clip_y, int clip_w, int clip_h, int bpp, int src_pitch, int dst_pitch);
|
||||
|
||||
void fill_scale_offset_matrix(void *dest_, bool transpose,
|
||||
float offset_x, float offset_y, float offset_z,
|
||||
float scale_x, float scale_y, float scale_z);
|
||||
void fill_window_matrix(void *dest, bool transpose);
|
||||
void fill_viewport_matrix(void *buffer, bool transpose);
|
||||
}
|
||||
|
@ -61,6 +61,31 @@
|
||||
<Import Project="..\rpcs3_llvm.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug - MemLeak|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\rsx_program_decompiler\rsx_decompiler;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\rsx_program_decompiler\rsx_decompiler;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\rsx_program_decompiler\rsx_decompiler;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\rsx_program_decompiler\rsx_decompiler;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\rsx_program_decompiler\rsx_decompiler;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="emucore.vcxproj">
|
||||
<Project>{c4a10229-4712-4bd2-b63e-50d93c67a038}</Project>
|
||||
@ -77,6 +102,7 @@
|
||||
<ClInclude Include="Emu\RSX\GL\gl_render_targets.h" />
|
||||
<ClInclude Include="Emu\RSX\GL\gl_texture_cache.h" />
|
||||
<ClInclude Include="Emu\RSX\GL\OpenGL.h" />
|
||||
<ClInclude Include="Emu\RSX\GL\rsx_gl_cache.h" />
|
||||
<ClInclude Include="Emu\RSX\GL\rsx_gl_texture.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@ -87,6 +113,7 @@
|
||||
<ClCompile Include="Emu\RSX\GL\gl_helpers.cpp" />
|
||||
<ClCompile Include="Emu\RSX\GL\gl_render_targets.cpp" />
|
||||
<ClCompile Include="Emu\RSX\GL\OpenGL.cpp" />
|
||||
<ClCompile Include="Emu\RSX\GL\rsx_gl_cache.cpp" />
|
||||
<ClCompile Include="Emu\RSX\GL\rsx_gl_texture.cpp" />
|
||||
<ClCompile Include="Emu\RSX\GL\vertex_buffer.cpp" />
|
||||
</ItemGroup>
|
||||
|
@ -10,6 +10,7 @@
|
||||
<ClCompile Include="Emu\RSX\GL\OpenGL.cpp" />
|
||||
<ClCompile Include="Emu\RSX\GL\gl_render_targets.cpp" />
|
||||
<ClCompile Include="Emu\RSX\GL\vertex_buffer.cpp" />
|
||||
<ClCompile Include="Emu\RSX\GL\rsx_gl_cache.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Emu\RSX\GL\rsx_gl_texture.h" />
|
||||
@ -23,5 +24,6 @@
|
||||
<ClInclude Include="Emu\RSX\GL\OpenGL.h" />
|
||||
<ClInclude Include="Emu\RSX\GL\gl_texture_cache.h" />
|
||||
<ClInclude Include="Emu\RSX\GL\gl_render_targets.h" />
|
||||
<ClInclude Include="Emu\RSX\GL\rsx_gl_cache.h" />
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -94,7 +94,7 @@
|
||||
<PropertyGroup />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\Vulkan\Vulkan-LoaderAndValidationLayers\include;..\Vulkan\glslang\glslang\Public;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\rsx_program_decompiler\rsx_decompiler;..\Vulkan\Vulkan-LoaderAndValidationLayers\include;..\Vulkan\glslang\glslang\Public;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
|
@ -277,6 +277,7 @@
|
||||
<ClCompile Include="Emu\RSX\Common\VertexProgramDecompiler.cpp" />
|
||||
<ClCompile Include="Emu\RSX\GCM.cpp" />
|
||||
<ClCompile Include="Emu\RSX\Null\NullGSRender.cpp" />
|
||||
<ClCompile Include="Emu\RSX\rsx_cache.cpp" />
|
||||
<ClCompile Include="Emu\RSX\rsx_methods.cpp" />
|
||||
<ClCompile Include="Emu\RSX\rsx_utils.cpp" />
|
||||
<ClCompile Include="Crypto\aes.cpp">
|
||||
@ -613,6 +614,7 @@
|
||||
<ClInclude Include="Emu\CPU\CPUThread.h" />
|
||||
<ClInclude Include="Emu\DbgCommand.h" />
|
||||
<ClInclude Include="Emu\Memory\wait_engine.h" />
|
||||
<ClInclude Include="Emu\RSX\rsx_cache.h" />
|
||||
<ClInclude Include="Emu\VFS.h" />
|
||||
<ClInclude Include="Emu\GameInfo.h" />
|
||||
<ClInclude Include="Emu\IdManager.h" />
|
||||
@ -669,6 +671,21 @@
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug - MemLeak|x64'">
|
||||
<IncludePath>..\rsx_program_decompiler\rsx_decompiler;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">
|
||||
<IncludePath>..\rsx_program_decompiler\rsx_decompiler;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<IncludePath>..\rsx_program_decompiler\rsx_decompiler;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<IncludePath>..\rsx_program_decompiler\rsx_decompiler;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">
|
||||
<IncludePath>..\rsx_program_decompiler\rsx_decompiler;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
|
@ -860,6 +860,9 @@
|
||||
<ClCompile Include="Emu\PSP2\Modules\sceVoiceQoS.cpp">
|
||||
<Filter>Emu\PSP2\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\RSX\rsx_cache.cpp">
|
||||
<Filter>Emu\GPU\RSX</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Utilities\dynamic_library.cpp">
|
||||
<Filter>Utilities</Filter>
|
||||
</ClCompile>
|
||||
@ -1648,6 +1651,9 @@
|
||||
<ClInclude Include="..\Utilities\sync.h">
|
||||
<Filter>Utilities</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\RSX\rsx_cache.h">
|
||||
<Filter>Emu\GPU\RSX</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Utilities\dynamic_library.h">
|
||||
<Filter>Utilities</Filter>
|
||||
</ClInclude>
|
||||
|
@ -90,7 +90,7 @@
|
||||
</Message>
|
||||
</PreBuildEvent>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\wxWidgets\include\msvc;..\wxWidgets\include;..\3rdparty\XAudio2_7;..\Vulkan\Vulkan-LoaderAndValidationLayers\include;..\Vulkan\glslang\glslang\Public;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\rsx_program_decompiler\rsx_decompiler;..\wxWidgets\include\msvc;..\wxWidgets\include;..\3rdparty\XAudio2_7;..\Vulkan\Vulkan-LoaderAndValidationLayers\include;..\Vulkan\glslang\glslang\Public;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalLibraryDirectories Condition="'$(Configuration)|$(Platform)'=='Debug - MemLeak|x64'">..\Vulkan\glslang-build\SPIRV\Debug;..\Vulkan\glslang-build\OGLCompilersDLL\Debug;..\Vulkan\glslang-build\glslang\OSDependent\Windows\Debug;..\Vulkan\Vulkan-build\loader\Debug;..\Vulkan\glslang-build\glslang\Debug;..\3rdparty\OpenAL\libs\Win64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
@ -104,7 +104,7 @@
|
||||
<AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">wxmsw31ud_adv.lib;wxbase31ud.lib;wxmsw31ud_core.lib;wxmsw31ud_aui.lib;wxtiffd.lib;wxjpegd.lib;wxpngd.lib;wxzlibd.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Release|x64'">wxmsw31u_adv.lib;wxbase31u.lib;wxmsw31u_core.lib;wxmsw31u_aui.lib;wxtiff.lib;wxjpeg.lib;wxpng.lib;wxzlib.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">wxmsw31u_adv.lib;wxbase31u.lib;wxmsw31u_core.lib;wxmsw31u_aui.lib;wxtiff.lib;wxjpeg.lib;wxpng.lib;wxzlib.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>VKstatic.1.lib;glslang.lib;OSDependent.lib;OGLCompiler.lib;SPIRV.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>VKstatic.1.lib;glslang.lib;OSDependent.lib;OGLCompiler.lib;SPIRV.lib;rsx_decompiler.lib;shader_code.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<BaseAddress>0x10000</BaseAddress>
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit b4d09867643df26e503ec09119c8048832676780
|
||||
Subproject commit e4d938c76850549acd837326e2fe0890d5b4be03
|
Loading…
x
Reference in New Issue
Block a user