diff options
Diffstat (limited to 'src/video_core')
28 files changed, 623 insertions, 768 deletions
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 45d8eaf23..6f3f2aa9f 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt @@ -127,6 +127,8 @@ add_library(video_core STATIC shader/track.cpp surface.cpp surface.h + texture_cache/format_lookup_table.cpp + texture_cache/format_lookup_table.h texture_cache/surface_base.cpp texture_cache/surface_base.h texture_cache/surface_params.cpp diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 4408b5001..0510ed777 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -427,8 +427,8 @@ private: VideoCore::RasterizerInterface& rasterizer; Core::System& system; - std::unique_ptr<StreamBuffer> stream_buffer; + std::unique_ptr<StreamBuffer> stream_buffer; TBufferType stream_buffer_handle{}; bool invalidated = false; @@ -440,18 +440,18 @@ private: using IntervalSet = boost::icl::interval_set<CacheAddr>; using IntervalCache = boost::icl::interval_map<CacheAddr, MapInterval>; using IntervalType = typename IntervalCache::interval_type; - IntervalCache mapped_addresses{}; + IntervalCache mapped_addresses; - static constexpr u64 write_page_bit{11}; - std::unordered_map<u64, u32> written_pages{}; + static constexpr u64 write_page_bit = 11; + std::unordered_map<u64, u32> written_pages; - static constexpr u64 block_page_bits{21}; - static constexpr u64 block_page_size{1 << block_page_bits}; - std::unordered_map<u64, TBuffer> blocks{}; + static constexpr u64 block_page_bits = 21; + static constexpr u64 block_page_size = 1ULL << block_page_bits; + std::unordered_map<u64, TBuffer> blocks; - std::list<TBuffer> pending_destruction{}; - u64 epoch{}; - u64 modified_ticks{}; + std::list<TBuffer> pending_destruction; + u64 epoch = 0; + u64 modified_ticks = 0; std::recursive_mutex mutex; }; diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 42ce49a4d..a44c09003 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp @@ -742,14 +742,6 @@ Texture::TICEntry Maxwell3D::GetTICEntry(u32 tic_index) const { Texture::TICEntry tic_entry; memory_manager.ReadBlockUnsafe(tic_address_gpu, &tic_entry, sizeof(Texture::TICEntry)); - [[maybe_unused]] const auto r_type{tic_entry.r_type.Value()}; - [[maybe_unused]] const auto g_type{tic_entry.g_type.Value()}; - [[maybe_unused]] const auto b_type{tic_entry.b_type.Value()}; - [[maybe_unused]] const auto a_type{tic_entry.a_type.Value()}; - - // TODO(Subv): Different data types for separate components are not supported - DEBUG_ASSERT(r_type == g_type && r_type == b_type && r_type == a_type); - return tic_entry; } diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index 78d6886fb..9fafed4a2 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h @@ -616,6 +616,14 @@ union Instruction { } shfl; union { + BitField<44, 1, u64> ftz; + BitField<39, 2, u64> tab5cb8_2; + BitField<38, 1, u64> ndv; + BitField<47, 1, u64> cc; + BitField<28, 8, u64> swizzle; + } fswzadd; + + union { BitField<8, 8, Register> gpr; BitField<20, 24, s64> offset; } gmem; @@ -1592,6 +1600,7 @@ public: DEPBAR, VOTE, SHFL, + FSWZADD, BFE_C, BFE_R, BFE_IMM, @@ -1890,6 +1899,7 @@ private: INST("1111000011110---", Id::DEPBAR, Type::Synch, "DEPBAR"), INST("0101000011011---", Id::VOTE, Type::Warp, "VOTE"), INST("1110111100010---", Id::SHFL, Type::Warp, "SHFL"), + INST("0101000011111---", Id::FSWZADD, Type::Warp, "FSWZADD"), INST("1110111111011---", Id::LD_A, Type::Memory, "LD_A"), INST("1110111101001---", Id::LD_S, Type::Memory, "LD_S"), INST("1110111101000---", Id::LD_L, Type::Memory, "LD_L"), diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp index c65b24c69..b30d5be74 100644 --- a/src/video_core/renderer_opengl/gl_device.cpp +++ b/src/video_core/renderer_opengl/gl_device.cpp @@ -62,6 +62,7 @@ Device::Device() { max_varyings = GetInteger<u32>(GL_MAX_VARYING_VECTORS); has_warp_intrinsics = GLAD_GL_NV_gpu_shader5 && GLAD_GL_NV_shader_thread_group && GLAD_GL_NV_shader_thread_shuffle; + has_shader_ballot = GLAD_GL_ARB_shader_ballot; has_vertex_viewport_layer = GLAD_GL_ARB_shader_viewport_layer_array; has_image_load_formatted = HasExtension(extensions, "GL_EXT_shader_image_load_formatted"); has_variable_aoffi = TestVariableAoffi(); @@ -79,6 +80,7 @@ Device::Device(std::nullptr_t) { max_vertex_attributes = 16; max_varyings = 15; has_warp_intrinsics = true; + has_shader_ballot = true; has_vertex_viewport_layer = true; has_image_load_formatted = true; has_variable_aoffi = true; diff --git a/src/video_core/renderer_opengl/gl_device.h b/src/video_core/renderer_opengl/gl_device.h index bf35bd0b6..6c86fe207 100644 --- a/src/video_core/renderer_opengl/gl_device.h +++ b/src/video_core/renderer_opengl/gl_device.h @@ -34,6 +34,10 @@ public: return has_warp_intrinsics; } + bool HasShaderBallot() const { + return has_shader_ballot; + } + bool HasVertexViewportLayer() const { return has_vertex_viewport_layer; } @@ -68,6 +72,7 @@ private: u32 max_vertex_attributes{}; u32 max_varyings{}; bool has_warp_intrinsics{}; + bool has_shader_ballot{}; bool has_vertex_viewport_layer{}; bool has_image_load_formatted{}; bool has_variable_aoffi{}; diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index e43ba9d6b..05f8e511b 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -257,10 +257,8 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) { continue; } - const std::size_t stage{index == 0 ? 0 : index - 1}; // Stage indices are 0 - 5 - GLShader::MaxwellUniformData ubo{}; - ubo.SetFromRegs(gpu, stage); + ubo.SetFromRegs(gpu); const auto [buffer, offset] = buffer_cache.UploadHostMemory(&ubo, sizeof(ubo), device.GetUniformBufferAlignment()); @@ -269,10 +267,11 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) { Shader shader{shader_cache.GetStageProgram(program)}; - const auto stage_enum = static_cast<Maxwell::ShaderStage>(stage); - SetupDrawConstBuffers(stage_enum, shader); - SetupDrawGlobalMemory(stage_enum, shader); - const auto texture_buffer_usage{SetupDrawTextures(stage_enum, shader, base_bindings)}; + // Stage indices are 0 - 5 + const auto stage = static_cast<Maxwell::ShaderStage>(index == 0 ? 0 : index - 1); + SetupDrawConstBuffers(stage, shader); + SetupDrawGlobalMemory(stage, shader); + const auto texture_buffer_usage{SetupDrawTextures(stage, shader, base_bindings)}; const ProgramVariant variant{base_bindings, primitive_mode, texture_buffer_usage}; const auto [program_handle, next_bindings] = shader->GetProgramHandle(variant); @@ -1055,6 +1054,15 @@ void RasterizerOpenGL::SyncViewport(OpenGLState& current_state) { } state.depth_clamp.far_plane = regs.view_volume_clip_control.depth_clamp_far != 0; state.depth_clamp.near_plane = regs.view_volume_clip_control.depth_clamp_near != 0; + + bool flip_y = false; + if (regs.viewport_transform[0].scale_y < 0.0) { + flip_y = !flip_y; + } + if (regs.screen_y_control.y_negate != 0) { + flip_y = !flip_y; + } + state.clip_control.origin = flip_y ? GL_UPPER_LEFT : GL_LOWER_LEFT; } void RasterizerOpenGL::SyncClipEnabled( @@ -1077,28 +1085,14 @@ void RasterizerOpenGL::SyncClipCoef() { } void RasterizerOpenGL::SyncCullMode() { - auto& maxwell3d = system.GPU().Maxwell3D(); - - const auto& regs = maxwell3d.regs; + const auto& regs = system.GPU().Maxwell3D().regs; state.cull.enabled = regs.cull.enabled != 0; if (state.cull.enabled) { - state.cull.front_face = MaxwellToGL::FrontFace(regs.cull.front_face); state.cull.mode = MaxwellToGL::CullFace(regs.cull.cull_face); - - const bool flip_triangles{regs.screen_y_control.triangle_rast_flip == 0 || - regs.viewport_transform[0].scale_y < 0.0f}; - - // If the GPU is configured to flip the rasterized triangles, then we need to flip the - // notion of front and back. Note: We flip the triangles when the value of the register is 0 - // because OpenGL already does it for us. - if (flip_triangles) { - if (state.cull.front_face == GL_CCW) - state.cull.front_face = GL_CW; - else if (state.cull.front_face == GL_CW) - state.cull.front_face = GL_CCW; - } } + + state.cull.front_face = MaxwellToGL::FrontFace(regs.cull.front_face); } void RasterizerOpenGL::SyncPrimitiveRestart() { diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 35e5214a5..04a239a39 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp @@ -275,16 +275,25 @@ CachedProgram BuildShader(const Device& device, u64 unique_identifier, ProgramTy std::string source = fmt::format(R"(// {} #version 430 core #extension GL_ARB_separate_shader_objects : enable -#extension GL_ARB_shader_viewport_layer_array : enable -#extension GL_EXT_shader_image_load_formatted : enable -#extension GL_NV_gpu_shader5 : enable -#extension GL_NV_shader_thread_group : enable -#extension GL_NV_shader_thread_shuffle : enable )", GetShaderId(unique_identifier, program_type)); if (is_compute) { source += "#extension GL_ARB_compute_variable_group_size : require\n"; } + if (device.HasShaderBallot()) { + source += "#extension GL_ARB_shader_ballot : require\n"; + } + if (device.HasVertexViewportLayer()) { + source += "#extension GL_ARB_shader_viewport_layer_array : require\n"; + } + if (device.HasImageLoadFormatted()) { + source += "#extension GL_EXT_shader_image_load_formatted : require\n"; + } + if (device.HasWarpIntrinsics()) { + source += "#extension GL_NV_gpu_shader5 : require\n" + "#extension GL_NV_shader_thread_group : require\n" + "#extension GL_NV_shader_thread_shuffle : require\n"; + } source += '\n'; if (!is_compute) { diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 0ce59a852..4f2b49170 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -1379,6 +1379,26 @@ private: return GenerateUnary(operation, "float", Type::Float, type); } + Expression FSwizzleAdd(Operation operation) { + const std::string op_a = VisitOperand(operation, 0).AsFloat(); + const std::string op_b = VisitOperand(operation, 1).AsFloat(); + + if (!device.HasShaderBallot()) { + LOG_ERROR(Render_OpenGL, "Shader ballot is unavailable but required by the shader"); + return {fmt::format("{} + {}", op_a, op_b), Type::Float}; + } + + const std::string instr_mask = VisitOperand(operation, 2).AsUint(); + const std::string mask = code.GenerateTemporary(); + code.AddLine("uint {} = ({} >> ((gl_SubGroupInvocationARB & 3) << 1)) & 3;", mask, + instr_mask); + + const std::string modifier_a = fmt::format("fswzadd_modifiers_a[{}]", mask); + const std::string modifier_b = fmt::format("fswzadd_modifiers_b[{}]", mask); + return {fmt::format("(({} * {}) + ({} * {}))", op_a, modifier_a, op_b, modifier_b), + Type::Float}; + } + Expression ICastFloat(Operation operation) { return GenerateUnary(operation, "int", Type::Int, Type::Float); } @@ -1872,10 +1892,6 @@ private: Expression EmitVertex(Operation operation) { ASSERT_MSG(stage == ProgramType::Geometry, "EmitVertex is expected to be used in a geometry shader."); - - // If a geometry shader is attached, it will always flip (it's the last stage before - // fragment). For more info about flipping, refer to gl_shader_gen.cpp. - code.AddLine("gl_Position.xy *= viewport_flip.xy;"); code.AddLine("EmitVertex();"); return {}; } @@ -1883,14 +1899,12 @@ private: Expression EndPrimitive(Operation operation) { ASSERT_MSG(stage == ProgramType::Geometry, "EndPrimitive is expected to be used in a geometry shader."); - code.AddLine("EndPrimitive();"); return {}; } Expression YNegate(Operation operation) { - // Config pack's third value is Y_NEGATE's state. - return {"config_pack[2]", Type::Uint}; + return {"y_direction", Type::Float}; } template <u32 element> @@ -1942,34 +1956,24 @@ private: return Vote(operation, "allThreadsEqualNV"); } - template <const std::string_view& func> - Expression Shuffle(Operation operation) { - const std::string value = VisitOperand(operation, 0).AsFloat(); - if (!device.HasWarpIntrinsics()) { - LOG_ERROR(Render_OpenGL, "Nvidia shuffle intrinsics are required by this shader"); - // On a "single-thread" device we are either on the same thread or out of bounds. Both - // cases return the passed value. - return {value, Type::Float}; + Expression ThreadId(Operation operation) { + if (!device.HasShaderBallot()) { + LOG_ERROR(Render_OpenGL, "Shader ballot is unavailable but required by the shader"); + return {"0U", Type::Uint}; } - - const std::string index = VisitOperand(operation, 1).AsUint(); - const std::string width = VisitOperand(operation, 2).AsUint(); - return {fmt::format("{}({}, {}, {})", func, value, index, width), Type::Float}; + return {"gl_SubGroupInvocationARB", Type::Uint}; } - template <const std::string_view& func> - Expression InRangeShuffle(Operation operation) { - const std::string index = VisitOperand(operation, 0).AsUint(); - const std::string width = VisitOperand(operation, 1).AsUint(); - if (!device.HasWarpIntrinsics()) { - // On a "single-thread" device we are only in bounds when the requested index is 0. - return {fmt::format("({} == 0U)", index), Type::Bool}; + Expression ShuffleIndexed(Operation operation) { + std::string value = VisitOperand(operation, 0).AsFloat(); + + if (!device.HasShaderBallot()) { + LOG_ERROR(Render_OpenGL, "Shader ballot is unavailable but required by the shader"); + return {std::move(value), Type::Float}; } - const std::string in_range = code.GenerateTemporary(); - code.AddLine("bool {};", in_range); - code.AddLine("{}(0U, {}, {}, {});", func, index, width, in_range); - return {in_range, Type::Bool}; + const std::string index = VisitOperand(operation, 1).AsUint(); + return {fmt::format("readInvocationARB({}, {})", value, index), Type::Float}; } struct Func final { @@ -1981,11 +1985,6 @@ private: static constexpr std::string_view Or = "Or"; static constexpr std::string_view Xor = "Xor"; static constexpr std::string_view Exchange = "Exchange"; - - static constexpr std::string_view ShuffleIndexed = "shuffleNV"; - static constexpr std::string_view ShuffleUp = "shuffleUpNV"; - static constexpr std::string_view ShuffleDown = "shuffleDownNV"; - static constexpr std::string_view ShuffleButterfly = "shuffleXorNV"; }; static constexpr std::array operation_decompilers = { @@ -2016,6 +2015,7 @@ private: &GLSLDecompiler::FTrunc, &GLSLDecompiler::FCastInteger<Type::Int>, &GLSLDecompiler::FCastInteger<Type::Uint>, + &GLSLDecompiler::FSwizzleAdd, &GLSLDecompiler::Add<Type::Int>, &GLSLDecompiler::Mul<Type::Int>, @@ -2151,15 +2151,8 @@ private: &GLSLDecompiler::VoteAny, &GLSLDecompiler::VoteEqual, - &GLSLDecompiler::Shuffle<Func::ShuffleIndexed>, - &GLSLDecompiler::Shuffle<Func::ShuffleUp>, - &GLSLDecompiler::Shuffle<Func::ShuffleDown>, - &GLSLDecompiler::Shuffle<Func::ShuffleButterfly>, - - &GLSLDecompiler::InRangeShuffle<Func::ShuffleIndexed>, - &GLSLDecompiler::InRangeShuffle<Func::ShuffleUp>, - &GLSLDecompiler::InRangeShuffle<Func::ShuffleDown>, - &GLSLDecompiler::InRangeShuffle<Func::ShuffleButterfly>, + &GLSLDecompiler::ThreadId, + &GLSLDecompiler::ShuffleIndexed, }; static_assert(operation_decompilers.size() == static_cast<std::size_t>(OperationCode::Amount)); @@ -2492,6 +2485,9 @@ bvec2 HalfFloatNanComparison(bvec2 comparison, vec2 pair1, vec2 pair2) { bvec2 is_nan2 = isnan(pair2); return bvec2(comparison.x || is_nan1.x || is_nan2.x, comparison.y || is_nan1.y || is_nan2.y); } + +const float fswzadd_modifiers_a[] = float[4](-1.0f, 1.0f, -1.0f, 0.0f ); +const float fswzadd_modifiers_b[] = float[4](-1.0f, -1.0f, 1.0f, -1.0f ); )"; } diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp index 0e22eede9..a63c1a6b8 100644 --- a/src/video_core/renderer_opengl/gl_shader_gen.cpp +++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp @@ -20,8 +20,7 @@ std::string GenerateVertexShader(const Device& device, const ShaderIR& ir, const std::string out = GetCommonDeclarations(); out += R"( layout (std140, binding = EMULATION_UBO_BINDING) uniform vs_config { - vec4 viewport_flip; - uvec4 config_pack; // instance_id, flip_stage, y_direction, padding + float y_direction; }; )"; @@ -33,25 +32,13 @@ layout (std140, binding = EMULATION_UBO_BINDING) uniform vs_config { out += R"( void main() { + gl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f); execute_vertex(); )"; - if (ir_b) { out += " execute_vertex_b();"; } - - out += R"( - - // Set Position Y direction - gl_Position.y *= utof(config_pack[2]); - // Check if the flip stage is VertexB - // Config pack's second value is flip_stage - if (config_pack[1] == 1) { - // Viewport can be flipped, which is unsupported by glViewport - gl_Position.xy *= viewport_flip.xy; - } -} -)"; + out += "}\n"; return out; } @@ -59,8 +46,7 @@ std::string GenerateGeometryShader(const Device& device, const ShaderIR& ir) { std::string out = GetCommonDeclarations(); out += R"( layout (std140, binding = EMULATION_UBO_BINDING) uniform gs_config { - vec4 viewport_flip; - uvec4 config_pack; // instance_id, flip_stage, y_direction, padding + float y_direction; }; )"; @@ -87,8 +73,7 @@ layout (location = 6) out vec4 FragColor6; layout (location = 7) out vec4 FragColor7; layout (std140, binding = EMULATION_UBO_BINDING) uniform fs_config { - vec4 viewport_flip; - uvec4 config_pack; // instance_id, flip_stage, y_direction, padding + float y_direction; }; )"; diff --git a/src/video_core/renderer_opengl/gl_shader_manager.cpp b/src/video_core/renderer_opengl/gl_shader_manager.cpp index b05f90f20..75d3fac04 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.cpp +++ b/src/video_core/renderer_opengl/gl_shader_manager.cpp @@ -40,27 +40,11 @@ void ProgramManager::UpdatePipeline() { old_state = current_state; } -void MaxwellUniformData::SetFromRegs(const Maxwell3D& maxwell, std::size_t shader_stage) { +void MaxwellUniformData::SetFromRegs(const Maxwell3D& maxwell) { const auto& regs = maxwell.regs; - const auto& state = maxwell.state; - - // TODO(bunnei): Support more than one viewport - viewport_flip[0] = regs.viewport_transform[0].scale_x < 0.0 ? -1.0f : 1.0f; - viewport_flip[1] = regs.viewport_transform[0].scale_y < 0.0 ? -1.0f : 1.0f; - - instance_id = state.current_instance; - - // Assign in which stage the position has to be flipped - // (the last stage before the fragment shader). - constexpr u32 geometry_index = static_cast<u32>(Maxwell3D::Regs::ShaderProgram::Geometry); - if (maxwell.regs.shader_config[geometry_index].enable) { - flip_stage = geometry_index; - } else { - flip_stage = static_cast<u32>(Maxwell3D::Regs::ShaderProgram::VertexB); - } // Y_NEGATE controls what value S2R returns for the Y_DIRECTION system value. - y_direction = regs.screen_y_control.y_negate == 0 ? 1.f : -1.f; + y_direction = regs.screen_y_control.y_negate == 0 ? 1.0f : -1.0f; } } // namespace OpenGL::GLShader diff --git a/src/video_core/renderer_opengl/gl_shader_manager.h b/src/video_core/renderer_opengl/gl_shader_manager.h index 6961e702a..3703e7018 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.h +++ b/src/video_core/renderer_opengl/gl_shader_manager.h @@ -18,17 +18,12 @@ namespace OpenGL::GLShader { /// @note Always keep a vec4 at the end. The GL spec is not clear whether the alignment at /// the end of a uniform block is included in UNIFORM_BLOCK_DATA_SIZE or not. /// Not following that rule will cause problems on some AMD drivers. -struct MaxwellUniformData { - void SetFromRegs(const Tegra::Engines::Maxwell3D& maxwell, std::size_t shader_stage); - - alignas(16) GLvec4 viewport_flip; - struct alignas(16) { - GLuint instance_id; - GLuint flip_stage; - GLfloat y_direction; - }; +struct alignas(16) MaxwellUniformData { + void SetFromRegs(const Tegra::Engines::Maxwell3D& maxwell); + + GLfloat y_direction; }; -static_assert(sizeof(MaxwellUniformData) == 32, "MaxwellUniformData structure size is incorrect"); +static_assert(sizeof(MaxwellUniformData) == 16, "MaxwellUniformData structure size is incorrect"); static_assert(sizeof(MaxwellUniformData) < 16384, "MaxwellUniformData structure must be less than 16kb as per the OpenGL spec"); diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp index f25148362..ccbe5912e 100644 --- a/src/video_core/renderer_opengl/gl_state.cpp +++ b/src/video_core/renderer_opengl/gl_state.cpp @@ -410,6 +410,12 @@ void OpenGLState::ApplyAlphaTest() { } } +void OpenGLState::ApplyClipControl() { + if (UpdateValue(cur_state.clip_control.origin, clip_control.origin)) { + glClipControl(clip_control.origin, GL_NEGATIVE_ONE_TO_ONE); + } +} + void OpenGLState::ApplyTextures() { if (const auto update = UpdateArray(cur_state.textures, textures)) { glBindTextures(update->first, update->second, textures.data() + update->first); @@ -453,6 +459,7 @@ void OpenGLState::Apply() { ApplyImages(); ApplyPolygonOffset(); ApplyAlphaTest(); + ApplyClipControl(); } void OpenGLState::EmulateViewportWithScissor() { diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h index cca25206b..eaff22bda 100644 --- a/src/video_core/renderer_opengl/gl_state.h +++ b/src/video_core/renderer_opengl/gl_state.h @@ -146,6 +146,10 @@ public: std::array<bool, 8> clip_distance = {}; // GL_CLIP_DISTANCE + struct { + GLenum origin = GL_LOWER_LEFT; + } clip_control; + OpenGLState(); /// Get the currently active OpenGL state @@ -182,6 +186,7 @@ public: void ApplyDepthClamp(); void ApplyPolygonOffset(); void ApplyAlphaTest(); + void ApplyClipControl(); /// Resets any references to the given resource OpenGLState& UnbindTexture(GLuint handle); diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 55b3e58b2..4659e098f 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp @@ -23,7 +23,6 @@ namespace OpenGL { using Tegra::Texture::SwizzleSource; using VideoCore::MortonSwizzleMode; -using VideoCore::Surface::ComponentType; using VideoCore::Surface::PixelFormat; using VideoCore::Surface::SurfaceCompression; using VideoCore::Surface::SurfaceTarget; @@ -40,114 +39,95 @@ struct FormatTuple { GLint internal_format; GLenum format; GLenum type; - ComponentType component_type; bool compressed; }; constexpr std::array<FormatTuple, VideoCore::Surface::MaxPixelFormat> tex_format_tuples = {{ - {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, ComponentType::UNorm, false}, // ABGR8U - {GL_RGBA8, GL_RGBA, GL_BYTE, ComponentType::SNorm, false}, // ABGR8S - {GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, ComponentType::UInt, false}, // ABGR8UI - {GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV, ComponentType::UNorm, false}, // B5G6R5U - {GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, ComponentType::UNorm, - false}, // A2B10G10R10U - {GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, ComponentType::UNorm, false}, // A1B5G5R5U - {GL_R8, GL_RED, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // R8U - {GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE, ComponentType::UInt, false}, // R8UI - {GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, ComponentType::Float, false}, // RGBA16F - {GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, ComponentType::UNorm, false}, // RGBA16U - {GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, ComponentType::UInt, false}, // RGBA16UI - {GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, ComponentType::Float, - false}, // R11FG11FB10F - {GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT, ComponentType::UInt, false}, // RGBA32UI - {GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, ComponentType::UNorm, - true}, // DXT1 - {GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, ComponentType::UNorm, - true}, // DXT23 - {GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, ComponentType::UNorm, - true}, // DXT45 - {GL_COMPRESSED_RED_RGTC1, GL_RED, GL_UNSIGNED_INT_8_8_8_8, ComponentType::UNorm, true}, // DXN1 - {GL_COMPRESSED_RG_RGTC2, GL_RG, GL_UNSIGNED_INT_8_8_8_8, ComponentType::UNorm, - true}, // DXN2UNORM - {GL_COMPRESSED_SIGNED_RG_RGTC2, GL_RG, GL_INT, ComponentType::SNorm, true}, // DXN2SNORM - {GL_COMPRESSED_RGBA_BPTC_UNORM, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, ComponentType::UNorm, - true}, // BC7U - {GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT, GL_RGB, GL_UNSIGNED_INT_8_8_8_8, ComponentType::Float, - true}, // BC6H_UF16 - {GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT, GL_RGB, GL_UNSIGNED_INT_8_8_8_8, ComponentType::Float, - true}, // BC6H_SF16 - {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_4X4 - {GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // BGRA8 - {GL_RGBA32F, GL_RGBA, GL_FLOAT, ComponentType::Float, false}, // RGBA32F - {GL_RG32F, GL_RG, GL_FLOAT, ComponentType::Float, false}, // RG32F - {GL_R32F, GL_RED, GL_FLOAT, ComponentType::Float, false}, // R32F - {GL_R16F, GL_RED, GL_HALF_FLOAT, ComponentType::Float, false}, // R16F - {GL_R16, GL_RED, GL_UNSIGNED_SHORT, ComponentType::UNorm, false}, // R16U - {GL_R16_SNORM, GL_RED, GL_SHORT, ComponentType::SNorm, false}, // R16S - {GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT, ComponentType::UInt, false}, // R16UI - {GL_R16I, GL_RED_INTEGER, GL_SHORT, ComponentType::SInt, false}, // R16I - {GL_RG16, GL_RG, GL_UNSIGNED_SHORT, ComponentType::UNorm, false}, // RG16 - {GL_RG16F, GL_RG, GL_HALF_FLOAT, ComponentType::Float, false}, // RG16F - {GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT, ComponentType::UInt, false}, // RG16UI - {GL_RG16I, GL_RG_INTEGER, GL_SHORT, ComponentType::SInt, false}, // RG16I - {GL_RG16_SNORM, GL_RG, GL_SHORT, ComponentType::SNorm, false}, // RG16S - {GL_RGB32F, GL_RGB, GL_FLOAT, ComponentType::Float, false}, // RGB32F - {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, ComponentType::UNorm, - false}, // RGBA8_SRGB - {GL_RG8, GL_RG, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // RG8U - {GL_RG8, GL_RG, GL_BYTE, ComponentType::SNorm, false}, // RG8S - {GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT, ComponentType::UInt, false}, // RG32UI - {GL_RGB16F, GL_RGBA16, GL_HALF_FLOAT, ComponentType::Float, false}, // RGBX16F - {GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT, ComponentType::UInt, false}, // R32UI - {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_8X8 - {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_8X5 - {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_5X4 - {GL_SRGB8_ALPHA8, GL_BGRA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // BGRA8 + {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, false}, // ABGR8U + {GL_RGBA8, GL_RGBA, GL_BYTE, false}, // ABGR8S + {GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, false}, // ABGR8UI + {GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV, false}, // B5G6R5U + {GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, false}, // A2B10G10R10U + {GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, false}, // A1B5G5R5U + {GL_R8, GL_RED, GL_UNSIGNED_BYTE, false}, // R8U + {GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE, false}, // R8UI + {GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, false}, // RGBA16F + {GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, false}, // RGBA16U + {GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, false}, // RGBA16UI + {GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, false}, // R11FG11FB10F + {GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT, false}, // RGBA32UI + {GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true}, // DXT1 + {GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true}, // DXT23 + {GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true}, // DXT45 + {GL_COMPRESSED_RED_RGTC1, GL_RED, GL_UNSIGNED_INT_8_8_8_8, true}, // DXN1 + {GL_COMPRESSED_RG_RGTC2, GL_RG, GL_UNSIGNED_INT_8_8_8_8, true}, // DXN2UNORM + {GL_COMPRESSED_SIGNED_RG_RGTC2, GL_RG, GL_INT, true}, // DXN2SNORM + {GL_COMPRESSED_RGBA_BPTC_UNORM, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true}, // BC7U + {GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT, GL_RGB, GL_UNSIGNED_INT_8_8_8_8, true}, // BC6H_UF16 + {GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT, GL_RGB, GL_UNSIGNED_INT_8_8_8_8, true}, // BC6H_SF16 + {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, false}, // ASTC_2D_4X4 + {GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, false}, // BGRA8 + {GL_RGBA32F, GL_RGBA, GL_FLOAT, false}, // RGBA32F + {GL_RG32F, GL_RG, GL_FLOAT, false}, // RG32F + {GL_R32F, GL_RED, GL_FLOAT, false}, // R32F + {GL_R16F, GL_RED, GL_HALF_FLOAT, false}, // R16F + {GL_R16, GL_RED, GL_UNSIGNED_SHORT, false}, // R16U + {GL_R16_SNORM, GL_RED, GL_SHORT, false}, // R16S + {GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT, false}, // R16UI + {GL_R16I, GL_RED_INTEGER, GL_SHORT, false}, // R16I + {GL_RG16, GL_RG, GL_UNSIGNED_SHORT, false}, // RG16 + {GL_RG16F, GL_RG, GL_HALF_FLOAT, false}, // RG16F + {GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT, false}, // RG16UI + {GL_RG16I, GL_RG_INTEGER, GL_SHORT, false}, // RG16I + {GL_RG16_SNORM, GL_RG, GL_SHORT, false}, // RG16S + {GL_RGB32F, GL_RGB, GL_FLOAT, false}, // RGB32F + {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, false}, // RGBA8_SRGB + {GL_RG8, GL_RG, GL_UNSIGNED_BYTE, false}, // RG8U + {GL_RG8, GL_RG, GL_BYTE, false}, // RG8S + {GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT, false}, // RG32UI + {GL_RGB16F, GL_RGBA16, GL_HALF_FLOAT, false}, // RGBX16F + {GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT, false}, // R32UI + {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, false}, // ASTC_2D_8X8 + {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, false}, // ASTC_2D_8X5 + {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, false}, // ASTC_2D_5X4 + {GL_SRGB8_ALPHA8, GL_BGRA, GL_UNSIGNED_BYTE, false}, // BGRA8 // Compressed sRGB formats - {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, ComponentType::UNorm, - true}, // DXT1_SRGB - {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, ComponentType::UNorm, - true}, // DXT23_SRGB - {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, ComponentType::UNorm, - true}, // DXT45_SRGB - {GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, ComponentType::UNorm, - true}, // BC7U_SRGB - {GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4_REV, ComponentType::UNorm, false}, // R4G4B4A4U - {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_4X4_SRGB - {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_8X8_SRGB - {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_8X5_SRGB - {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_5X4_SRGB - {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_5X5 - {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_5X5_SRGB - {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_10X8 - {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_10X8_SRGB - {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_6X6 - {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_6X6_SRGB - {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_10X10 - {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_10X10_SRGB - {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_12X12 - {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_12X12_SRGB - {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_8X6 - {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_8X6_SRGB - {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_6X5 - {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_6X5_SRGB - {GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, ComponentType::Float, false}, // E5B9G9R9F + {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true}, // DXT1_SRGB + {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true}, // DXT23_SRGB + {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true}, // DXT45_SRGB + {GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true}, // BC7U_SRGB + {GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4_REV, false}, // R4G4B4A4U + {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, false}, // ASTC_2D_4X4_SRGB + {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, false}, // ASTC_2D_8X8_SRGB + {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, false}, // ASTC_2D_8X5_SRGB + {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, false}, // ASTC_2D_5X4_SRGB + {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, false}, // ASTC_2D_5X5 + {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, false}, // ASTC_2D_5X5_SRGB + {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, false}, // ASTC_2D_10X8 + {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, false}, // ASTC_2D_10X8_SRGB + {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, false}, // ASTC_2D_6X6 + {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, false}, // ASTC_2D_6X6_SRGB + {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, false}, // ASTC_2D_10X10 + {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, false}, // ASTC_2D_10X10_SRGB + {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, false}, // ASTC_2D_12X12 + {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, false}, // ASTC_2D_12X12_SRGB + {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, false}, // ASTC_2D_8X6 + {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, false}, // ASTC_2D_8X6_SRGB + {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, false}, // ASTC_2D_6X5 + {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, false}, // ASTC_2D_6X5_SRGB + {GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, false}, // E5B9G9R9F // Depth formats - {GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT, ComponentType::Float, false}, // Z32F - {GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, ComponentType::UNorm, - false}, // Z16 + {GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT, false}, // Z32F + {GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, false}, // Z16 // DepthStencil formats - {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, ComponentType::UNorm, - false}, // Z24S8 - {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, ComponentType::UNorm, - false}, // S8Z24 - {GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, - ComponentType::Float, false}, // Z32FS8 + {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, false}, // Z24S8 + {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, false}, // S8Z24 + {GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, false}, // Z32FS8 }}; -const FormatTuple& GetFormatTuple(PixelFormat pixel_format, ComponentType component_type) { +const FormatTuple& GetFormatTuple(PixelFormat pixel_format) { ASSERT(static_cast<std::size_t>(pixel_format) < tex_format_tuples.size()); const auto& format{tex_format_tuples[static_cast<std::size_t>(pixel_format)]}; return format; @@ -249,7 +229,7 @@ OGLTexture CreateTexture(const SurfaceParams& params, GLenum target, GLenum inte CachedSurface::CachedSurface(const GPUVAddr gpu_addr, const SurfaceParams& params) : VideoCommon::SurfaceBase<View>(gpu_addr, params) { - const auto& tuple{GetFormatTuple(params.pixel_format, params.component_type)}; + const auto& tuple{GetFormatTuple(params.pixel_format)}; internal_format = tuple.internal_format; format = tuple.format; type = tuple.type; @@ -451,8 +431,7 @@ OGLTextureView CachedSurfaceView::CreateTextureView() const { texture_view.Create(); const GLuint handle{texture_view.handle}; - const FormatTuple& tuple{ - GetFormatTuple(owner_params.pixel_format, owner_params.component_type)}; + const FormatTuple& tuple{GetFormatTuple(owner_params.pixel_format)}; glTextureView(handle, target, surface.texture.handle, tuple.internal_format, params.base_level, params.num_levels, params.base_layer, params.num_layers); @@ -562,8 +541,8 @@ void TextureCacheOpenGL::BufferCopy(Surface& src_surface, Surface& dst_surface) const auto& dst_params = dst_surface->GetSurfaceParams(); UNIMPLEMENTED_IF(src_params.num_levels > 1 || dst_params.num_levels > 1); - const auto source_format = GetFormatTuple(src_params.pixel_format, src_params.component_type); - const auto dest_format = GetFormatTuple(dst_params.pixel_format, dst_params.component_type); + const auto source_format = GetFormatTuple(src_params.pixel_format); + const auto dest_format = GetFormatTuple(dst_params.pixel_format); const std::size_t source_size = src_surface->GetHostSizeInBytes(); const std::size_t dest_size = dst_surface->GetHostSizeInBytes(); diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp index 3c5acda3e..463ed43ae 100644 --- a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp +++ b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp @@ -95,83 +95,82 @@ vk::CompareOp DepthCompareFunction(Tegra::Texture::DepthCompareFunc depth_compar } // namespace Sampler struct FormatTuple { - vk::Format format; ///< Vulkan format - ComponentType component_type; ///< Abstracted component type - bool attachable; ///< True when this format can be used as an attachment + vk::Format format; ///< Vulkan format + bool attachable; ///< True when this format can be used as an attachment }; static constexpr std::array<FormatTuple, VideoCore::Surface::MaxPixelFormat> tex_format_tuples = {{ - {vk::Format::eA8B8G8R8UnormPack32, ComponentType::UNorm, true}, // ABGR8U - {vk::Format::eUndefined, ComponentType::Invalid, false}, // ABGR8S - {vk::Format::eUndefined, ComponentType::Invalid, false}, // ABGR8UI - {vk::Format::eB5G6R5UnormPack16, ComponentType::UNorm, false}, // B5G6R5U - {vk::Format::eA2B10G10R10UnormPack32, ComponentType::UNorm, true}, // A2B10G10R10U - {vk::Format::eUndefined, ComponentType::Invalid, false}, // A1B5G5R5U - {vk::Format::eR8Unorm, ComponentType::UNorm, true}, // R8U - {vk::Format::eUndefined, ComponentType::Invalid, false}, // R8UI - {vk::Format::eUndefined, ComponentType::Invalid, false}, // RGBA16F - {vk::Format::eUndefined, ComponentType::Invalid, false}, // RGBA16U - {vk::Format::eUndefined, ComponentType::Invalid, false}, // RGBA16UI - {vk::Format::eUndefined, ComponentType::Invalid, false}, // R11FG11FB10F - {vk::Format::eUndefined, ComponentType::Invalid, false}, // RGBA32UI - {vk::Format::eBc1RgbaUnormBlock, ComponentType::UNorm, false}, // DXT1 - {vk::Format::eBc2UnormBlock, ComponentType::UNorm, false}, // DXT23 - {vk::Format::eBc3UnormBlock, ComponentType::UNorm, false}, // DXT45 - {vk::Format::eBc4UnormBlock, ComponentType::UNorm, false}, // DXN1 - {vk::Format::eUndefined, ComponentType::Invalid, false}, // DXN2UNORM - {vk::Format::eUndefined, ComponentType::Invalid, false}, // DXN2SNORM - {vk::Format::eUndefined, ComponentType::Invalid, false}, // BC7U - {vk::Format::eUndefined, ComponentType::Invalid, false}, // BC6H_UF16 - {vk::Format::eUndefined, ComponentType::Invalid, false}, // BC6H_SF16 - {vk::Format::eUndefined, ComponentType::Invalid, false}, // ASTC_2D_4X4 - {vk::Format::eUndefined, ComponentType::Invalid, false}, // BGRA8 - {vk::Format::eUndefined, ComponentType::Invalid, false}, // RGBA32F - {vk::Format::eUndefined, ComponentType::Invalid, false}, // RG32F - {vk::Format::eUndefined, ComponentType::Invalid, false}, // R32F - {vk::Format::eUndefined, ComponentType::Invalid, false}, // R16F - {vk::Format::eUndefined, ComponentType::Invalid, false}, // R16U - {vk::Format::eUndefined, ComponentType::Invalid, false}, // R16S - {vk::Format::eUndefined, ComponentType::Invalid, false}, // R16UI - {vk::Format::eUndefined, ComponentType::Invalid, false}, // R16I - {vk::Format::eUndefined, ComponentType::Invalid, false}, // RG16 - {vk::Format::eUndefined, ComponentType::Invalid, false}, // RG16F - {vk::Format::eUndefined, ComponentType::Invalid, false}, // RG16UI - {vk::Format::eUndefined, ComponentType::Invalid, false}, // RG16I - {vk::Format::eUndefined, ComponentType::Invalid, false}, // RG16S - {vk::Format::eUndefined, ComponentType::Invalid, false}, // RGB32F - {vk::Format::eA8B8G8R8SrgbPack32, ComponentType::UNorm, true}, // RGBA8_SRGB - {vk::Format::eUndefined, ComponentType::Invalid, false}, // RG8U - {vk::Format::eUndefined, ComponentType::Invalid, false}, // RG8S - {vk::Format::eUndefined, ComponentType::Invalid, false}, // RG32UI - {vk::Format::eUndefined, ComponentType::Invalid, false}, // RGBX16F - {vk::Format::eUndefined, ComponentType::Invalid, false}, // R32UI - {vk::Format::eUndefined, ComponentType::Invalid, false}, // ASTC_2D_8X8 - {vk::Format::eUndefined, ComponentType::Invalid, false}, // ASTC_2D_8X5 - {vk::Format::eUndefined, ComponentType::Invalid, false}, // ASTC_2D_5X4 + {vk::Format::eA8B8G8R8UnormPack32, true}, // ABGR8U + {vk::Format::eUndefined, false}, // ABGR8S + {vk::Format::eUndefined, false}, // ABGR8UI + {vk::Format::eB5G6R5UnormPack16, false}, // B5G6R5U + {vk::Format::eA2B10G10R10UnormPack32, true}, // A2B10G10R10U + {vk::Format::eUndefined, false}, // A1B5G5R5U + {vk::Format::eR8Unorm, true}, // R8U + {vk::Format::eUndefined, false}, // R8UI + {vk::Format::eUndefined, false}, // RGBA16F + {vk::Format::eUndefined, false}, // RGBA16U + {vk::Format::eUndefined, false}, // RGBA16UI + {vk::Format::eUndefined, false}, // R11FG11FB10F + {vk::Format::eUndefined, false}, // RGBA32UI + {vk::Format::eBc1RgbaUnormBlock, false}, // DXT1 + {vk::Format::eBc2UnormBlock, false}, // DXT23 + {vk::Format::eBc3UnormBlock, false}, // DXT45 + {vk::Format::eBc4UnormBlock, false}, // DXN1 + {vk::Format::eUndefined, false}, // DXN2UNORM + {vk::Format::eUndefined, false}, // DXN2SNORM + {vk::Format::eUndefined, false}, // BC7U + {vk::Format::eUndefined, false}, // BC6H_UF16 + {vk::Format::eUndefined, false}, // BC6H_SF16 + {vk::Format::eUndefined, false}, // ASTC_2D_4X4 + {vk::Format::eUndefined, false}, // BGRA8 + {vk::Format::eUndefined, false}, // RGBA32F + {vk::Format::eUndefined, false}, // RG32F + {vk::Format::eUndefined, false}, // R32F + {vk::Format::eUndefined, false}, // R16F + {vk::Format::eUndefined, false}, // R16U + {vk::Format::eUndefined, false}, // R16S + {vk::Format::eUndefined, false}, // R16UI + {vk::Format::eUndefined, false}, // R16I + {vk::Format::eUndefined, false}, // RG16 + {vk::Format::eUndefined, false}, // RG16F + {vk::Format::eUndefined, false}, // RG16UI + {vk::Format::eUndefined, false}, // RG16I + {vk::Format::eUndefined, false}, // RG16S + {vk::Format::eUndefined, false}, // RGB32F + {vk::Format::eA8B8G8R8SrgbPack32, true}, // RGBA8_SRGB + {vk::Format::eUndefined, false}, // RG8U + {vk::Format::eUndefined, false}, // RG8S + {vk::Format::eUndefined, false}, // RG32UI + {vk::Format::eUndefined, false}, // RGBX16F + {vk::Format::eUndefined, false}, // R32UI + {vk::Format::eUndefined, false}, // ASTC_2D_8X8 + {vk::Format::eUndefined, false}, // ASTC_2D_8X5 + {vk::Format::eUndefined, false}, // ASTC_2D_5X4 // Compressed sRGB formats - {vk::Format::eUndefined, ComponentType::Invalid, false}, // BGRA8_SRGB - {vk::Format::eUndefined, ComponentType::Invalid, false}, // DXT1_SRGB - {vk::Format::eUndefined, ComponentType::Invalid, false}, // DXT23_SRGB - {vk::Format::eUndefined, ComponentType::Invalid, false}, // DXT45_SRGB - {vk::Format::eUndefined, ComponentType::Invalid, false}, // BC7U_SRGB - {vk::Format::eUndefined, ComponentType::Invalid, false}, // ASTC_2D_4X4_SRGB - {vk::Format::eUndefined, ComponentType::Invalid, false}, // ASTC_2D_8X8_SRGB - {vk::Format::eUndefined, ComponentType::Invalid, false}, // ASTC_2D_8X5_SRGB - {vk::Format::eUndefined, ComponentType::Invalid, false}, // ASTC_2D_5X4_SRGB - {vk::Format::eUndefined, ComponentType::Invalid, false}, // ASTC_2D_5X5 - {vk::Format::eUndefined, ComponentType::Invalid, false}, // ASTC_2D_5X5_SRGB - {vk::Format::eUndefined, ComponentType::Invalid, false}, // ASTC_2D_10X8 - {vk::Format::eUndefined, ComponentType::Invalid, false}, // ASTC_2D_10X8_SRGB + {vk::Format::eUndefined, false}, // BGRA8_SRGB + {vk::Format::eUndefined, false}, // DXT1_SRGB + {vk::Format::eUndefined, false}, // DXT23_SRGB + {vk::Format::eUndefined, false}, // DXT45_SRGB + {vk::Format::eUndefined, false}, // BC7U_SRGB + {vk::Format::eUndefined, false}, // ASTC_2D_4X4_SRGB + {vk::Format::eUndefined, false}, // ASTC_2D_8X8_SRGB + {vk::Format::eUndefined, false}, // ASTC_2D_8X5_SRGB + {vk::Format::eUndefined, false}, // ASTC_2D_5X4_SRGB + {vk::Format::eUndefined, false}, // ASTC_2D_5X5 + {vk::Format::eUndefined, false}, // ASTC_2D_5X5_SRGB + {vk::Format::eUndefined, false}, // ASTC_2D_10X8 + {vk::Format::eUndefined, false}, // ASTC_2D_10X8_SRGB // Depth formats - {vk::Format::eD32Sfloat, ComponentType::Float, true}, // Z32F - {vk::Format::eD16Unorm, ComponentType::UNorm, true}, // Z16 + {vk::Format::eD32Sfloat, true}, // Z32F + {vk::Format::eD16Unorm, true}, // Z16 // DepthStencil formats - {vk::Format::eD24UnormS8Uint, ComponentType::UNorm, true}, // Z24S8 - {vk::Format::eD24UnormS8Uint, ComponentType::UNorm, true}, // S8Z24 (emulated) - {vk::Format::eUndefined, ComponentType::Invalid, false}, // Z32FS8 + {vk::Format::eD24UnormS8Uint, true}, // Z24S8 + {vk::Format::eD24UnormS8Uint, true}, // S8Z24 (emulated) + {vk::Format::eUndefined, false}, // Z32FS8 }}; static constexpr bool IsZetaFormat(PixelFormat pixel_format) { @@ -180,14 +179,13 @@ static constexpr bool IsZetaFormat(PixelFormat pixel_format) { } std::pair<vk::Format, bool> SurfaceFormat(const VKDevice& device, FormatType format_type, - PixelFormat pixel_format, ComponentType component_type) { + PixelFormat pixel_format) { ASSERT(static_cast<std::size_t>(pixel_format) < tex_format_tuples.size()); const auto tuple = tex_format_tuples[static_cast<u32>(pixel_format)]; UNIMPLEMENTED_IF_MSG(tuple.format == vk::Format::eUndefined, - "Unimplemented texture format with pixel format={} and component type={}", - static_cast<u32>(pixel_format), static_cast<u32>(component_type)); - ASSERT_MSG(component_type == tuple.component_type, "Component type mismatch"); + "Unimplemented texture format with pixel format={}", + static_cast<u32>(pixel_format)); auto usage = vk::FormatFeatureFlagBits::eSampledImage | vk::FormatFeatureFlagBits::eTransferDst | vk::FormatFeatureFlagBits::eTransferSrc; diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.h b/src/video_core/renderer_vulkan/maxwell_to_vk.h index 4cadc0721..5b0ffd87a 100644 --- a/src/video_core/renderer_vulkan/maxwell_to_vk.h +++ b/src/video_core/renderer_vulkan/maxwell_to_vk.h @@ -16,7 +16,6 @@ namespace Vulkan::MaxwellToVK { using Maxwell = Tegra::Engines::Maxwell3D::Regs; using PixelFormat = VideoCore::Surface::PixelFormat; -using ComponentType = VideoCore::Surface::ComponentType; namespace Sampler { @@ -31,7 +30,7 @@ vk::CompareOp DepthCompareFunction(Tegra::Texture::DepthCompareFunc depth_compar } // namespace Sampler std::pair<vk::Format, bool> SurfaceFormat(const VKDevice& device, FormatType format_type, - PixelFormat pixel_format, ComponentType component_type); + PixelFormat pixel_format); vk::ShaderStageFlagBits ShaderStage(Maxwell::ShaderStage stage); diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp index 42cf068b6..2850d5b59 100644 --- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp +++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp @@ -783,6 +783,11 @@ private: return {}; } + Id FSwizzleAdd(Operation operation) { + UNIMPLEMENTED(); + return {}; + } + Id HNegate(Operation operation) { UNIMPLEMENTED(); return {}; @@ -1195,42 +1200,12 @@ private: return {}; } - Id ShuffleIndexed(Operation) { - UNIMPLEMENTED(); - return {}; - } - - Id ShuffleUp(Operation) { - UNIMPLEMENTED(); - return {}; - } - - Id ShuffleDown(Operation) { - UNIMPLEMENTED(); - return {}; - } - - Id ShuffleButterfly(Operation) { - UNIMPLEMENTED(); - return {}; - } - - Id InRangeShuffleIndexed(Operation) { + Id ThreadId(Operation) { UNIMPLEMENTED(); return {}; } - Id InRangeShuffleUp(Operation) { - UNIMPLEMENTED(); - return {}; - } - - Id InRangeShuffleDown(Operation) { - UNIMPLEMENTED(); - return {}; - } - - Id InRangeShuffleButterfly(Operation) { + Id ShuffleIndexed(Operation) { UNIMPLEMENTED(); return {}; } @@ -1393,6 +1368,7 @@ private: &SPIRVDecompiler::Unary<&Module::OpTrunc, Type::Float>, &SPIRVDecompiler::Unary<&Module::OpConvertSToF, Type::Float, Type::Int>, &SPIRVDecompiler::Unary<&Module::OpConvertUToF, Type::Float, Type::Uint>, + &SPIRVDecompiler::FSwizzleAdd, &SPIRVDecompiler::Binary<&Module::OpIAdd, Type::Int>, &SPIRVDecompiler::Binary<&Module::OpIMul, Type::Int>, @@ -1528,15 +1504,8 @@ private: &SPIRVDecompiler::VoteAny, &SPIRVDecompiler::VoteEqual, + &SPIRVDecompiler::ThreadId, &SPIRVDecompiler::ShuffleIndexed, - &SPIRVDecompiler::ShuffleUp, - &SPIRVDecompiler::ShuffleDown, - &SPIRVDecompiler::ShuffleButterfly, - - &SPIRVDecompiler::InRangeShuffleIndexed, - &SPIRVDecompiler::InRangeShuffleUp, - &SPIRVDecompiler::InRangeShuffleDown, - &SPIRVDecompiler::InRangeShuffleButterfly, }; static_assert(operation_decompilers.size() == static_cast<std::size_t>(OperationCode::Amount)); diff --git a/src/video_core/shader/decode/other.cpp b/src/video_core/shader/decode/other.cpp index 116b95f76..17cd45d3c 100644 --- a/src/video_core/shader/decode/other.cpp +++ b/src/video_core/shader/decode/other.cpp @@ -256,7 +256,7 @@ u32 ShaderIR::DecodeOther(NodeBlock& bb, u32 pc) { break; } case OpCode::Id::DEPBAR: { - LOG_WARNING(HW_GPU, "DEPBAR instruction is stubbed"); + LOG_DEBUG(HW_GPU, "DEPBAR instruction is stubbed"); break; } default: diff --git a/src/video_core/shader/decode/warp.cpp b/src/video_core/shader/decode/warp.cpp index fa8a250cc..d98d0e1dd 100644 --- a/src/video_core/shader/decode/warp.cpp +++ b/src/video_core/shader/decode/warp.cpp @@ -17,6 +17,7 @@ using Tegra::Shader::ShuffleOperation; using Tegra::Shader::VoteOperation; namespace { + OperationCode GetOperationCode(VoteOperation vote_op) { switch (vote_op) { case VoteOperation::All: @@ -30,6 +31,7 @@ OperationCode GetOperationCode(VoteOperation vote_op) { return OperationCode::VoteAll; } } + } // Anonymous namespace u32 ShaderIR::DecodeWarp(NodeBlock& bb, u32 pc) { @@ -46,50 +48,59 @@ u32 ShaderIR::DecodeWarp(NodeBlock& bb, u32 pc) { break; } case OpCode::Id::SHFL: { - Node width = [this, instr] { - Node mask = instr.shfl.is_mask_imm ? Immediate(static_cast<u32>(instr.shfl.mask_imm)) - : GetRegister(instr.gpr39); - - // Convert the obscure SHFL mask back into GL_NV_shader_thread_shuffle's width. This has - // been done reversing Nvidia's math. It won't work on all cases due to SHFL having - // different parameters that don't properly map to GLSL's interface, but it should work - // for cases emitted by Nvidia's compiler. - if (instr.shfl.operation == ShuffleOperation::Up) { - return Operation( - OperationCode::ILogicalShiftRight, - Operation(OperationCode::IAdd, std::move(mask), Immediate(-0x2000)), - Immediate(8)); - } else { - return Operation(OperationCode::ILogicalShiftRight, - Operation(OperationCode::IAdd, Immediate(0x201F), - Operation(OperationCode::INegate, std::move(mask))), - Immediate(8)); - } - }(); + Node mask = instr.shfl.is_mask_imm ? Immediate(static_cast<u32>(instr.shfl.mask_imm)) + : GetRegister(instr.gpr39); + Node index = instr.shfl.is_index_imm ? Immediate(static_cast<u32>(instr.shfl.index_imm)) + : GetRegister(instr.gpr20); + + Node thread_id = Operation(OperationCode::ThreadId); + Node clamp = Operation(OperationCode::IBitwiseAnd, mask, Immediate(0x1FU)); + Node seg_mask = BitfieldExtract(mask, 8, 16); - const auto [operation, in_range] = [instr]() -> std::pair<OperationCode, OperationCode> { + Node neg_seg_mask = Operation(OperationCode::IBitwiseNot, seg_mask); + Node min_thread_id = Operation(OperationCode::IBitwiseAnd, thread_id, seg_mask); + Node max_thread_id = Operation(OperationCode::IBitwiseOr, min_thread_id, + Operation(OperationCode::IBitwiseAnd, clamp, neg_seg_mask)); + + Node src_thread_id = [instr, index, neg_seg_mask, min_thread_id, thread_id] { switch (instr.shfl.operation) { case ShuffleOperation::Idx: - return {OperationCode::ShuffleIndexed, OperationCode::InRangeShuffleIndexed}; - case ShuffleOperation::Up: - return {OperationCode::ShuffleUp, OperationCode::InRangeShuffleUp}; + return Operation(OperationCode::IBitwiseOr, + Operation(OperationCode::IBitwiseAnd, index, neg_seg_mask), + min_thread_id); case ShuffleOperation::Down: - return {OperationCode::ShuffleDown, OperationCode::InRangeShuffleDown}; + return Operation(OperationCode::IAdd, thread_id, index); + case ShuffleOperation::Up: + return Operation(OperationCode::IAdd, thread_id, + Operation(OperationCode::INegate, index)); case ShuffleOperation::Bfly: - return {OperationCode::ShuffleButterfly, OperationCode::InRangeShuffleButterfly}; + return Operation(OperationCode::IBitwiseXor, thread_id, index); } - UNREACHABLE_MSG("Invalid SHFL operation: {}", - static_cast<u64>(instr.shfl.operation.Value())); - return {}; + UNREACHABLE(); + return Immediate(0U); }(); - // Setting the predicate before the register is intentional to avoid overwriting. - Node index = instr.shfl.is_index_imm ? Immediate(static_cast<u32>(instr.shfl.index_imm)) - : GetRegister(instr.gpr20); - SetPredicate(bb, instr.shfl.pred48, Operation(in_range, index, width)); + Node in_bounds = [instr, src_thread_id, min_thread_id, max_thread_id] { + if (instr.shfl.operation == ShuffleOperation::Up) { + return Operation(OperationCode::LogicalIGreaterEqual, src_thread_id, min_thread_id); + } else { + return Operation(OperationCode::LogicalILessEqual, src_thread_id, max_thread_id); + } + }(); + + SetPredicate(bb, instr.shfl.pred48, in_bounds); SetRegister( bb, instr.gpr0, - Operation(operation, GetRegister(instr.gpr8), std::move(index), std::move(width))); + Operation(OperationCode::ShuffleIndexed, GetRegister(instr.gpr8), src_thread_id)); + break; + } + case OpCode::Id::FSWZADD: { + UNIMPLEMENTED_IF(instr.fswzadd.ndv); + + Node op_a = GetRegister(instr.gpr8); + Node op_b = GetRegister(instr.gpr20); + Node mask = Immediate(static_cast<u32>(instr.fswzadd.swizzle)); + SetRegister(bb, instr.gpr0, Operation(OperationCode::FSwizzleAdd, op_a, op_b, mask)); break; } default: diff --git a/src/video_core/shader/node.h b/src/video_core/shader/node.h index 4300d9ff4..54217e6a4 100644 --- a/src/video_core/shader/node.h +++ b/src/video_core/shader/node.h @@ -47,6 +47,7 @@ enum class OperationCode { FTrunc, /// (MetaArithmetic, float a) -> float FCastInteger, /// (MetaArithmetic, int a) -> float FCastUInteger, /// (MetaArithmetic, uint a) -> float + FSwizzleAdd, /// (float a, float b, uint mask) -> float IAdd, /// (MetaArithmetic, int a, int b) -> int IMul, /// (MetaArithmetic, int a, int b) -> int @@ -181,15 +182,8 @@ enum class OperationCode { VoteAny, /// (bool) -> bool VoteEqual, /// (bool) -> bool - ShuffleIndexed, /// (uint value, uint index, uint width) -> uint - ShuffleUp, /// (uint value, uint index, uint width) -> uint - ShuffleDown, /// (uint value, uint index, uint width) -> uint - ShuffleButterfly, /// (uint value, uint index, uint width) -> uint - - InRangeShuffleIndexed, /// (uint index, uint width) -> bool - InRangeShuffleUp, /// (uint index, uint width) -> bool - InRangeShuffleDown, /// (uint index, uint width) -> bool - InRangeShuffleButterfly, /// (uint index, uint width) -> bool + ThreadId, /// () -> uint + ShuffleIndexed, /// (uint value, uint index) -> uint Amount, }; diff --git a/src/video_core/surface.cpp b/src/video_core/surface.cpp index 621136b6e..1655ccf16 100644 --- a/src/video_core/surface.cpp +++ b/src/video_core/surface.cpp @@ -168,309 +168,6 @@ PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format) } } -PixelFormat PixelFormatFromTextureFormat(Tegra::Texture::TextureFormat format, - Tegra::Texture::ComponentType component_type, - bool is_srgb) { - // TODO(Subv): Properly implement this - switch (format) { - case Tegra::Texture::TextureFormat::A8R8G8B8: - if (is_srgb) { - return PixelFormat::RGBA8_SRGB; - } - switch (component_type) { - case Tegra::Texture::ComponentType::UNORM: - return PixelFormat::ABGR8U; - case Tegra::Texture::ComponentType::SNORM: - return PixelFormat::ABGR8S; - case Tegra::Texture::ComponentType::UINT: - return PixelFormat::ABGR8UI; - default: - break; - } - break; - case Tegra::Texture::TextureFormat::B5G6R5: - switch (component_type) { - case Tegra::Texture::ComponentType::UNORM: - return PixelFormat::B5G6R5U; - default: - break; - } - break; - case Tegra::Texture::TextureFormat::A2B10G10R10: - switch (component_type) { - case Tegra::Texture::ComponentType::UNORM: - return PixelFormat::A2B10G10R10U; - default: - break; - } - break; - case Tegra::Texture::TextureFormat::A1B5G5R5: - switch (component_type) { - case Tegra::Texture::ComponentType::UNORM: - return PixelFormat::A1B5G5R5U; - default: - break; - } - break; - case Tegra::Texture::TextureFormat::A4B4G4R4: - switch (component_type) { - case Tegra::Texture::ComponentType::UNORM: - return PixelFormat::R4G4B4A4U; - default: - break; - } - break; - case Tegra::Texture::TextureFormat::R8: - switch (component_type) { - case Tegra::Texture::ComponentType::UNORM: - return PixelFormat::R8U; - case Tegra::Texture::ComponentType::UINT: - return PixelFormat::R8UI; - default: - break; - } - break; - case Tegra::Texture::TextureFormat::G8R8: - // TextureFormat::G8R8 is actually ordered red then green, as such we can use - // PixelFormat::RG8U and PixelFormat::RG8S. This was tested with The Legend of Zelda: Breath - // of the Wild, which uses this format to render the hearts on the UI. - switch (component_type) { - case Tegra::Texture::ComponentType::UNORM: - return PixelFormat::RG8U; - case Tegra::Texture::ComponentType::SNORM: - return PixelFormat::RG8S; - default: - break; - } - break; - case Tegra::Texture::TextureFormat::R16_G16_B16_A16: - switch (component_type) { - case Tegra::Texture::ComponentType::UNORM: - return PixelFormat::RGBA16U; - case Tegra::Texture::ComponentType::FLOAT: - return PixelFormat::RGBA16F; - default: - break; - } - break; - case Tegra::Texture::TextureFormat::BF10GF11RF11: - switch (component_type) { - case Tegra::Texture::ComponentType::FLOAT: - return PixelFormat::R11FG11FB10F; - default: - break; - } - break; - case Tegra::Texture::TextureFormat::R32_G32_B32_A32: - switch (component_type) { - case Tegra::Texture::ComponentType::FLOAT: - return PixelFormat::RGBA32F; - case Tegra::Texture::ComponentType::UINT: - return PixelFormat::RGBA32UI; - default: - break; - } - break; - case Tegra::Texture::TextureFormat::R32_G32: - switch (component_type) { - case Tegra::Texture::ComponentType::FLOAT: - return PixelFormat::RG32F; - case Tegra::Texture::ComponentType::UINT: - return PixelFormat::RG32UI; - default: - break; - } - break; - case Tegra::Texture::TextureFormat::R32_G32_B32: - switch (component_type) { - case Tegra::Texture::ComponentType::FLOAT: - return PixelFormat::RGB32F; - default: - break; - } - break; - case Tegra::Texture::TextureFormat::R16: - switch (component_type) { - case Tegra::Texture::ComponentType::FLOAT: - return PixelFormat::R16F; - case Tegra::Texture::ComponentType::UNORM: - return PixelFormat::R16U; - case Tegra::Texture::ComponentType::SNORM: - return PixelFormat::R16S; - case Tegra::Texture::ComponentType::UINT: - return PixelFormat::R16UI; - case Tegra::Texture::ComponentType::SINT: - return PixelFormat::R16I; - default: - break; - } - break; - case Tegra::Texture::TextureFormat::R32: - switch (component_type) { - case Tegra::Texture::ComponentType::FLOAT: - return PixelFormat::R32F; - case Tegra::Texture::ComponentType::UINT: - return PixelFormat::R32UI; - default: - break; - } - break; - case Tegra::Texture::TextureFormat::E5B9G9R9_SHAREDEXP: - switch (component_type) { - case Tegra::Texture::ComponentType::FLOAT: - return PixelFormat::E5B9G9R9F; - default: - break; - } - break; - case Tegra::Texture::TextureFormat::ZF32: - return PixelFormat::Z32F; - case Tegra::Texture::TextureFormat::Z16: - return PixelFormat::Z16; - case Tegra::Texture::TextureFormat::S8Z24: - return PixelFormat::S8Z24; - case Tegra::Texture::TextureFormat::ZF32_X24S8: - return PixelFormat::Z32FS8; - case Tegra::Texture::TextureFormat::DXT1: - return is_srgb ? PixelFormat::DXT1_SRGB : PixelFormat::DXT1; - case Tegra::Texture::TextureFormat::DXT23: - return is_srgb ? PixelFormat::DXT23_SRGB : PixelFormat::DXT23; - case Tegra::Texture::TextureFormat::DXT45: - return is_srgb ? PixelFormat::DXT45_SRGB : PixelFormat::DXT45; - case Tegra::Texture::TextureFormat::DXN1: - return PixelFormat::DXN1; - case Tegra::Texture::TextureFormat::DXN2: - switch (component_type) { - case Tegra::Texture::ComponentType::UNORM: - return PixelFormat::DXN2UNORM; - case Tegra::Texture::ComponentType::SNORM: - return PixelFormat::DXN2SNORM; - default: - break; - } - break; - case Tegra::Texture::TextureFormat::BC7U: - return is_srgb ? PixelFormat::BC7U_SRGB : PixelFormat::BC7U; - case Tegra::Texture::TextureFormat::BC6H_UF16: - return PixelFormat::BC6H_UF16; - case Tegra::Texture::TextureFormat::BC6H_SF16: - return PixelFormat::BC6H_SF16; - case Tegra::Texture::TextureFormat::ASTC_2D_4X4: - return is_srgb ? PixelFormat::ASTC_2D_4X4_SRGB : PixelFormat::ASTC_2D_4X4; - case Tegra::Texture::TextureFormat::ASTC_2D_5X4: - return is_srgb ? PixelFormat::ASTC_2D_5X4_SRGB : PixelFormat::ASTC_2D_5X4; - case Tegra::Texture::TextureFormat::ASTC_2D_5X5: - return is_srgb ? PixelFormat::ASTC_2D_5X5_SRGB : PixelFormat::ASTC_2D_5X5; - case Tegra::Texture::TextureFormat::ASTC_2D_8X8: - return is_srgb ? PixelFormat::ASTC_2D_8X8_SRGB : PixelFormat::ASTC_2D_8X8; - case Tegra::Texture::TextureFormat::ASTC_2D_8X5: - return is_srgb ? PixelFormat::ASTC_2D_8X5_SRGB : PixelFormat::ASTC_2D_8X5; - case Tegra::Texture::TextureFormat::ASTC_2D_10X8: - return is_srgb ? PixelFormat::ASTC_2D_10X8_SRGB : PixelFormat::ASTC_2D_10X8; - case Tegra::Texture::TextureFormat::ASTC_2D_6X6: - return is_srgb ? PixelFormat::ASTC_2D_6X6_SRGB : PixelFormat::ASTC_2D_6X6; - case Tegra::Texture::TextureFormat::ASTC_2D_10X10: - return is_srgb ? PixelFormat::ASTC_2D_10X10_SRGB : PixelFormat::ASTC_2D_10X10; - case Tegra::Texture::TextureFormat::ASTC_2D_12X12: - return is_srgb ? PixelFormat::ASTC_2D_12X12_SRGB : PixelFormat::ASTC_2D_12X12; - case Tegra::Texture::TextureFormat::ASTC_2D_8X6: - return is_srgb ? PixelFormat::ASTC_2D_8X6_SRGB : PixelFormat::ASTC_2D_8X6; - case Tegra::Texture::TextureFormat::ASTC_2D_6X5: - return is_srgb ? PixelFormat::ASTC_2D_6X5_SRGB : PixelFormat::ASTC_2D_6X5; - case Tegra::Texture::TextureFormat::R16_G16: - switch (component_type) { - case Tegra::Texture::ComponentType::FLOAT: - return PixelFormat::RG16F; - case Tegra::Texture::ComponentType::UNORM: - return PixelFormat::RG16; - case Tegra::Texture::ComponentType::SNORM: - return PixelFormat::RG16S; - case Tegra::Texture::ComponentType::UINT: - return PixelFormat::RG16UI; - case Tegra::Texture::ComponentType::SINT: - return PixelFormat::RG16I; - default: - break; - } - break; - default: - break; - } - LOG_CRITICAL(HW_GPU, "Unimplemented format={}, component_type={}", static_cast<u32>(format), - static_cast<u32>(component_type)); - UNREACHABLE(); - return PixelFormat::ABGR8U; -} - -ComponentType ComponentTypeFromTexture(Tegra::Texture::ComponentType type) { - // TODO(Subv): Implement more component types - switch (type) { - case Tegra::Texture::ComponentType::UNORM: - return ComponentType::UNorm; - case Tegra::Texture::ComponentType::FLOAT: - return ComponentType::Float; - case Tegra::Texture::ComponentType::SNORM: - return ComponentType::SNorm; - case Tegra::Texture::ComponentType::UINT: - return ComponentType::UInt; - case Tegra::Texture::ComponentType::SINT: - return ComponentType::SInt; - default: - LOG_CRITICAL(HW_GPU, "Unimplemented component type={}", static_cast<u32>(type)); - UNREACHABLE(); - return ComponentType::UNorm; - } -} - -ComponentType ComponentTypeFromRenderTarget(Tegra::RenderTargetFormat format) { - // TODO(Subv): Implement more render targets - switch (format) { - case Tegra::RenderTargetFormat::RGBA8_UNORM: - case Tegra::RenderTargetFormat::RGBA8_SRGB: - case Tegra::RenderTargetFormat::BGRA8_UNORM: - case Tegra::RenderTargetFormat::BGRA8_SRGB: - case Tegra::RenderTargetFormat::RGB10_A2_UNORM: - case Tegra::RenderTargetFormat::R8_UNORM: - case Tegra::RenderTargetFormat::RG16_UNORM: - case Tegra::RenderTargetFormat::R16_UNORM: - case Tegra::RenderTargetFormat::B5G6R5_UNORM: - case Tegra::RenderTargetFormat::BGR5A1_UNORM: - case Tegra::RenderTargetFormat::RG8_UNORM: - case Tegra::RenderTargetFormat::RGBA16_UNORM: - return ComponentType::UNorm; - case Tegra::RenderTargetFormat::RGBA8_SNORM: - case Tegra::RenderTargetFormat::RG16_SNORM: - case Tegra::RenderTargetFormat::R16_SNORM: - case Tegra::RenderTargetFormat::RG8_SNORM: - return ComponentType::SNorm; - case Tegra::RenderTargetFormat::RGBA16_FLOAT: - case Tegra::RenderTargetFormat::RGBX16_FLOAT: - case Tegra::RenderTargetFormat::R11G11B10_FLOAT: - case Tegra::RenderTargetFormat::RGBA32_FLOAT: - case Tegra::RenderTargetFormat::RG32_FLOAT: - case Tegra::RenderTargetFormat::RG16_FLOAT: - case Tegra::RenderTargetFormat::R16_FLOAT: - case Tegra::RenderTargetFormat::R32_FLOAT: - return ComponentType::Float; - case Tegra::RenderTargetFormat::RGBA32_UINT: - case Tegra::RenderTargetFormat::RGBA16_UINT: - case Tegra::RenderTargetFormat::RG16_UINT: - case Tegra::RenderTargetFormat::R8_UINT: - case Tegra::RenderTargetFormat::R16_UINT: - case Tegra::RenderTargetFormat::RG32_UINT: - case Tegra::RenderTargetFormat::R32_UINT: - case Tegra::RenderTargetFormat::RGBA8_UINT: - return ComponentType::UInt; - case Tegra::RenderTargetFormat::RG16_SINT: - case Tegra::RenderTargetFormat::R16_SINT: - return ComponentType::SInt; - default: - LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); - UNREACHABLE(); - return ComponentType::UNorm; - } -} - PixelFormat PixelFormatFromGPUPixelFormat(Tegra::FramebufferConfig::PixelFormat format) { switch (format) { case Tegra::FramebufferConfig::PixelFormat::ABGR8: @@ -485,22 +182,6 @@ PixelFormat PixelFormatFromGPUPixelFormat(Tegra::FramebufferConfig::PixelFormat } } -ComponentType ComponentTypeFromDepthFormat(Tegra::DepthFormat format) { - switch (format) { - case Tegra::DepthFormat::Z16_UNORM: - case Tegra::DepthFormat::S8_Z24_UNORM: - case Tegra::DepthFormat::Z24_S8_UNORM: - return ComponentType::UNorm; - case Tegra::DepthFormat::Z32_FLOAT: - case Tegra::DepthFormat::Z32_S8_X24_FLOAT: - return ComponentType::Float; - default: - LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); - UNREACHABLE(); - return ComponentType::UNorm; - } -} - SurfaceType GetFormatType(PixelFormat pixel_format) { if (static_cast<std::size_t>(pixel_format) < static_cast<std::size_t>(PixelFormat::MaxColorFormat)) { diff --git a/src/video_core/surface.h b/src/video_core/surface.h index d3bcd38c5..0d17a93ed 100644 --- a/src/video_core/surface.h +++ b/src/video_core/surface.h @@ -106,18 +106,8 @@ enum class PixelFormat { Max = MaxDepthStencilFormat, Invalid = 255, }; - static constexpr std::size_t MaxPixelFormat = static_cast<std::size_t>(PixelFormat::Max); -enum class ComponentType { - Invalid = 0, - SNorm = 1, - UNorm = 2, - SInt = 3, - UInt = 4, - Float = 5, -}; - enum class SurfaceType { ColorTexture = 0, Depth = 1, @@ -609,18 +599,8 @@ PixelFormat PixelFormatFromDepthFormat(Tegra::DepthFormat format); PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format); -PixelFormat PixelFormatFromTextureFormat(Tegra::Texture::TextureFormat format, - Tegra::Texture::ComponentType component_type, - bool is_srgb); - -ComponentType ComponentTypeFromTexture(Tegra::Texture::ComponentType type); - -ComponentType ComponentTypeFromRenderTarget(Tegra::RenderTargetFormat format); - PixelFormat PixelFormatFromGPUPixelFormat(Tegra::FramebufferConfig::PixelFormat format); -ComponentType ComponentTypeFromDepthFormat(Tegra::DepthFormat format); - SurfaceType GetFormatType(PixelFormat pixel_format); bool IsPixelFormatASTC(PixelFormat format); diff --git a/src/video_core/texture_cache/format_lookup_table.cpp b/src/video_core/texture_cache/format_lookup_table.cpp new file mode 100644 index 000000000..271e67533 --- /dev/null +++ b/src/video_core/texture_cache/format_lookup_table.cpp @@ -0,0 +1,208 @@ +// Copyright 2019 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include <array> +#include "common/common_types.h" +#include "common/logging/log.h" +#include "video_core/texture_cache/format_lookup_table.h" + +namespace VideoCommon { + +using Tegra::Texture::ComponentType; +using Tegra::Texture::TextureFormat; +using VideoCore::Surface::PixelFormat; + +namespace { + +constexpr auto SNORM = ComponentType::SNORM; +constexpr auto UNORM = ComponentType::UNORM; +constexpr auto SINT = ComponentType::SINT; +constexpr auto UINT = ComponentType::UINT; +constexpr auto SNORM_FORCE_FP16 = ComponentType::SNORM_FORCE_FP16; +constexpr auto UNORM_FORCE_FP16 = ComponentType::UNORM_FORCE_FP16; +constexpr auto FLOAT = ComponentType::FLOAT; +constexpr bool C = false; // Normal color +constexpr bool S = true; // Srgb + +struct Table { + constexpr Table(TextureFormat texture_format, bool is_srgb, ComponentType red_component, + ComponentType green_component, ComponentType blue_component, + ComponentType alpha_component, PixelFormat pixel_format) + : texture_format{texture_format}, pixel_format{pixel_format}, red_component{red_component}, + green_component{green_component}, blue_component{blue_component}, + alpha_component{alpha_component}, is_srgb{is_srgb} {} + + TextureFormat texture_format; + PixelFormat pixel_format; + ComponentType red_component; + ComponentType green_component; + ComponentType blue_component; + ComponentType alpha_component; + bool is_srgb; +}; +constexpr std::array<Table, 74> DefinitionTable = {{ + {TextureFormat::A8R8G8B8, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ABGR8U}, + {TextureFormat::A8R8G8B8, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::ABGR8S}, + {TextureFormat::A8R8G8B8, C, UINT, UINT, UINT, UINT, PixelFormat::ABGR8UI}, + {TextureFormat::A8R8G8B8, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::RGBA8_SRGB}, + + {TextureFormat::B5G6R5, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::B5G6R5U}, + + {TextureFormat::A2B10G10R10, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::A2B10G10R10U}, + + {TextureFormat::A1B5G5R5, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::A1B5G5R5U}, + + {TextureFormat::A4B4G4R4, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::R4G4B4A4U}, + + {TextureFormat::R8, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::R8U}, + {TextureFormat::R8, C, UINT, UINT, UINT, UINT, PixelFormat::R8UI}, + + {TextureFormat::G8R8, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::RG8U}, + {TextureFormat::G8R8, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::RG8S}, + + {TextureFormat::R16_G16_B16_A16, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::RGBA16U}, + {TextureFormat::R16_G16_B16_A16, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::RGBA16F}, + {TextureFormat::R16_G16_B16_A16, C, UINT, UINT, UINT, UINT, PixelFormat::RGBA16UI}, + + {TextureFormat::R16_G16, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::RG16F}, + {TextureFormat::R16_G16, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::RG16}, + {TextureFormat::R16_G16, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::RG16S}, + {TextureFormat::R16_G16, C, UINT, UINT, UINT, UINT, PixelFormat::RG16UI}, + {TextureFormat::R16_G16, C, SINT, SINT, SINT, SINT, PixelFormat::RG16I}, + + {TextureFormat::R16, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::R16F}, + {TextureFormat::R16, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::R16U}, + {TextureFormat::R16, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::R16S}, + {TextureFormat::R16, C, UINT, UINT, UINT, UINT, PixelFormat::R16UI}, + {TextureFormat::R16, C, SINT, SINT, SINT, SINT, PixelFormat::R16I}, + + {TextureFormat::BF10GF11RF11, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::R11FG11FB10F}, + + {TextureFormat::R32_G32_B32_A32, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::RGBA32F}, + {TextureFormat::R32_G32_B32_A32, C, UINT, UINT, UINT, UINT, PixelFormat::RGBA32UI}, + + {TextureFormat::R32_G32_B32, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::RGB32F}, + + {TextureFormat::R32_G32, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::RG32F}, + {TextureFormat::R32_G32, C, UINT, UINT, UINT, UINT, PixelFormat::RG32UI}, + + {TextureFormat::R32, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::R32F}, + {TextureFormat::R32, C, UINT, UINT, UINT, UINT, PixelFormat::R32UI}, + + {TextureFormat::E5B9G9R9_SHAREDEXP, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::E5B9G9R9F}, + + {TextureFormat::ZF32, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::Z32F}, + {TextureFormat::Z16, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::Z16}, + {TextureFormat::S8Z24, C, UINT, UNORM, UNORM, UNORM, PixelFormat::S8Z24}, + {TextureFormat::ZF32_X24S8, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::Z32FS8}, + + {TextureFormat::DXT1, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::DXT1}, + {TextureFormat::DXT1, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::DXT1_SRGB}, + + {TextureFormat::DXT23, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::DXT23}, + {TextureFormat::DXT23, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::DXT23_SRGB}, + + {TextureFormat::DXT45, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::DXT45}, + {TextureFormat::DXT45, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::DXT45_SRGB}, + + // TODO: Use a different pixel format for SNORM + {TextureFormat::DXN1, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::DXN1}, + {TextureFormat::DXN1, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::DXN1}, + + {TextureFormat::DXN2, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::DXN2UNORM}, + {TextureFormat::DXN2, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::DXN2SNORM}, + + {TextureFormat::BC7U, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::BC7U}, + {TextureFormat::BC7U, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::BC7U_SRGB}, + + {TextureFormat::BC6H_SF16, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::BC6H_SF16}, + {TextureFormat::BC6H_UF16, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::BC6H_UF16}, + + {TextureFormat::ASTC_2D_4X4, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_4X4}, + {TextureFormat::ASTC_2D_4X4, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_4X4_SRGB}, + + {TextureFormat::ASTC_2D_5X4, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_5X4}, + {TextureFormat::ASTC_2D_5X4, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_5X4_SRGB}, + + {TextureFormat::ASTC_2D_5X5, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_5X5}, + {TextureFormat::ASTC_2D_5X5, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_5X5_SRGB}, + + {TextureFormat::ASTC_2D_8X8, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X8}, + {TextureFormat::ASTC_2D_8X8, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X8_SRGB}, + + {TextureFormat::ASTC_2D_8X5, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X5}, + {TextureFormat::ASTC_2D_8X5, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X5_SRGB}, + + {TextureFormat::ASTC_2D_10X8, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_10X8}, + {TextureFormat::ASTC_2D_10X8, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_10X8_SRGB}, + + {TextureFormat::ASTC_2D_6X6, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_6X6}, + {TextureFormat::ASTC_2D_6X6, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_6X6_SRGB}, + + {TextureFormat::ASTC_2D_10X10, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_10X10}, + {TextureFormat::ASTC_2D_10X10, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_10X10_SRGB}, + + {TextureFormat::ASTC_2D_12X12, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_12X12}, + {TextureFormat::ASTC_2D_12X12, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_12X12_SRGB}, + + {TextureFormat::ASTC_2D_8X6, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X6}, + {TextureFormat::ASTC_2D_8X6, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X6_SRGB}, + + {TextureFormat::ASTC_2D_6X5, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_6X5}, + {TextureFormat::ASTC_2D_6X5, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_6X5_SRGB}, +}}; + +} // Anonymous namespace + +FormatLookupTable::FormatLookupTable() { + table.fill(static_cast<u8>(PixelFormat::Invalid)); + + for (const auto& entry : DefinitionTable) { + table[CalculateIndex(entry.texture_format, entry.is_srgb != 0, entry.red_component, + entry.green_component, entry.blue_component, entry.alpha_component)] = + static_cast<u8>(entry.pixel_format); + } +} + +PixelFormat FormatLookupTable::GetPixelFormat(TextureFormat format, bool is_srgb, + ComponentType red_component, + ComponentType green_component, + ComponentType blue_component, + ComponentType alpha_component) const noexcept { + const auto pixel_format = static_cast<PixelFormat>(table[CalculateIndex( + format, is_srgb, red_component, green_component, blue_component, alpha_component)]); + // [[likely]] + if (pixel_format != PixelFormat::Invalid) { + return pixel_format; + } + UNIMPLEMENTED_MSG("texture format={} srgb={} components={{{} {} {} {}}}", + static_cast<int>(format), is_srgb, static_cast<int>(red_component), + static_cast<int>(green_component), static_cast<int>(blue_component), + static_cast<int>(alpha_component)); + return PixelFormat::ABGR8U; +} + +void FormatLookupTable::Set(TextureFormat format, bool is_srgb, ComponentType red_component, + ComponentType green_component, ComponentType blue_component, + ComponentType alpha_component, PixelFormat pixel_format) {} + +std::size_t FormatLookupTable::CalculateIndex(TextureFormat format, bool is_srgb, + ComponentType red_component, + ComponentType green_component, + ComponentType blue_component, + ComponentType alpha_component) noexcept { + const auto format_index = static_cast<std::size_t>(format); + const auto red_index = static_cast<std::size_t>(red_component); + const auto green_index = static_cast<std::size_t>(red_component); + const auto blue_index = static_cast<std::size_t>(red_component); + const auto alpha_index = static_cast<std::size_t>(red_component); + const std::size_t srgb_index = is_srgb ? 1 : 0; + + return format_index * PerFormat + + srgb_index * PerComponent * PerComponent * PerComponent * PerComponent + + alpha_index * PerComponent * PerComponent * PerComponent + + blue_index * PerComponent * PerComponent + green_index * PerComponent + red_index; +} + +} // namespace VideoCommon diff --git a/src/video_core/texture_cache/format_lookup_table.h b/src/video_core/texture_cache/format_lookup_table.h new file mode 100644 index 000000000..aa77e0a5a --- /dev/null +++ b/src/video_core/texture_cache/format_lookup_table.h @@ -0,0 +1,51 @@ +// Copyright 2019 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <array> +#include <limits> +#include "video_core/surface.h" +#include "video_core/textures/texture.h" + +namespace VideoCommon { + +class FormatLookupTable { +public: + explicit FormatLookupTable(); + + VideoCore::Surface::PixelFormat GetPixelFormat( + Tegra::Texture::TextureFormat format, bool is_srgb, + Tegra::Texture::ComponentType red_component, Tegra::Texture::ComponentType green_component, + Tegra::Texture::ComponentType blue_component, + Tegra::Texture::ComponentType alpha_component) const noexcept; + +private: + static_assert(VideoCore::Surface::MaxPixelFormat <= std::numeric_limits<u8>::max()); + + static constexpr std::size_t NumTextureFormats = 128; + + static constexpr std::size_t PerComponent = 8; + static constexpr std::size_t PerComponents2 = PerComponent * PerComponent; + static constexpr std::size_t PerComponents3 = PerComponents2 * PerComponent; + static constexpr std::size_t PerComponents4 = PerComponents3 * PerComponent; + static constexpr std::size_t PerFormat = PerComponents4 * 2; + + static std::size_t CalculateIndex(Tegra::Texture::TextureFormat format, bool is_srgb, + Tegra::Texture::ComponentType red_component, + Tegra::Texture::ComponentType green_component, + Tegra::Texture::ComponentType blue_component, + Tegra::Texture::ComponentType alpha_component) noexcept; + + void Set(Tegra::Texture::TextureFormat format, bool is_srgb, + Tegra::Texture::ComponentType red_component, + Tegra::Texture::ComponentType green_component, + Tegra::Texture::ComponentType blue_component, + Tegra::Texture::ComponentType alpha_component, + VideoCore::Surface::PixelFormat pixel_format); + + std::array<u8, NumTextureFormats * PerFormat> table; +}; + +} // namespace VideoCommon diff --git a/src/video_core/texture_cache/surface_params.cpp b/src/video_core/texture_cache/surface_params.cpp index 1e4d3fb79..858e17e08 100644 --- a/src/video_core/texture_cache/surface_params.cpp +++ b/src/video_core/texture_cache/surface_params.cpp @@ -2,24 +2,23 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include <map> +#include <algorithm> +#include <string> +#include <tuple> #include "common/alignment.h" #include "common/bit_util.h" #include "core/core.h" #include "video_core/engines/shader_bytecode.h" #include "video_core/surface.h" +#include "video_core/texture_cache/format_lookup_table.h" #include "video_core/texture_cache/surface_params.h" namespace VideoCommon { -using VideoCore::Surface::ComponentTypeFromDepthFormat; -using VideoCore::Surface::ComponentTypeFromRenderTarget; -using VideoCore::Surface::ComponentTypeFromTexture; using VideoCore::Surface::PixelFormat; using VideoCore::Surface::PixelFormatFromDepthFormat; using VideoCore::Surface::PixelFormatFromRenderTargetFormat; -using VideoCore::Surface::PixelFormatFromTextureFormat; using VideoCore::Surface::SurfaceTarget; using VideoCore::Surface::SurfaceTargetFromTextureType; using VideoCore::Surface::SurfaceType; @@ -69,7 +68,8 @@ constexpr u32 GetMipmapSize(bool uncompressed, u32 mip_size, u32 tile) { } // Anonymous namespace -SurfaceParams SurfaceParams::CreateForTexture(const Tegra::Texture::TICEntry& tic, +SurfaceParams SurfaceParams::CreateForTexture(const FormatLookupTable& lookup_table, + const Tegra::Texture::TICEntry& tic, const VideoCommon::Shader::Sampler& entry) { SurfaceParams params; params.is_tiled = tic.IsTiled(); @@ -78,8 +78,8 @@ SurfaceParams SurfaceParams::CreateForTexture(const Tegra::Texture::TICEntry& ti params.block_height = params.is_tiled ? tic.BlockHeight() : 0, params.block_depth = params.is_tiled ? tic.BlockDepth() : 0, params.tile_width_spacing = params.is_tiled ? (1 << tic.tile_width_spacing.Value()) : 1; - params.pixel_format = - PixelFormatFromTextureFormat(tic.format, tic.r_type.Value(), params.srgb_conversion); + params.pixel_format = lookup_table.GetPixelFormat( + tic.format, params.srgb_conversion, tic.r_type, tic.g_type, tic.b_type, tic.a_type); params.type = GetFormatType(params.pixel_format); if (entry.IsShadow() && params.type == SurfaceType::ColorTexture) { switch (params.pixel_format) { @@ -99,7 +99,6 @@ SurfaceParams SurfaceParams::CreateForTexture(const Tegra::Texture::TICEntry& ti } params.type = GetFormatType(params.pixel_format); } - params.component_type = ComponentTypeFromTexture(tic.r_type.Value()); params.type = GetFormatType(params.pixel_format); // TODO: on 1DBuffer we should use the tic info. if (tic.IsBuffer()) { @@ -128,7 +127,8 @@ SurfaceParams SurfaceParams::CreateForTexture(const Tegra::Texture::TICEntry& ti return params; } -SurfaceParams SurfaceParams::CreateForImage(const Tegra::Texture::TICEntry& tic, +SurfaceParams SurfaceParams::CreateForImage(const FormatLookupTable& lookup_table, + const Tegra::Texture::TICEntry& tic, const VideoCommon::Shader::Image& entry) { SurfaceParams params; params.is_tiled = tic.IsTiled(); @@ -137,10 +137,9 @@ SurfaceParams SurfaceParams::CreateForImage(const Tegra::Texture::TICEntry& tic, params.block_height = params.is_tiled ? tic.BlockHeight() : 0, params.block_depth = params.is_tiled ? tic.BlockDepth() : 0, params.tile_width_spacing = params.is_tiled ? (1 << tic.tile_width_spacing.Value()) : 1; - params.pixel_format = - PixelFormatFromTextureFormat(tic.format, tic.r_type.Value(), params.srgb_conversion); + params.pixel_format = lookup_table.GetPixelFormat( + tic.format, params.srgb_conversion, tic.r_type, tic.g_type, tic.b_type, tic.a_type); params.type = GetFormatType(params.pixel_format); - params.component_type = ComponentTypeFromTexture(tic.r_type.Value()); params.type = GetFormatType(params.pixel_format); params.target = ImageTypeToSurfaceTarget(entry.GetType()); // TODO: on 1DBuffer we should use the tic info. @@ -181,7 +180,6 @@ SurfaceParams SurfaceParams::CreateForDepthBuffer( params.block_depth = std::min(block_depth, 5U); params.tile_width_spacing = 1; params.pixel_format = PixelFormatFromDepthFormat(format); - params.component_type = ComponentTypeFromDepthFormat(format); params.type = GetFormatType(params.pixel_format); params.width = zeta_width; params.height = zeta_height; @@ -206,7 +204,6 @@ SurfaceParams SurfaceParams::CreateForFramebuffer(Core::System& system, std::siz params.block_depth = config.memory_layout.block_depth; params.tile_width_spacing = 1; params.pixel_format = PixelFormatFromRenderTargetFormat(config.format); - params.component_type = ComponentTypeFromRenderTarget(config.format); params.type = GetFormatType(params.pixel_format); if (params.is_tiled) { params.pitch = 0; @@ -236,7 +233,6 @@ SurfaceParams SurfaceParams::CreateForFermiCopySurface( params.block_depth = params.is_tiled ? std::min(config.BlockDepth(), 5U) : 0, params.tile_width_spacing = 1; params.pixel_format = PixelFormatFromRenderTargetFormat(config.format); - params.component_type = ComponentTypeFromRenderTarget(config.format); params.type = GetFormatType(params.pixel_format); params.width = config.width; params.height = config.height; @@ -355,10 +351,10 @@ std::size_t SurfaceParams::GetInnerMipmapMemorySize(u32 level, bool as_host_size bool SurfaceParams::operator==(const SurfaceParams& rhs) const { return std::tie(is_tiled, block_width, block_height, block_depth, tile_width_spacing, width, - height, depth, pitch, num_levels, pixel_format, component_type, type, target) == + height, depth, pitch, num_levels, pixel_format, type, target) == std::tie(rhs.is_tiled, rhs.block_width, rhs.block_height, rhs.block_depth, rhs.tile_width_spacing, rhs.width, rhs.height, rhs.depth, rhs.pitch, - rhs.num_levels, rhs.pixel_format, rhs.component_type, rhs.type, rhs.target); + rhs.num_levels, rhs.pixel_format, rhs.type, rhs.target); } std::string SurfaceParams::TargetName() const { diff --git a/src/video_core/texture_cache/surface_params.h b/src/video_core/texture_cache/surface_params.h index c58e7f8a4..709aa0dc2 100644 --- a/src/video_core/texture_cache/surface_params.h +++ b/src/video_core/texture_cache/surface_params.h @@ -16,16 +16,20 @@ namespace VideoCommon { +class FormatLookupTable; + using VideoCore::Surface::SurfaceCompression; class SurfaceParams { public: /// Creates SurfaceCachedParams from a texture configuration. - static SurfaceParams CreateForTexture(const Tegra::Texture::TICEntry& tic, + static SurfaceParams CreateForTexture(const FormatLookupTable& lookup_table, + const Tegra::Texture::TICEntry& tic, const VideoCommon::Shader::Sampler& entry); /// Creates SurfaceCachedParams from an image configuration. - static SurfaceParams CreateForImage(const Tegra::Texture::TICEntry& tic, + static SurfaceParams CreateForImage(const FormatLookupTable& lookup_table, + const Tegra::Texture::TICEntry& tic, const VideoCommon::Shader::Image& entry); /// Creates SurfaceCachedParams for a depth buffer configuration. @@ -248,7 +252,6 @@ public: u32 num_levels; u32 emulated_levels; VideoCore::Surface::PixelFormat pixel_format; - VideoCore::Surface::ComponentType component_type; VideoCore::Surface::SurfaceType type; VideoCore::Surface::SurfaceTarget target; diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 6a92b22d3..41309ebea 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -29,6 +29,7 @@ #include "video_core/rasterizer_interface.h" #include "video_core/surface.h" #include "video_core/texture_cache/copy_params.h" +#include "video_core/texture_cache/format_lookup_table.h" #include "video_core/texture_cache/surface_base.h" #include "video_core/texture_cache/surface_params.h" #include "video_core/texture_cache/surface_view.h" @@ -96,7 +97,7 @@ public: if (!gpu_addr) { return {}; } - const auto params{SurfaceParams::CreateForTexture(tic, entry)}; + const auto params{SurfaceParams::CreateForTexture(format_lookup_table, tic, entry)}; const auto [surface, view] = GetSurface(gpu_addr, params, true, false); if (guard_samplers) { sampled_textures.push_back(surface); @@ -111,7 +112,7 @@ public: if (!gpu_addr) { return {}; } - const auto params{SurfaceParams::CreateForImage(tic, entry)}; + const auto params{SurfaceParams::CreateForImage(format_lookup_table, tic, entry)}; const auto [surface, view] = GetSurface(gpu_addr, params, true, false); if (guard_samplers) { sampled_textures.push_back(surface); @@ -485,15 +486,13 @@ private: GetSiblingFormat(cr_params.pixel_format) == params.pixel_format) { SurfaceParams new_params = params; new_params.pixel_format = cr_params.pixel_format; - new_params.component_type = cr_params.component_type; new_params.type = cr_params.type; new_surface = GetUncachedSurface(gpu_addr, new_params); } else { new_surface = GetUncachedSurface(gpu_addr, params); } const auto& final_params = new_surface->GetSurfaceParams(); - if (cr_params.type != final_params.type || - (cr_params.component_type != final_params.component_type)) { + if (cr_params.type != final_params.type) { BufferCopy(current_surface, new_surface); } else { std::vector<CopyParams> bricks = current_surface->BreakDown(final_params); @@ -835,12 +834,11 @@ private: } } - const auto inherit_format = ([](SurfaceParams& to, TSurface from) { + const auto inherit_format = [](SurfaceParams& to, TSurface from) { const SurfaceParams& params = from->GetSurfaceParams(); to.pixel_format = params.pixel_format; - to.component_type = params.component_type; to.type = params.type; - }); + }; // Now we got the cases where one or both is Depth and the other is not known if (!incomplete_src) { inherit_format(src_params, deduced_src.surface); @@ -956,6 +954,8 @@ private: VideoCore::RasterizerInterface& rasterizer; + FormatLookupTable format_lookup_table; + u64 ticks{}; // Guards the cache for protection conflicts. |