mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-02-16 03:40:27 +00:00
rsx: Implement stencil mirror views
- Implements a mirror view of D24S8 data that accesses the stencil components. Finishes the implementation of TEX2D_DEPTH_RGBA as the stencil component was previously missing from the reconstructed data - Add a few missing destructors Image classes are inherited a lot and I forgot to make the dtors virtual
This commit is contained in:
parent
696b91cb9b
commit
4b79ef1ad9
@ -278,10 +278,10 @@ std::string FragmentProgramDecompiler::Format(const std::string& code, bool igno
|
||||
const std::pair<std::string, std::function<std::string()>> repl_list[] =
|
||||
{
|
||||
{ "$$", []() -> std::string { return "$"; } },
|
||||
{ "$0", [this]() -> std::string {return GetSRC<SRC0>(src0);} },//std::bind(std::mem_fn(&GLFragmentDecompilerThread::GetSRC<SRC0>), *this, src0) },
|
||||
{ "$1", [this]() -> std::string {return GetSRC<SRC1>(src1);} },//std::bind(std::mem_fn(&GLFragmentDecompilerThread::GetSRC<SRC1>), this, src1) },
|
||||
{ "$2", [this]() -> std::string {return GetSRC<SRC2>(src2);} },//std::bind(std::mem_fn(&GLFragmentDecompilerThread::GetSRC<SRC2>), this, src2) },
|
||||
{ "$t", std::bind(std::mem_fn(&FragmentProgramDecompiler::AddTex), this) },
|
||||
{ "$0", [this]() -> std::string {return GetSRC<SRC0>(src0);} },
|
||||
{ "$1", [this]() -> std::string {return GetSRC<SRC1>(src1);} },
|
||||
{ "$2", [this]() -> std::string {return GetSRC<SRC2>(src2);} },
|
||||
{ "$t", [this]() -> std::string { return "tex" + std::to_string(dst.tex_num);} },
|
||||
{ "$_i", [this]() -> std::string {return std::to_string(dst.tex_num);} },
|
||||
{ "$m", std::bind(std::mem_fn(&FragmentProgramDecompiler::GetMask), this) },
|
||||
{ "$ifcond ", [this]() -> std::string
|
||||
@ -624,6 +624,7 @@ bool FragmentProgramDecompiler::handle_tex_srb(u32 opcode)
|
||||
AddX2d();
|
||||
AddCode(Format("x2d = $0.xyxy + $1.xxxx * $2.xzxz + $1.yyyy * $2.ywyw;", true));
|
||||
case RSX_FP_OPCODE_TEX:
|
||||
AddTex();
|
||||
switch (m_prog.get_texture_dimension(dst.tex_num))
|
||||
{
|
||||
case rsx::texture_dimension_extended::texture_dimension_1d:
|
||||
@ -655,6 +656,7 @@ bool FragmentProgramDecompiler::handle_tex_srb(u32 opcode)
|
||||
AddX2d();
|
||||
AddCode(Format("x2d = $0.xyxy + $1.xxxx * $2.xzxz + $1.yyyy * $2.ywyw;", true));
|
||||
case RSX_FP_OPCODE_TXP:
|
||||
AddTex();
|
||||
switch (m_prog.get_texture_dimension(dst.tex_num))
|
||||
{
|
||||
case rsx::texture_dimension_extended::texture_dimension_1d:
|
||||
@ -679,6 +681,7 @@ bool FragmentProgramDecompiler::handle_tex_srb(u32 opcode)
|
||||
}
|
||||
return false;
|
||||
case RSX_FP_OPCODE_TXD:
|
||||
AddTex();
|
||||
switch (m_prog.get_texture_dimension(dst.tex_num))
|
||||
{
|
||||
case rsx::texture_dimension_extended::texture_dimension_1d:
|
||||
@ -697,6 +700,7 @@ bool FragmentProgramDecompiler::handle_tex_srb(u32 opcode)
|
||||
}
|
||||
return false;
|
||||
case RSX_FP_OPCODE_TXB:
|
||||
AddTex();
|
||||
switch (m_prog.get_texture_dimension(dst.tex_num))
|
||||
{
|
||||
case rsx::texture_dimension_extended::texture_dimension_1d:
|
||||
@ -715,6 +719,7 @@ bool FragmentProgramDecompiler::handle_tex_srb(u32 opcode)
|
||||
}
|
||||
return false;
|
||||
case RSX_FP_OPCODE_TXL:
|
||||
AddTex();
|
||||
switch (m_prog.get_texture_dimension(dst.tex_num))
|
||||
{
|
||||
case rsx::texture_dimension_extended::texture_dimension_1d:
|
||||
|
@ -481,9 +481,10 @@ namespace glsl
|
||||
" }\n"
|
||||
"}\n\n"
|
||||
|
||||
"vec4 texture2DReconstruct(sampler2D tex, vec2 coord, float remap)\n"
|
||||
"vec4 texture2DReconstruct(sampler2D tex, usampler2D stencil_tex, vec2 coord, float remap)\n"
|
||||
"{\n"
|
||||
" vec4 result = decodeLinearDepth(texture(tex, coord.xy).r);\n"
|
||||
" result.z = float(texture(stencil_tex, coord.xy).x) / 255.f;\n"
|
||||
" uint remap_vector = floatBitsToUint(remap) & 0xFF;\n"
|
||||
" if (remap_vector == 0xE4) return result;\n\n"
|
||||
" vec4 tmp;\n"
|
||||
@ -555,27 +556,30 @@ namespace glsl
|
||||
" return rgba;\n"
|
||||
"}\n\n"
|
||||
|
||||
"#define TEX1D(index, tex, coord1) process_texel(texture(tex, coord1 * texture_parameters[index].x), floatBitsToUint(texture_parameters[index].w))\n"
|
||||
"#define TEX1D_BIAS(index, tex, coord1, bias) process_texel(texture(tex, coord1 * texture_parameters[index].x, bias), floatBitsToUint(texture_parameters[index].w))\n"
|
||||
"#define TEX1D_LOD(index, tex, coord1, lod) process_texel(textureLod(tex, coord1 * texture_parameters[index].x, lod), floatBitsToUint(texture_parameters[index].w))\n"
|
||||
"#define TEX1D_GRAD(index, tex, coord1, dpdx, dpdy) process_texel(textureGrad(tex, coord1 * texture_parameters[index].x, dpdx, dpdy), floatBitsToUint(texture_parameters[index].w))\n"
|
||||
"#define TEX1D_PROJ(index, tex, coord2) process_texel(textureProj(tex, coord2 * vec2(texture_parameters[index].x, 1.)), floatBitsToUint(texture_parameters[index].w))\n"
|
||||
"#define TEX_NAME(index) tex##index\n"
|
||||
"#define TEX_NAME_STENCIL(index) tex##index##_stencil\n\n"
|
||||
|
||||
"#define TEX2D(index, tex, coord2) process_texel(texture(tex, coord2 * texture_parameters[index].xy), floatBitsToUint(texture_parameters[index].w))\n"
|
||||
"#define TEX2D_BIAS(index, tex, coord2, bias) process_texel(texture(tex, coord2 * texture_parameters[index].xy, bias), floatBitsToUint(texture_parameters[index].w))\n"
|
||||
"#define TEX2D_LOD(index, tex, coord2, lod) process_texel(textureLod(tex, coord2 * texture_parameters[index].xy, lod), floatBitsToUint(texture_parameters[index].w))\n"
|
||||
"#define TEX2D_GRAD(index, tex, coord2, dpdx, dpdy) process_texel(textureGrad(tex, coord2 * texture_parameters[index].xy, dpdx, dpdy), floatBitsToUint(texture_parameters[index].w))\n"
|
||||
"#define TEX2D_PROJ(index, tex, coord4) process_texel(textureProj(tex, coord4 * vec4(texture_parameters[index].xy, 1., 1.)), floatBitsToUint(texture_parameters[index].w))\n"
|
||||
"#define TEX1D(index, coord1) process_texel(texture(TEX_NAME(index), coord1 * texture_parameters[index].x), floatBitsToUint(texture_parameters[index].w))\n"
|
||||
"#define TEX1D_BIAS(index, coord1, bias) process_texel(texture(TEX_NAME(index), coord1 * texture_parameters[index].x, bias), floatBitsToUint(texture_parameters[index].w))\n"
|
||||
"#define TEX1D_LOD(index, coord1, lod) process_texel(textureLod(TEX_NAME(index), coord1 * texture_parameters[index].x, lod), floatBitsToUint(texture_parameters[index].w))\n"
|
||||
"#define TEX1D_GRAD(index, coord1, dpdx, dpdy) process_texel(textureGrad(TEX_NAME(index), coord1 * texture_parameters[index].x, dpdx, dpdy), floatBitsToUint(texture_parameters[index].w))\n"
|
||||
"#define TEX1D_PROJ(index, coord2) process_texel(textureProj(TEX_NAME(index), coord2 * vec2(texture_parameters[index].x, 1.)), floatBitsToUint(texture_parameters[index].w))\n"
|
||||
|
||||
"#define TEX2D_DEPTH_RGBA8(index, tex, coord2) process_texel(texture2DReconstruct(tex, coord2 * texture_parameters[index].xy, texture_parameters[index].z), floatBitsToUint(texture_parameters[index].w))\n"
|
||||
"#define TEX2D_SHADOW(index, tex, coord3) texture(tex, coord3 * vec3(texture_parameters[index].xy, 1.))\n"
|
||||
"#define TEX2D_SHADOWPROJ(index, tex, coord4) textureProj(tex, coord4 * vec4(texture_parameters[index].xy, 1., 1.))\n"
|
||||
"#define TEX2D(index, coord2) process_texel(texture(TEX_NAME(index), coord2 * texture_parameters[index].xy), floatBitsToUint(texture_parameters[index].w))\n"
|
||||
"#define TEX2D_BIAS(index, coord2, bias) process_texel(texture(TEX_NAME(index), coord2 * texture_parameters[index].xy, bias), floatBitsToUint(texture_parameters[index].w))\n"
|
||||
"#define TEX2D_LOD(index, coord2, lod) process_texel(textureLod(TEX_NAME(index), coord2 * texture_parameters[index].xy, lod), floatBitsToUint(texture_parameters[index].w))\n"
|
||||
"#define TEX2D_GRAD(index, coord2, dpdx, dpdy) process_texel(textureGrad(TEX_NAME(index), coord2 * texture_parameters[index].xy, dpdx, dpdy), floatBitsToUint(texture_parameters[index].w))\n"
|
||||
"#define TEX2D_PROJ(index, coord4) process_texel(textureProj(TEX_NAME(index), coord4 * vec4(texture_parameters[index].xy, 1., 1.)), floatBitsToUint(texture_parameters[index].w))\n"
|
||||
|
||||
"#define TEX3D(index, tex, coord3) process_texel(texture(tex, coord3), floatBitsToUint(texture_parameters[index].w))\n"
|
||||
"#define TEX3D_BIAS(index, tex, coord3, bias) process_texel(texture(tex, coord3, bias), floatBitsToUint(texture_parameters[index].w))\n"
|
||||
"#define TEX3D_LOD(index, tex, coord3, lod) process_texel(textureLod(tex, coord3, lod), floatBitsToUint(texture_parameters[index].w))\n"
|
||||
"#define TEX3D_GRAD(index, tex, coord3, dpdx, dpdy) process_texel(textureGrad(tex, coord3, dpdx, dpdy), floatBitsToUint(texture_parameters[index].w))\n"
|
||||
"#define TEX3D_PROJ(index, tex, coord4) process_texel(textureProj(tex, coord4), floatBitsToUint(texture_parameters[index].w))\n\n";
|
||||
"#define TEX2D_DEPTH_RGBA8(index, coord2) process_texel(texture2DReconstruct(TEX_NAME(index), TEX_NAME_STENCIL(index), coord2 * texture_parameters[index].xy, texture_parameters[index].z), floatBitsToUint(texture_parameters[index].w))\n"
|
||||
"#define TEX2D_SHADOW(index, coord3) texture(TEX_NAME(index), coord3 * vec3(texture_parameters[index].xy, 1.))\n"
|
||||
"#define TEX2D_SHADOWPROJ(index, coord4) textureProj(TEX_NAME(index), coord4 * vec4(texture_parameters[index].xy, 1., 1.))\n"
|
||||
|
||||
"#define TEX3D(index, coord3) process_texel(texture(TEX_NAME(index), coord3), floatBitsToUint(texture_parameters[index].w))\n"
|
||||
"#define TEX3D_BIAS(index, coord3, bias) process_texel(texture(TEX_NAME(index), coord3, bias), floatBitsToUint(texture_parameters[index].w))\n"
|
||||
"#define TEX3D_LOD(index, coord3, lod) process_texel(textureLod(TEX_NAME(index), coord3, lod), floatBitsToUint(texture_parameters[index].w))\n"
|
||||
"#define TEX3D_GRAD(index, coord3, dpdx, dpdy) process_texel(textureGrad(TEX_NAME(index), coord3, dpdx, dpdy), floatBitsToUint(texture_parameters[index].w))\n"
|
||||
"#define TEX3D_PROJ(index, coord4) process_texel(textureProj(TEX_NAME(index), coord4), floatBitsToUint(texture_parameters[index].w))\n\n";
|
||||
}
|
||||
|
||||
if (require_wpos)
|
||||
@ -619,49 +623,49 @@ namespace glsl
|
||||
case FUNCTION::FUNCTION_REFL:
|
||||
return "vec4($0 - 2.0 * (dot($0, $1)) * $1)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D:
|
||||
return "TEX1D($_i, $t, $0.x)";
|
||||
return "TEX1D($_i, $0.x)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_BIAS:
|
||||
return "TEX1D_BIAS($_i, $t, $0.x, $1.x)";
|
||||
return "TEX1D_BIAS($_i, $0.x, $1.x)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_PROJ:
|
||||
return "TEX1D_PROJ($_i, $t, $0.xy)";
|
||||
return "TEX1D_PROJ($_i, $0.xy)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_LOD:
|
||||
return "TEX1D_LOD($_i, $t, $0.x, $1.x)";
|
||||
return "TEX1D_LOD($_i, $0.x, $1.x)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_GRAD:
|
||||
return "TEX1D_GRAD($_i, $t, $0.x, $1.x, $2.x)";
|
||||
return "TEX1D_GRAD($_i, $0.x, $1.x, $2.x)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D:
|
||||
return "TEX2D($_i, $t, $0.xy)";
|
||||
return "TEX2D($_i, $0.xy)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_BIAS:
|
||||
return "TEX2D_BIAS($_i, $t, $0.xy, $1.x)";
|
||||
return "TEX2D_BIAS($_i, $0.xy, $1.x)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_PROJ:
|
||||
return "TEX2D_PROJ($_i, $t, $0)";
|
||||
return "TEX2D_PROJ($_i, $0)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_LOD:
|
||||
return "TEX2D_LOD($_i, $t, $0.xy, $1.x)";
|
||||
return "TEX2D_LOD($_i, $0.xy, $1.x)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_GRAD:
|
||||
return "TEX2D_GRAD($_i, $t, $0.xy, $1.xy, $2.xy)";
|
||||
return "TEX2D_GRAD($_i, $0.xy, $1.xy, $2.xy)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SHADOW2D:
|
||||
return "TEX2D_SHADOW($_i, $t, $0.xyz)";
|
||||
return "TEX2D_SHADOW($_i, $0.xyz)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SHADOW2D_PROJ:
|
||||
return "TEX2D_SHADOWPROJ($_i, $t, $0)";
|
||||
return "TEX2D_SHADOWPROJ($_i, $0)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE:
|
||||
return "TEX3D($_i, $t, $0.xyz)";
|
||||
return "TEX3D($_i, $0.xyz)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_BIAS:
|
||||
return "TEX3D_BIAS($_i, $t, $0.xyz, $1.x)";
|
||||
return "TEX3D_BIAS($_i, $0.xyz, $1.x)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_PROJ:
|
||||
return "TEX3D($_i, $t, ($0.xyz / $0.w))";
|
||||
return "TEX3D($_i, ($0.xyz / $0.w))";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_LOD:
|
||||
return "TEX3D_LOD($_i, $t, $0.xyz, $1.x)";
|
||||
return "TEX3D_LOD($_i, $0.xyz, $1.x)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_GRAD:
|
||||
return "TEX3D_GRAD($_i, $t, $0.xyz, $1.xyz, $2.xyz)";
|
||||
return "TEX3D_GRAD($_i, $0.xyz, $1.xyz, $2.xyz)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D:
|
||||
return "TEX3D($_i, $t, $0.xyz)";
|
||||
return "TEX3D($_i, $0.xyz)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_BIAS:
|
||||
return "TEX3D_BIAS($_i, $t, $0.xyz, $1.x)";
|
||||
return "TEX3D_BIAS($_i, $0.xyz, $1.x)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_PROJ:
|
||||
return "TEX3D_PROJ($_i, $t, $0)";
|
||||
return "TEX3D_PROJ($_i, $0)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_LOD:
|
||||
return "TEX3D_LOD($_i, $t, $0.xyz, $1.x)";
|
||||
return "TEX3D_LOD($_i, $0.xyz, $1.x)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_GRAD:
|
||||
return "TEX3D_GRAD($_i, $t, $0.xyz, $1.xyz, $2.xyz)";
|
||||
return "TEX3D_GRAD($_i, $0.xyz, $1.xyz, $2.xyz)";
|
||||
case FUNCTION::FUNCTION_DFDX:
|
||||
return "dFdx($0)";
|
||||
case FUNCTION::FUNCTION_DFDY:
|
||||
@ -674,7 +678,7 @@ namespace glsl
|
||||
case FUNCTION::FUNCTION_VERTEX_TEXTURE_FETCHCUBE:
|
||||
return "textureLod($t, $0.xyz, 0)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_DEPTH_RGBA:
|
||||
return "TEX2D_DEPTH_RGBA8($_i, $t, $0.xy)";
|
||||
return "TEX2D_DEPTH_RGBA8($_i, $0.xy)";
|
||||
}
|
||||
}
|
||||
}
|
@ -225,7 +225,7 @@ std::string VertexProgramDecompiler::Format(const std::string& code)
|
||||
{ "$2", std::bind(std::mem_fn(&VertexProgramDecompiler::GetSRC), this, 2) },
|
||||
{ "$s", std::bind(std::mem_fn(&VertexProgramDecompiler::GetSRC), this, 2) },
|
||||
{ "$a", std::bind(std::mem_fn(&VertexProgramDecompiler::AddAddrReg), this) },
|
||||
{ "$t", std::bind(std::mem_fn(&VertexProgramDecompiler::GetTex), this) },
|
||||
{ "$t", [this]() -> std::string { return "vtex" + std::to_string(d2.tex_num); } },
|
||||
{ "$ifcond ", [this]() -> std::string
|
||||
{
|
||||
const std::string& cond = GetCond();
|
||||
@ -582,6 +582,7 @@ std::string VertexProgramDecompiler::Decompile()
|
||||
case RSX_VEC_OPCODE_SSG: SetDSTVec("sign($0)"); break;
|
||||
case RSX_VEC_OPCODE_TXL:
|
||||
{
|
||||
GetTex();
|
||||
switch (m_prog.get_texture_dimension(d2.tex_num))
|
||||
{
|
||||
case rsx::texture_dimension_extended::texture_dimension_1d:
|
||||
|
@ -116,7 +116,12 @@ void GLFragmentDecompilerThread::insertConstants(std::stringstream & OS)
|
||||
|
||||
const auto mask = (1 << index);
|
||||
|
||||
if (m_prog.shadow_textures & mask)
|
||||
if (m_prog.redirected_textures & mask)
|
||||
{
|
||||
// Provide a stencil view of the main resource for the S channel
|
||||
OS << "uniform u" << samplerType << " " << PI.name << "_stencil;\n";
|
||||
}
|
||||
else if (m_prog.shadow_textures & mask)
|
||||
{
|
||||
if (m_shadow_sampled_textures & mask)
|
||||
{
|
||||
|
@ -401,40 +401,48 @@ void GLGSRender::end()
|
||||
//Bind textures and resolve external copy operations
|
||||
std::chrono::time_point<steady_clock> textures_start = steady_clock::now();
|
||||
void *unused = nullptr;
|
||||
gl::texture_view* tmp_view;
|
||||
|
||||
for (int i = 0; i < rsx::limits::fragment_textures_count; ++i)
|
||||
{
|
||||
if (current_fp_metadata.referenced_textures_mask & (1 << i))
|
||||
{
|
||||
auto sampler_state = static_cast<gl::texture_cache::sampled_image_descriptor*>(fs_sampler_state[i].get());
|
||||
auto &tex = rsx::method_registers.fragment_textures[i];
|
||||
_SelectTexture(GL_FRAGMENT_TEXTURES_START + i);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0 + i);
|
||||
|
||||
if (tex.enabled())
|
||||
gl::texture_view* view = nullptr;
|
||||
if (rsx::method_registers.fragment_textures[i].enabled())
|
||||
{
|
||||
if (sampler_state->image_handle)
|
||||
auto sampler_state = static_cast<gl::texture_cache::sampled_image_descriptor*>(fs_sampler_state[i].get());
|
||||
view = sampler_state->image_handle;
|
||||
|
||||
if (!view && sampler_state->external_subresource_desc.external_handle)
|
||||
{
|
||||
sampler_state->image_handle->bind();
|
||||
view = m_gl_texture_cache.create_temporary_subresource(unused, sampler_state->external_subresource_desc);
|
||||
}
|
||||
else if (sampler_state->external_subresource_desc.external_handle &&
|
||||
(tmp_view = m_gl_texture_cache.create_temporary_subresource(unused, sampler_state->external_subresource_desc)))
|
||||
}
|
||||
|
||||
if (LIKELY(view))
|
||||
{
|
||||
view->bind();
|
||||
|
||||
if (current_fragment_program.redirected_textures & (1 << i))
|
||||
{
|
||||
tmp_view->bind();
|
||||
}
|
||||
else
|
||||
{
|
||||
auto target = gl::get_target(sampler_state->image_type);
|
||||
glBindTexture(target, m_null_textures[target]->id());
|
||||
_SelectTexture(GL_STENCIL_MIRRORS_START + i);
|
||||
|
||||
auto root_texture = static_cast<gl::viewable_image*>(view->image());
|
||||
auto stencil_view = root_texture->get_view(0xAAE4, rsx::default_remap_vector, gl::image_aspect::stencil);
|
||||
stencil_view->bind();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_1D, m_null_textures[GL_TEXTURE_1D]->id());
|
||||
glBindTexture(GL_TEXTURE_2D, m_null_textures[GL_TEXTURE_2D]->id());
|
||||
glBindTexture(GL_TEXTURE_3D, m_null_textures[GL_TEXTURE_3D]->id());
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, m_null_textures[GL_TEXTURE_CUBE_MAP]->id());
|
||||
auto target = gl::get_target(current_fragment_program.get_texture_dimension(i));
|
||||
glBindTexture(target, m_null_textures[target]->id());
|
||||
|
||||
if (current_fragment_program.redirected_textures & (1 << i))
|
||||
{
|
||||
_SelectTexture(GL_STENCIL_MIRRORS_START + i);
|
||||
glBindTexture(target, m_null_textures[target]->id());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -444,7 +452,7 @@ void GLGSRender::end()
|
||||
if (current_vp_metadata.referenced_textures_mask & (1 << i))
|
||||
{
|
||||
auto sampler_state = static_cast<gl::texture_cache::sampled_image_descriptor*>(vs_sampler_state[i].get());
|
||||
glActiveTexture(GL_TEXTURE0 + rsx::limits::fragment_textures_count + i);
|
||||
_SelectTexture(GL_VERTEX_TEXTURES_START + i);
|
||||
|
||||
if (sampler_state->image_handle)
|
||||
{
|
||||
@ -773,25 +781,23 @@ void GLGSRender::on_init_thread()
|
||||
m_max_texbuffer_size = (16 * 0x100000);
|
||||
}
|
||||
|
||||
const u32 texture_index_offset = rsx::limits::fragment_textures_count + rsx::limits::vertex_textures_count;
|
||||
|
||||
//Array stream buffer
|
||||
{
|
||||
m_gl_persistent_stream_buffer = std::make_unique<gl::texture>(GL_TEXTURE_BUFFER, 0, 0, 0, 0, GL_R8UI);
|
||||
glActiveTexture(GL_TEXTURE0 + texture_index_offset);
|
||||
_SelectTexture(GL_STREAM_BUFFER_START + 0);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, m_gl_persistent_stream_buffer->id());
|
||||
}
|
||||
|
||||
//Register stream buffer
|
||||
{
|
||||
m_gl_volatile_stream_buffer = std::make_unique<gl::texture>(GL_TEXTURE_BUFFER, 0, 0, 0, 0, GL_R8UI);
|
||||
glActiveTexture(GL_TEXTURE0 + texture_index_offset + 1);
|
||||
_SelectTexture(GL_STREAM_BUFFER_START + 1);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, m_gl_volatile_stream_buffer->id());
|
||||
}
|
||||
|
||||
//Fallback null texture instead of relying on texture0
|
||||
{
|
||||
std::vector<u32> pixeldata = {0, 0, 0, 0};
|
||||
std::vector<u32> pixeldata = { 0, 0, 0, 0 };
|
||||
|
||||
//1D
|
||||
auto tex1D = std::make_unique<gl::texture>(GL_TEXTURE_1D, 1, 1, 1, 1, GL_RGBA8);
|
||||
@ -888,16 +894,24 @@ void GLGSRender::on_init_thread()
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < rsx::limits::fragment_textures_count; ++i)
|
||||
int image_unit = 0;
|
||||
for (auto &sampler : m_fs_sampler_states)
|
||||
{
|
||||
m_fs_sampler_states[i].create();
|
||||
m_fs_sampler_states[i].bind(i);
|
||||
sampler.create();
|
||||
sampler.bind(image_unit++);
|
||||
}
|
||||
|
||||
for (int i = 0; i < rsx::limits::vertex_textures_count; ++i)
|
||||
for (auto &sampler : m_fs_sampler_mirror_states)
|
||||
{
|
||||
m_vs_sampler_states[i].create();
|
||||
m_vs_sampler_states[i].bind(rsx::limits::fragment_textures_count + i);
|
||||
sampler.create();
|
||||
sampler.apply_defaults();
|
||||
sampler.bind(image_unit++);
|
||||
}
|
||||
|
||||
for (auto &sampler : m_vs_sampler_states)
|
||||
{
|
||||
sampler.create();
|
||||
sampler.bind(image_unit++);
|
||||
}
|
||||
|
||||
//Occlusion query
|
||||
@ -1037,6 +1051,11 @@ void GLGSRender::on_exit()
|
||||
sampler.remove();
|
||||
}
|
||||
|
||||
for (auto &sampler : m_fs_sampler_mirror_states)
|
||||
{
|
||||
sampler.remove();
|
||||
}
|
||||
|
||||
for (auto &sampler : m_vs_sampler_states)
|
||||
{
|
||||
sampler.remove();
|
||||
|
@ -277,8 +277,9 @@ private:
|
||||
GLFragmentProgram m_fragment_prog;
|
||||
GLVertexProgram m_vertex_prog;
|
||||
|
||||
gl::sampler_state m_fs_sampler_states[rsx::limits::fragment_textures_count];
|
||||
gl::sampler_state m_vs_sampler_states[rsx::limits::vertex_textures_count];
|
||||
gl::sampler_state m_fs_sampler_states[rsx::limits::fragment_textures_count]; // Fragment textures
|
||||
gl::sampler_state m_fs_sampler_mirror_states[rsx::limits::fragment_textures_count]; // Alternate views of fragment textures with different format (e.g Depth vs Stencil for D24S8)
|
||||
gl::sampler_state m_vs_sampler_states[rsx::limits::vertex_textures_count]; // Vertex textures
|
||||
|
||||
gl::glsl::program *m_program;
|
||||
|
||||
|
@ -13,6 +13,13 @@
|
||||
|
||||
#include "Utilities/geometry.h"
|
||||
|
||||
#define GL_FRAGMENT_TEXTURES_START 0
|
||||
#define GL_VERTEX_TEXTURES_START GL_FRAGMENT_TEXTURES_START + 16
|
||||
#define GL_STENCIL_MIRRORS_START GL_VERTEX_TEXTURES_START + 4
|
||||
#define GL_STREAM_BUFFER_START GL_STENCIL_MIRRORS_START + 16
|
||||
|
||||
inline static void _SelectTexture(int unit) { glActiveTexture(GL_TEXTURE0 + unit); }
|
||||
|
||||
namespace gl
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
@ -1609,7 +1616,7 @@ namespace gl
|
||||
m_component_layout = { GL_ALPHA, GL_RED, GL_GREEN, GL_BLUE };
|
||||
}
|
||||
|
||||
~texture()
|
||||
virtual ~texture()
|
||||
{
|
||||
glDeleteTextures(1, &m_id);
|
||||
}
|
||||
@ -1793,20 +1800,29 @@ namespace gl
|
||||
}
|
||||
};
|
||||
|
||||
enum image_aspect : u32
|
||||
{
|
||||
color = 1,
|
||||
depth = 2,
|
||||
stencil = 4
|
||||
};
|
||||
|
||||
class texture_view
|
||||
{
|
||||
GLuint m_id = 0;
|
||||
GLenum m_target = 0;
|
||||
GLenum m_format = 0;
|
||||
GLenum m_aspect_flags = 0;
|
||||
texture *m_image_data = nullptr;
|
||||
|
||||
GLenum component_swizzle[4];
|
||||
|
||||
void create(texture* data, GLenum target, GLenum sized_format, const GLenum* argb_swizzle = nullptr)
|
||||
void create(texture* data, GLenum target, GLenum sized_format, GLenum aspect_flags, const GLenum* argb_swizzle = nullptr)
|
||||
{
|
||||
m_target = target;
|
||||
m_format = sized_format;
|
||||
m_image_data = data;
|
||||
m_aspect_flags = aspect_flags;
|
||||
|
||||
const auto num_levels = data->levels();
|
||||
const auto num_layers = (target != GL_TEXTURE_CUBE_MAP) ? 1 : 6;
|
||||
@ -1831,22 +1847,34 @@ namespace gl
|
||||
component_swizzle[2] = GL_BLUE;
|
||||
component_swizzle[3] = GL_ALPHA;
|
||||
}
|
||||
|
||||
if (aspect_flags & image_aspect::stencil)
|
||||
{
|
||||
constexpr u32 depth_stencil_mask = (image_aspect::depth | image_aspect::stencil);
|
||||
verify("Invalid aspect mask combination" HERE), (aspect_flags & depth_stencil_mask) != depth_stencil_mask;
|
||||
|
||||
glBindTexture(m_target, m_id);
|
||||
glTexParameteri(m_target, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_STENCIL_INDEX);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
texture_view(const texture_view&) = delete;
|
||||
texture_view(texture_view&&) = delete;
|
||||
|
||||
texture_view(texture* data, GLenum target, GLenum sized_format, const GLenum* argb_swizzle = nullptr)
|
||||
texture_view(texture* data, GLenum target, GLenum sized_format,
|
||||
const GLenum* argb_swizzle = nullptr,
|
||||
GLenum aspect_flags = image_aspect::color | image_aspect::depth)
|
||||
{
|
||||
create(data, target, sized_format, argb_swizzle);
|
||||
create(data, target, sized_format, aspect_flags, argb_swizzle);
|
||||
}
|
||||
|
||||
texture_view(texture* data, const GLenum* argb_swizzle = nullptr)
|
||||
texture_view(texture* data, const GLenum* argb_swizzle = nullptr,
|
||||
GLenum aspect_flags = image_aspect::color | image_aspect::depth)
|
||||
{
|
||||
GLenum target = (GLenum)data->get_target();
|
||||
GLenum sized_format = (GLenum)data->get_internal_format();
|
||||
create(data, target, sized_format, argb_swizzle);
|
||||
create(data, target, sized_format, aspect_flags, argb_swizzle);
|
||||
}
|
||||
|
||||
~texture_view()
|
||||
@ -1869,6 +1897,11 @@ namespace gl
|
||||
return m_format;
|
||||
}
|
||||
|
||||
GLenum aspect() const
|
||||
{
|
||||
return m_aspect_flags;
|
||||
}
|
||||
|
||||
bool compare_swizzle(GLenum* argb_swizzle) const
|
||||
{
|
||||
return (argb_swizzle[0] == component_swizzle[3] &&
|
||||
@ -1901,23 +1934,26 @@ namespace gl
|
||||
|
||||
class viewable_image : public texture
|
||||
{
|
||||
std::unordered_map<u32, std::unique_ptr<texture_view>> views;
|
||||
std::unordered_multimap<u32, std::unique_ptr<texture_view>> views;
|
||||
|
||||
public:
|
||||
using texture::texture;
|
||||
|
||||
texture_view* get_view(u32 remap_encoding, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap)
|
||||
texture_view* get_view(u32 remap_encoding, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap, GLenum aspect_flags = image_aspect::color | image_aspect::depth)
|
||||
{
|
||||
auto found = views.find(remap_encoding);
|
||||
if (found != views.end())
|
||||
auto found = views.equal_range(remap_encoding);
|
||||
for (auto It = found.first; It != found.second; ++It)
|
||||
{
|
||||
return found->second.get();
|
||||
if (It->second->aspect() & aspect_flags)
|
||||
{
|
||||
return It->second.get();
|
||||
}
|
||||
}
|
||||
|
||||
auto mapping = apply_swizzle_remap(get_native_component_layout(), remap);
|
||||
auto view = std::make_unique<texture_view>(this, mapping.data());
|
||||
auto view = std::make_unique<texture_view>(this, mapping.data(), aspect_flags);
|
||||
auto result = view.get();
|
||||
views[remap_encoding] = std::move(view);
|
||||
views.emplace(remap_encoding, std::move(view));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
#include "GLVertexProgram.h"
|
||||
#include "GLFragmentProgram.h"
|
||||
#include "GLHelpers.h"
|
||||
#include "../Common/ProgramStateCache.h"
|
||||
|
||||
struct GLTraits
|
||||
@ -42,27 +43,36 @@ struct GLTraits
|
||||
.bind_fragment_data_location("ocol3", 3)
|
||||
.make();
|
||||
|
||||
//Progam locations are guaranteed to not change after linking
|
||||
//Texture locations are simply bound to the TIUs so this can be done once
|
||||
// Progam locations are guaranteed to not change after linking
|
||||
// Texture locations are simply bound to the TIUs so this can be done once
|
||||
for (int i = 0; i < rsx::limits::fragment_textures_count; ++i)
|
||||
{
|
||||
int location;
|
||||
if (result->uniforms.has_location(rsx::constants::fragment_texture_names[i], &location))
|
||||
result->uniforms[location] = i;
|
||||
{
|
||||
// Assign location to TIU
|
||||
result->uniforms[location] = GL_FRAGMENT_TEXTURES_START + i;
|
||||
|
||||
// Check for stencil mirror
|
||||
const std::string mirror_name = std::string(rsx::constants::fragment_texture_names[i]) + "_stencil";
|
||||
if (result->uniforms.has_location(mirror_name, &location))
|
||||
{
|
||||
// Assign mirror to TIU
|
||||
result->uniforms[location] = GL_STENCIL_MIRRORS_START + i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < rsx::limits::vertex_textures_count; ++i)
|
||||
{
|
||||
int location;
|
||||
if (result->uniforms.has_location(rsx::constants::vertex_texture_names[i], &location))
|
||||
result->uniforms[location] = (i + rsx::limits::fragment_textures_count);
|
||||
result->uniforms[location] = GL_VERTEX_TEXTURES_START + i;
|
||||
}
|
||||
|
||||
const int stream_buffer_start = rsx::limits::fragment_textures_count + rsx::limits::vertex_textures_count;
|
||||
|
||||
//Bind locations 0 and 1 to the stream buffers
|
||||
result->uniforms[0] = stream_buffer_start;
|
||||
result->uniforms[1] = stream_buffer_start + 1;
|
||||
// Bind locations 0 and 1 to the stream buffers
|
||||
result->uniforms[0] = GL_STREAM_BUFFER_START + 0;
|
||||
result->uniforms[1] = GL_STREAM_BUFFER_START + 1;
|
||||
|
||||
LOG_NOTICE(RSX, "*** prog id = %d", result->id());
|
||||
LOG_NOTICE(RSX, "*** vp id = %d", vertexProgramData.id);
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "stdafx.h"
|
||||
#include "stdafx.h"
|
||||
#include "GLTexture.h"
|
||||
#include "../GCM.h"
|
||||
#include "../RSXThread.h"
|
||||
@ -290,6 +290,19 @@ namespace gl
|
||||
glSamplerParameteri(samplerHandle, GL_TEXTURE_COMPARE_MODE, GL_NONE);
|
||||
}
|
||||
|
||||
void sampler_state::apply_defaults()
|
||||
{
|
||||
glSamplerParameteri(samplerHandle, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glSamplerParameteri(samplerHandle, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glSamplerParameteri(samplerHandle, GL_TEXTURE_WRAP_R, GL_REPEAT);
|
||||
glSamplerParameteri(samplerHandle, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glSamplerParameteri(samplerHandle, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glSamplerParameterf(samplerHandle, GL_TEXTURE_LOD_BIAS, 0.f);
|
||||
glSamplerParameteri(samplerHandle, GL_TEXTURE_MIN_LOD, 0);
|
||||
glSamplerParameteri(samplerHandle, GL_TEXTURE_MAX_LOD, 0);
|
||||
glSamplerParameteri(samplerHandle, GL_TEXTURE_COMPARE_MODE, GL_NONE);
|
||||
}
|
||||
|
||||
bool is_compressed_format(u32 texture_format)
|
||||
{
|
||||
switch (texture_format)
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "OpenGL.h"
|
||||
#include "OpenGL.h"
|
||||
#include "../GCM.h"
|
||||
#include "../Common/TextureUtils.h"
|
||||
#include "GLHelpers.h"
|
||||
@ -56,5 +56,7 @@ namespace gl
|
||||
|
||||
void apply(const rsx::fragment_texture& tex, const rsx::sampled_image_descriptor_base* sampled_image);
|
||||
void apply(const rsx::vertex_texture& tex, const rsx::sampled_image_descriptor_base* sampled_image);
|
||||
|
||||
void apply_defaults();
|
||||
};
|
||||
}
|
||||
|
@ -758,7 +758,7 @@ namespace gl
|
||||
}
|
||||
}
|
||||
|
||||
auto dst = std::make_unique<gl::texture>(dst_type, width, height, 1, 1, sized_internal_fmt);
|
||||
std::unique_ptr<gl::texture> dst = std::make_unique<gl::viewable_image>(dst_type, width, height, 1, 1, sized_internal_fmt);
|
||||
|
||||
if (copy)
|
||||
{
|
||||
@ -855,7 +855,7 @@ namespace gl
|
||||
gl::texture_view* generate_cubemap_from_images(void*&, u32 gcm_format, u16 size, const std::vector<copy_region_descriptor>& sources, const texture_channel_remap_t& /*remap_vector*/) override
|
||||
{
|
||||
const GLenum ifmt = gl::get_sized_internal_format(gcm_format);
|
||||
auto dst_image = std::make_unique<gl::texture>(GL_TEXTURE_CUBE_MAP, size, size, 1, 1, ifmt);
|
||||
std::unique_ptr<gl::texture> dst_image = std::make_unique<gl::viewable_image>(GL_TEXTURE_CUBE_MAP, size, size, 1, 1, ifmt);
|
||||
auto view = std::make_unique<gl::texture_view>(dst_image.get(), GL_TEXTURE_CUBE_MAP, ifmt);
|
||||
|
||||
//Empty GL_ERROR
|
||||
@ -884,7 +884,7 @@ namespace gl
|
||||
gl::texture_view* generate_3d_from_2d_images(void*&, u32 gcm_format, u16 width, u16 height, u16 depth, const std::vector<copy_region_descriptor>& sources, const texture_channel_remap_t& /*remap_vector*/) override
|
||||
{
|
||||
const GLenum ifmt = gl::get_sized_internal_format(gcm_format);
|
||||
auto dst_image = std::make_unique<gl::texture>(GL_TEXTURE_3D, width, height, depth, 1, ifmt);
|
||||
std::unique_ptr<gl::texture> dst_image = std::make_unique<gl::viewable_image>(GL_TEXTURE_3D, width, height, depth, 1, ifmt);
|
||||
auto view = std::make_unique<gl::texture_view>(dst_image.get(), GL_TEXTURE_3D, ifmt);
|
||||
|
||||
//Empty GL_ERROR
|
||||
|
@ -141,9 +141,24 @@ void VKFragmentDecompilerThread::insertConstants(std::stringstream & OS)
|
||||
inputs.push_back(in);
|
||||
|
||||
OS << "layout(set=0, binding=" << location++ << ") uniform " << samplerType << " " << PI.name << ";\n";
|
||||
|
||||
if (m_prog.redirected_textures & mask)
|
||||
{
|
||||
// Insert stencil mirror declaration
|
||||
in.name += "_stencil";
|
||||
in.location = location;
|
||||
|
||||
inputs.push_back(in);
|
||||
|
||||
OS << "layout(set=0, binding=" << location++ << ") uniform u" << PT.type << " " << in.name << ";\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Some drivers (macOS) do not support more than 16 texture descriptors per stage
|
||||
// TODO: If any application requires more than this, the layout can be restructured a bit
|
||||
verify("Too many sampler descriptors!" HERE), location <= VERTEX_TEXTURES_FIRST_BIND_SLOT;
|
||||
|
||||
std::string constants_block;
|
||||
for (const ParamType& PT : m_parr.params[PF_PARAM_UNIFORM])
|
||||
{
|
||||
|
@ -805,6 +805,8 @@ VKGSRender::~VKGSRender()
|
||||
for (auto& handle : vs_sampler_handles)
|
||||
handle.reset();
|
||||
|
||||
m_stencil_mirror_sampler.reset();
|
||||
|
||||
//Overlay text handler
|
||||
m_text_writer.reset();
|
||||
|
||||
@ -1585,29 +1587,66 @@ void VKGSRender::end()
|
||||
{
|
||||
if (current_fp_metadata.referenced_textures_mask & (1 << i))
|
||||
{
|
||||
if (!rsx::method_registers.fragment_textures[i].enabled())
|
||||
vk::image_view* view = nullptr;
|
||||
if (rsx::method_registers.fragment_textures[i].enabled())
|
||||
{
|
||||
m_program->bind_uniform({ vk::null_sampler(), vk::null_image_view(*m_current_command_buffer), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, rsx::constants::fragment_texture_names[i], m_current_frame->descriptor_set);
|
||||
continue;
|
||||
auto sampler_state = static_cast<vk::texture_cache::sampled_image_descriptor*>(fs_sampler_state[i].get());
|
||||
view = sampler_state->image_handle;
|
||||
|
||||
if (!view && sampler_state->external_subresource_desc.external_handle)
|
||||
{
|
||||
//Requires update, copy subresource
|
||||
view = m_texture_cache.create_temporary_subresource(*m_current_command_buffer, sampler_state->external_subresource_desc);
|
||||
}
|
||||
}
|
||||
|
||||
auto sampler_state = static_cast<vk::texture_cache::sampled_image_descriptor*>(fs_sampler_state[i].get());
|
||||
auto image_ptr = sampler_state->image_handle;
|
||||
|
||||
if (!image_ptr && sampler_state->external_subresource_desc.external_handle)
|
||||
if (LIKELY(view))
|
||||
{
|
||||
//Requires update, copy subresource
|
||||
image_ptr = m_texture_cache.create_temporary_subresource(*m_current_command_buffer, sampler_state->external_subresource_desc);
|
||||
}
|
||||
m_program->bind_uniform({ fs_sampler_handles[i]->value, view->value, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL },
|
||||
i,
|
||||
::glsl::program_domain::glsl_fragment_program,
|
||||
m_current_frame->descriptor_set);
|
||||
|
||||
if (!image_ptr)
|
||||
if (current_fragment_program.redirected_textures & (1 << i))
|
||||
{
|
||||
// Stencil mirror required
|
||||
auto root_image = static_cast<vk::viewable_image*>(view->image());
|
||||
auto stencil_view = root_image->get_view(0xAAE4, rsx::default_remap_vector, VK_IMAGE_ASPECT_STENCIL_BIT);
|
||||
|
||||
if (!m_stencil_mirror_sampler)
|
||||
{
|
||||
m_stencil_mirror_sampler = std::make_unique<vk::sampler>(*m_device,
|
||||
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
|
||||
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
|
||||
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
|
||||
VK_FALSE, 0.f, 1.f, 0.f, 0.f,
|
||||
VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST,
|
||||
VK_BORDER_COLOR_INT_OPAQUE_BLACK);
|
||||
}
|
||||
|
||||
m_program->bind_uniform({ m_stencil_mirror_sampler->value, stencil_view->value, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL },
|
||||
i,
|
||||
::glsl::program_domain::glsl_fragment_program,
|
||||
m_current_frame->descriptor_set,
|
||||
true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR(RSX, "Texture upload failed to texture index %d. Binding null sampler.", i);
|
||||
m_program->bind_uniform({ vk::null_sampler(), vk::null_image_view(*m_current_command_buffer), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, rsx::constants::fragment_texture_names[i], m_current_frame->descriptor_set);
|
||||
continue;
|
||||
}
|
||||
m_program->bind_uniform({ vk::null_sampler(), vk::null_image_view(*m_current_command_buffer), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL },
|
||||
i,
|
||||
::glsl::program_domain::glsl_fragment_program,
|
||||
m_current_frame->descriptor_set);
|
||||
|
||||
m_program->bind_uniform({ fs_sampler_handles[i]->value, image_ptr->value, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, rsx::constants::fragment_texture_names[i], m_current_frame->descriptor_set);
|
||||
if (current_fragment_program.redirected_textures & (1 << i))
|
||||
{
|
||||
m_program->bind_uniform({ vk::null_sampler(), vk::null_image_view(*m_current_command_buffer), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL },
|
||||
i,
|
||||
::glsl::program_domain::glsl_fragment_program,
|
||||
m_current_frame->descriptor_set,
|
||||
true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1617,7 +1656,11 @@ void VKGSRender::end()
|
||||
{
|
||||
if (!rsx::method_registers.vertex_textures[i].enabled())
|
||||
{
|
||||
m_program->bind_uniform({ vk::null_sampler(), vk::null_image_view(*m_current_command_buffer), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, rsx::constants::vertex_texture_names[i], m_current_frame->descriptor_set);
|
||||
m_program->bind_uniform({ vk::null_sampler(), vk::null_image_view(*m_current_command_buffer), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL },
|
||||
i,
|
||||
::glsl::program_domain::glsl_vertex_program,
|
||||
m_current_frame->descriptor_set);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1637,7 +1680,10 @@ void VKGSRender::end()
|
||||
continue;
|
||||
}
|
||||
|
||||
m_program->bind_uniform({ vs_sampler_handles[i]->value, image_ptr->value, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, rsx::constants::vertex_texture_names[i], m_current_frame->descriptor_set);
|
||||
m_program->bind_uniform({ vs_sampler_handles[i]->value, image_ptr->value, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL },
|
||||
i,
|
||||
::glsl::program_domain::glsl_vertex_program,
|
||||
m_current_frame->descriptor_set);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -291,6 +291,7 @@ private:
|
||||
shared_mutex m_sampler_mutex;
|
||||
u64 surface_store_tag = 0;
|
||||
std::atomic_bool m_samplers_dirty = { true };
|
||||
std::unique_ptr<vk::sampler> m_stencil_mirror_sampler;
|
||||
std::array<std::unique_ptr<rsx::sampled_image_descriptor_base>, rsx::limits::fragment_textures_count> fs_sampler_state = {};
|
||||
std::array<std::unique_ptr<rsx::sampled_image_descriptor_base>, rsx::limits::vertex_textures_count> vs_sampler_state = {};
|
||||
std::array<std::unique_ptr<vk::sampler>, rsx::limits::fragment_textures_count> fs_sampler_handles;
|
||||
|
@ -692,7 +692,7 @@ namespace vk
|
||||
|
||||
// TODO: Ctor that uses a provided memory heap
|
||||
|
||||
~image()
|
||||
virtual ~image()
|
||||
{
|
||||
vkDestroyImage(m_device, value, nullptr);
|
||||
}
|
||||
@ -746,7 +746,7 @@ namespace vk
|
||||
image_view(VkDevice dev, vk::image* resource,
|
||||
const VkComponentMapping mapping = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A },
|
||||
const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1})
|
||||
: m_device(dev)
|
||||
: m_device(dev), m_resource(resource)
|
||||
{
|
||||
info.format = resource->info.format;
|
||||
info.image = resource->value;
|
||||
@ -792,11 +792,17 @@ namespace vk
|
||||
#endif
|
||||
}
|
||||
|
||||
vk::image* image() const
|
||||
{
|
||||
return m_resource;
|
||||
}
|
||||
|
||||
image_view(const image_view&) = delete;
|
||||
image_view(image_view&&) = delete;
|
||||
|
||||
private:
|
||||
VkDevice m_device;
|
||||
vk::image* m_resource = nullptr;
|
||||
|
||||
void create_impl()
|
||||
{
|
||||
@ -2844,6 +2850,11 @@ public:
|
||||
std::array<std::vector<program_input>, input_type_max_enum> uniforms;
|
||||
VkDevice m_device;
|
||||
|
||||
std::array<u32, 16> fs_texture_bindings;
|
||||
std::array<u32, 16> fs_texture_mirror_bindings;
|
||||
std::array<u32, 4> vs_texture_bindings;
|
||||
bool linked;
|
||||
|
||||
public:
|
||||
VkPipeline pipeline;
|
||||
u64 attribute_location_mask;
|
||||
@ -2855,9 +2866,11 @@ public:
|
||||
~program();
|
||||
|
||||
program& load_uniforms(::glsl::program_domain domain, const std::vector<program_input>& inputs);
|
||||
program& link();
|
||||
|
||||
bool has_uniform(program_input_type type, const std::string &uniform_name);
|
||||
void bind_uniform(const VkDescriptorImageInfo &image_descriptor, const std::string &uniform_name, VkDescriptorSet &descriptor_set);
|
||||
void bind_uniform(const VkDescriptorImageInfo &image_descriptor, int texture_unit, ::glsl::program_domain domain, VkDescriptorSet &descriptor_set, bool is_stencil_mirror = false);
|
||||
void bind_uniform(const VkDescriptorBufferInfo &buffer_descriptor, uint32_t binding_point, VkDescriptorSet &descriptor_set);
|
||||
void bind_uniform(const VkBufferView &buffer_view, program_input_type type, const std::string &binding_name, VkDescriptorSet &descriptor_set);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
#include "VKVertexProgram.h"
|
||||
#include "VKFragmentProgram.h"
|
||||
#include "../Common/ProgramStateCache.h"
|
||||
@ -165,8 +165,9 @@ struct VKTraits
|
||||
info.renderPass = pipelineProperties.render_pass;
|
||||
|
||||
CHECK_RESULT(vkCreateGraphicsPipelines(dev, nullptr, 1, &info, NULL, &pipeline));
|
||||
pipeline_storage_type result = std::make_unique<vk::glsl::program>(dev, pipeline, vertexProgramData.uniforms, fragmentProgramData.uniforms);
|
||||
|
||||
pipeline_storage_type result = std::make_unique<vk::glsl::program>(dev, pipeline, vertexProgramData.uniforms, fragmentProgramData.uniforms);
|
||||
result->link();
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
@ -1,6 +1,8 @@
|
||||
#include "stdafx.h"
|
||||
#include "VKHelpers.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace vk
|
||||
{
|
||||
namespace glsl
|
||||
@ -10,10 +12,16 @@ namespace vk
|
||||
program::program(VkDevice dev, VkPipeline p, const std::vector<program_input> &vertex_input, const std::vector<program_input>& fragment_inputs)
|
||||
: m_device(dev), pipeline(p)
|
||||
{
|
||||
linked = false;
|
||||
|
||||
load_uniforms(program_domain::glsl_vertex_program, vertex_input);
|
||||
load_uniforms(program_domain::glsl_vertex_program, fragment_inputs);
|
||||
attribute_location_mask = 0;
|
||||
vertex_attributes_mask = 0;
|
||||
|
||||
fs_texture_bindings.fill(~0u);
|
||||
fs_texture_mirror_bindings.fill(~0u);
|
||||
vs_texture_bindings.fill(~0u);
|
||||
}
|
||||
|
||||
program::~program()
|
||||
@ -23,6 +31,8 @@ namespace vk
|
||||
|
||||
program& program::load_uniforms(program_domain domain, const std::vector<program_input>& inputs)
|
||||
{
|
||||
verify("Cannot change uniforms in already linked program!" HERE), !linked;
|
||||
|
||||
for (auto &item : inputs)
|
||||
{
|
||||
uniforms[item.type].push_back(item);
|
||||
@ -31,6 +41,46 @@ namespace vk
|
||||
return *this;
|
||||
}
|
||||
|
||||
program& program::link()
|
||||
{
|
||||
// Preprocess texture bindings
|
||||
// Link step is only useful for rasterizer programs, compute programs do not need this
|
||||
for (const auto &uniform : uniforms[program_input_type::input_type_texture])
|
||||
{
|
||||
if (const auto name_start = uniform.name.find("tex"); name_start != std::string::npos)
|
||||
{
|
||||
const auto name_end = uniform.name.find("_stencil");
|
||||
const auto index_start = name_start + 3; // Skip 'tex' part
|
||||
const auto index_length = (name_end != std::string::npos) ? name_end - index_start : name_end;
|
||||
const auto index_part = uniform.name.substr(index_start, index_length);
|
||||
const auto index = std::stoi(index_part);
|
||||
|
||||
if (name_start == 0)
|
||||
{
|
||||
// Fragment texture (tex...)
|
||||
if (name_end == std::string::npos)
|
||||
{
|
||||
// Normal texture
|
||||
fs_texture_bindings[index] = uniform.location;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Stencil mirror
|
||||
fs_texture_mirror_bindings[index] = uniform.location;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Vertex texture (vtex...)
|
||||
vs_texture_bindings[index] = uniform.location;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
linked = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool program::has_uniform(program_input_type type, const std::string &uniform_name)
|
||||
{
|
||||
for (const auto &uniform : uniforms[type])
|
||||
@ -71,6 +121,44 @@ namespace vk
|
||||
LOG_NOTICE(RSX, "texture not found in program: %s", uniform_name.c_str());
|
||||
}
|
||||
|
||||
void program::bind_uniform(const VkDescriptorImageInfo & image_descriptor, int texture_unit, ::glsl::program_domain domain, VkDescriptorSet &descriptor_set, bool is_stencil_mirror)
|
||||
{
|
||||
verify("Unsupported program domain" HERE, domain != ::glsl::program_domain::glsl_compute_program);
|
||||
|
||||
u32 binding;
|
||||
if (domain == ::glsl::program_domain::glsl_fragment_program)
|
||||
{
|
||||
binding = (is_stencil_mirror) ? fs_texture_mirror_bindings[texture_unit] : fs_texture_bindings[texture_unit];
|
||||
}
|
||||
else
|
||||
{
|
||||
binding = vs_texture_bindings[texture_unit];
|
||||
}
|
||||
|
||||
if (binding != ~0u)
|
||||
{
|
||||
const VkWriteDescriptorSet descriptor_writer =
|
||||
{
|
||||
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // sType
|
||||
nullptr, // pNext
|
||||
descriptor_set, // dstSet
|
||||
binding, // dstBinding
|
||||
0, // dstArrayElement
|
||||
1, // descriptorCount
|
||||
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, // descriptorType
|
||||
&image_descriptor, // pImageInfo
|
||||
nullptr, // pBufferInfo
|
||||
nullptr // pTexelBufferView
|
||||
};
|
||||
|
||||
vkUpdateDescriptorSets(m_device, 1, &descriptor_writer, 0, nullptr);
|
||||
attribute_location_mask |= (1ull << binding);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_NOTICE(RSX, "texture not found in program: %stex%u", (domain == ::glsl::program_domain::glsl_vertex_program)? "v" : "", texture_unit);
|
||||
}
|
||||
|
||||
void program::bind_uniform(const VkDescriptorBufferInfo &buffer_descriptor, uint32_t binding_point, VkDescriptorSet &descriptor_set)
|
||||
{
|
||||
bind_buffer(buffer_descriptor, binding_point, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, descriptor_set);
|
||||
|
@ -1,4 +1,4 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "VKHelpers.h"
|
||||
@ -21,24 +21,9 @@ namespace vk
|
||||
VkImageAspectFlags attachment_aspect_flag = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
std::unordered_multimap<u32, std::unique_ptr<vk::image_view>> views;
|
||||
|
||||
u64 frame_tag = 0; //frame id when invalidated, 0 if not invalid
|
||||
u64 frame_tag = 0; // frame id when invalidated, 0 if not invalid
|
||||
|
||||
render_target(vk::render_device &dev,
|
||||
uint32_t memory_type_index,
|
||||
uint32_t access_flags,
|
||||
VkImageType image_type,
|
||||
VkFormat format,
|
||||
uint32_t width, uint32_t height, uint32_t depth,
|
||||
uint32_t mipmaps, uint32_t layers,
|
||||
VkSampleCountFlagBits samples,
|
||||
VkImageLayout initial_layout,
|
||||
VkImageTiling tiling,
|
||||
VkImageUsageFlags usage,
|
||||
VkImageCreateFlags image_flags)
|
||||
|
||||
: viewable_image(dev, memory_type_index, access_flags, image_type, format, width, height, depth,
|
||||
mipmaps, layers, samples, initial_layout, tiling, usage, image_flags)
|
||||
{}
|
||||
using viewable_image::viewable_image;
|
||||
|
||||
vk::image* get_surface() override
|
||||
{
|
||||
|
@ -516,7 +516,7 @@ namespace vk
|
||||
image_flags = (view_type == VK_IMAGE_VIEW_TYPE_CUBE)? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0;
|
||||
}
|
||||
|
||||
image.reset(new vk::image(*vk::get_current_renderer(), m_memory_types.device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
image.reset(new vk::viewable_image(*vk::get_current_renderer(), m_memory_types.device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
image_type,
|
||||
dst_format,
|
||||
w, h, 1, 1, 1, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
@ -543,7 +543,7 @@ namespace vk
|
||||
view_swizzle = vk::apply_swizzle_remap({view_swizzle.a, view_swizzle.r, view_swizzle.g, view_swizzle.b}, remap_vector);
|
||||
|
||||
VkImageSubresourceRange view_range = { aspect & ~(VK_IMAGE_ASPECT_STENCIL_BIT), 0, 1, 0, 1 };
|
||||
view.reset(new vk::image_view(*vk::get_current_renderer(), image->value, view_type, dst_format, view_swizzle, view_range));
|
||||
view.reset(new vk::image_view(*vk::get_current_renderer(), image.get(), view_swizzle, view_range));
|
||||
|
||||
if (copy)
|
||||
{
|
||||
@ -595,14 +595,14 @@ namespace vk
|
||||
VkFormat dst_format = vk::get_compatible_sampler_format(m_formats_support, gcm_format);
|
||||
VkImageAspectFlags dst_aspect = vk::get_aspect_flags(dst_format);
|
||||
|
||||
image.reset(new vk::image(*vk::get_current_renderer(), m_memory_types.device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
image.reset(new vk::viewable_image(*vk::get_current_renderer(), m_memory_types.device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
VK_IMAGE_TYPE_2D,
|
||||
dst_format,
|
||||
size, size, 1, 1, 6, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT));
|
||||
|
||||
VkImageSubresourceRange view_range = { dst_aspect & ~(VK_IMAGE_ASPECT_STENCIL_BIT), 0, 1, 0, 6 };
|
||||
view.reset(new vk::image_view(*vk::get_current_renderer(), image->value, VK_IMAGE_VIEW_TYPE_CUBE, image->info.format, image->native_component_map, view_range));
|
||||
view.reset(new vk::image_view(*vk::get_current_renderer(), image.get(), image->native_component_map, view_range));
|
||||
|
||||
VkImageSubresourceRange dst_range = { dst_aspect, 0, 1, 0, 6 };
|
||||
vk::change_image_layout(cmd, image.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, dst_range);
|
||||
@ -658,14 +658,14 @@ namespace vk
|
||||
VkFormat dst_format = vk::get_compatible_sampler_format(m_formats_support, gcm_format);
|
||||
VkImageAspectFlags dst_aspect = vk::get_aspect_flags(dst_format);
|
||||
|
||||
image.reset(new vk::image(*vk::get_current_renderer(), m_memory_types.device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
image.reset(new vk::viewable_image(*vk::get_current_renderer(), m_memory_types.device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
VK_IMAGE_TYPE_3D,
|
||||
dst_format,
|
||||
width, height, depth, 1, 1, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, 0));
|
||||
|
||||
VkImageSubresourceRange view_range = { dst_aspect & ~(VK_IMAGE_ASPECT_STENCIL_BIT), 0, 1, 0, 1 };
|
||||
view.reset(new vk::image_view(*vk::get_current_renderer(), image->value, VK_IMAGE_VIEW_TYPE_3D, image->info.format, image->native_component_map, view_range));
|
||||
view.reset(new vk::image_view(*vk::get_current_renderer(), image.get(), image->native_component_map, view_range));
|
||||
|
||||
VkImageSubresourceRange dst_range = { dst_aspect, 0, 1, 0, 1 };
|
||||
vk::change_image_layout(cmd, image.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, dst_range);
|
||||
|
Loading…
x
Reference in New Issue
Block a user