video_core: Unify ProgramType and ShaderStage into ShaderType
This commit is contained in:
parent
0f23359a44
commit
c8a48aacc0
22 changed files with 260 additions and 287 deletions
|
@ -22,6 +22,7 @@ add_library(video_core STATIC
|
||||||
engines/maxwell_dma.h
|
engines/maxwell_dma.h
|
||||||
engines/shader_bytecode.h
|
engines/shader_bytecode.h
|
||||||
engines/shader_header.h
|
engines/shader_header.h
|
||||||
|
engines/shader_type.h
|
||||||
gpu.cpp
|
gpu.cpp
|
||||||
gpu.h
|
gpu.h
|
||||||
gpu_asynch.cpp
|
gpu_asynch.cpp
|
||||||
|
|
|
@ -8,19 +8,11 @@
|
||||||
#include "common/bit_field.h"
|
#include "common/bit_field.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "video_core/engines/shader_bytecode.h"
|
#include "video_core/engines/shader_bytecode.h"
|
||||||
|
#include "video_core/engines/shader_type.h"
|
||||||
#include "video_core/textures/texture.h"
|
#include "video_core/textures/texture.h"
|
||||||
|
|
||||||
namespace Tegra::Engines {
|
namespace Tegra::Engines {
|
||||||
|
|
||||||
enum class ShaderType : u32 {
|
|
||||||
Vertex = 0,
|
|
||||||
TesselationControl = 1,
|
|
||||||
TesselationEval = 2,
|
|
||||||
Geometry = 3,
|
|
||||||
Fragment = 4,
|
|
||||||
Compute = 5,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SamplerDescriptor {
|
struct SamplerDescriptor {
|
||||||
union {
|
union {
|
||||||
BitField<0, 20, Tegra::Shader::TextureType> texture_type;
|
BitField<0, 20, Tegra::Shader::TextureType> texture_type;
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "video_core/engines/kepler_compute.h"
|
#include "video_core/engines/kepler_compute.h"
|
||||||
#include "video_core/engines/maxwell_3d.h"
|
#include "video_core/engines/maxwell_3d.h"
|
||||||
|
#include "video_core/engines/shader_type.h"
|
||||||
#include "video_core/memory_manager.h"
|
#include "video_core/memory_manager.h"
|
||||||
#include "video_core/rasterizer_interface.h"
|
#include "video_core/rasterizer_interface.h"
|
||||||
#include "video_core/renderer_base.h"
|
#include "video_core/renderer_base.h"
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "video_core/engines/const_buffer_engine_interface.h"
|
#include "video_core/engines/const_buffer_engine_interface.h"
|
||||||
#include "video_core/engines/engine_upload.h"
|
#include "video_core/engines/engine_upload.h"
|
||||||
|
#include "video_core/engines/shader_type.h"
|
||||||
#include "video_core/gpu.h"
|
#include "video_core/gpu.h"
|
||||||
#include "video_core/textures/texture.h"
|
#include "video_core/textures/texture.h"
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "core/core_timing.h"
|
#include "core/core_timing.h"
|
||||||
#include "video_core/debug_utils/debug_utils.h"
|
#include "video_core/debug_utils/debug_utils.h"
|
||||||
#include "video_core/engines/maxwell_3d.h"
|
#include "video_core/engines/maxwell_3d.h"
|
||||||
|
#include "video_core/engines/shader_type.h"
|
||||||
#include "video_core/memory_manager.h"
|
#include "video_core/memory_manager.h"
|
||||||
#include "video_core/rasterizer_interface.h"
|
#include "video_core/rasterizer_interface.h"
|
||||||
#include "video_core/textures/texture.h"
|
#include "video_core/textures/texture.h"
|
||||||
|
@ -368,24 +369,24 @@ void Maxwell3D::CallMethod(const GPU::MethodCall& method_call) {
|
||||||
StartCBData(method);
|
StartCBData(method);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MAXWELL3D_REG_INDEX(cb_bind[0].raw_config): {
|
case MAXWELL3D_REG_INDEX(cb_bind[0]): {
|
||||||
ProcessCBBind(Regs::ShaderStage::Vertex);
|
ProcessCBBind(0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MAXWELL3D_REG_INDEX(cb_bind[1].raw_config): {
|
case MAXWELL3D_REG_INDEX(cb_bind[1]): {
|
||||||
ProcessCBBind(Regs::ShaderStage::TesselationControl);
|
ProcessCBBind(1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MAXWELL3D_REG_INDEX(cb_bind[2].raw_config): {
|
case MAXWELL3D_REG_INDEX(cb_bind[2]): {
|
||||||
ProcessCBBind(Regs::ShaderStage::TesselationEval);
|
ProcessCBBind(2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MAXWELL3D_REG_INDEX(cb_bind[3].raw_config): {
|
case MAXWELL3D_REG_INDEX(cb_bind[3]): {
|
||||||
ProcessCBBind(Regs::ShaderStage::Geometry);
|
ProcessCBBind(3);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MAXWELL3D_REG_INDEX(cb_bind[4].raw_config): {
|
case MAXWELL3D_REG_INDEX(cb_bind[4]): {
|
||||||
ProcessCBBind(Regs::ShaderStage::Fragment);
|
ProcessCBBind(4);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MAXWELL3D_REG_INDEX(draw.vertex_end_gl): {
|
case MAXWELL3D_REG_INDEX(draw.vertex_end_gl): {
|
||||||
|
@ -687,10 +688,10 @@ void Maxwell3D::DrawArrays() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Maxwell3D::ProcessCBBind(Regs::ShaderStage stage) {
|
void Maxwell3D::ProcessCBBind(std::size_t stage_index) {
|
||||||
// Bind the buffer currently in CB_ADDRESS to the specified index in the desired shader stage.
|
// Bind the buffer currently in CB_ADDRESS to the specified index in the desired shader stage.
|
||||||
auto& shader = state.shader_stages[static_cast<std::size_t>(stage)];
|
auto& shader = state.shader_stages[stage_index];
|
||||||
auto& bind_data = regs.cb_bind[static_cast<std::size_t>(stage)];
|
auto& bind_data = regs.cb_bind[stage_index];
|
||||||
|
|
||||||
ASSERT(bind_data.index < Regs::MaxConstBuffers);
|
ASSERT(bind_data.index < Regs::MaxConstBuffers);
|
||||||
auto& buffer = shader.const_buffers[bind_data.index];
|
auto& buffer = shader.const_buffers[bind_data.index];
|
||||||
|
@ -757,9 +758,9 @@ Texture::FullTextureInfo Maxwell3D::GetTextureInfo(Texture::TextureHandle tex_ha
|
||||||
return Texture::FullTextureInfo{GetTICEntry(tex_handle.tic_id), GetTSCEntry(tex_handle.tsc_id)};
|
return Texture::FullTextureInfo{GetTICEntry(tex_handle.tic_id), GetTSCEntry(tex_handle.tsc_id)};
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture::FullTextureInfo Maxwell3D::GetStageTexture(Regs::ShaderStage stage,
|
Texture::FullTextureInfo Maxwell3D::GetStageTexture(ShaderType stage, std::size_t offset) const {
|
||||||
std::size_t offset) const {
|
const auto stage_index = static_cast<std::size_t>(stage);
|
||||||
const auto& shader = state.shader_stages[static_cast<std::size_t>(stage)];
|
const auto& shader = state.shader_stages[stage_index];
|
||||||
const auto& tex_info_buffer = shader.const_buffers[regs.tex_cb_index];
|
const auto& tex_info_buffer = shader.const_buffers[regs.tex_cb_index];
|
||||||
ASSERT(tex_info_buffer.enabled && tex_info_buffer.address != 0);
|
ASSERT(tex_info_buffer.enabled && tex_info_buffer.address != 0);
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "video_core/engines/const_buffer_engine_interface.h"
|
#include "video_core/engines/const_buffer_engine_interface.h"
|
||||||
#include "video_core/engines/const_buffer_info.h"
|
#include "video_core/engines/const_buffer_info.h"
|
||||||
#include "video_core/engines/engine_upload.h"
|
#include "video_core/engines/engine_upload.h"
|
||||||
|
#include "video_core/engines/shader_type.h"
|
||||||
#include "video_core/gpu.h"
|
#include "video_core/gpu.h"
|
||||||
#include "video_core/macro_interpreter.h"
|
#include "video_core/macro_interpreter.h"
|
||||||
#include "video_core/textures/texture.h"
|
#include "video_core/textures/texture.h"
|
||||||
|
@ -130,14 +131,6 @@ public:
|
||||||
Fragment = 5,
|
Fragment = 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ShaderStage : u32 {
|
|
||||||
Vertex = 0,
|
|
||||||
TesselationControl = 1,
|
|
||||||
TesselationEval = 2,
|
|
||||||
Geometry = 3,
|
|
||||||
Fragment = 4,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct VertexAttribute {
|
struct VertexAttribute {
|
||||||
enum class Size : u32 {
|
enum class Size : u32 {
|
||||||
Invalid = 0x0,
|
Invalid = 0x0,
|
||||||
|
@ -1254,7 +1247,7 @@ public:
|
||||||
Texture::FullTextureInfo GetTextureInfo(Texture::TextureHandle tex_handle) const;
|
Texture::FullTextureInfo GetTextureInfo(Texture::TextureHandle tex_handle) const;
|
||||||
|
|
||||||
/// Returns the texture information for a specific texture in a specific shader stage.
|
/// Returns the texture information for a specific texture in a specific shader stage.
|
||||||
Texture::FullTextureInfo GetStageTexture(Regs::ShaderStage stage, std::size_t offset) const;
|
Texture::FullTextureInfo GetStageTexture(ShaderType stage, std::size_t offset) const;
|
||||||
|
|
||||||
u32 AccessConstBuffer32(ShaderType stage, u64 const_buffer, u64 offset) const override;
|
u32 AccessConstBuffer32(ShaderType stage, u64 const_buffer, u64 offset) const override;
|
||||||
|
|
||||||
|
@ -1376,7 +1369,7 @@ private:
|
||||||
void FinishCBData();
|
void FinishCBData();
|
||||||
|
|
||||||
/// Handles a write to the CB_BIND register.
|
/// Handles a write to the CB_BIND register.
|
||||||
void ProcessCBBind(Regs::ShaderStage stage);
|
void ProcessCBBind(std::size_t stage_index);
|
||||||
|
|
||||||
/// Handles a write to the VERTEX_END_GL register, triggering a draw.
|
/// Handles a write to the VERTEX_END_GL register, triggering a draw.
|
||||||
void DrawArrays();
|
void DrawArrays();
|
||||||
|
|
20
src/video_core/engines/shader_type.h
Normal file
20
src/video_core/engines/shader_type.h
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
// Copyright 2019 yuzu Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/common_types.h"
|
||||||
|
|
||||||
|
namespace Tegra::Engines {
|
||||||
|
|
||||||
|
enum class ShaderType : u32 {
|
||||||
|
Vertex = 0,
|
||||||
|
TesselationControl = 1,
|
||||||
|
TesselationEval = 2,
|
||||||
|
Geometry = 3,
|
||||||
|
Fragment = 4,
|
||||||
|
Compute = 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Tegra::Engines
|
|
@ -22,6 +22,7 @@
|
||||||
#include "core/settings.h"
|
#include "core/settings.h"
|
||||||
#include "video_core/engines/kepler_compute.h"
|
#include "video_core/engines/kepler_compute.h"
|
||||||
#include "video_core/engines/maxwell_3d.h"
|
#include "video_core/engines/maxwell_3d.h"
|
||||||
|
#include "video_core/engines/shader_type.h"
|
||||||
#include "video_core/memory_manager.h"
|
#include "video_core/memory_manager.h"
|
||||||
#include "video_core/renderer_opengl/gl_rasterizer.h"
|
#include "video_core/renderer_opengl/gl_rasterizer.h"
|
||||||
#include "video_core/renderer_opengl/gl_shader_cache.h"
|
#include "video_core/renderer_opengl/gl_shader_cache.h"
|
||||||
|
@ -60,8 +61,7 @@ Tegra::Texture::FullTextureInfo GetTextureInfo(const Engine& engine, const Entry
|
||||||
return engine.GetTextureInfo(tex_handle);
|
return engine.GetTextureInfo(tex_handle);
|
||||||
}
|
}
|
||||||
if constexpr (std::is_same_v<Engine, Tegra::Engines::Maxwell3D>) {
|
if constexpr (std::is_same_v<Engine, Tegra::Engines::Maxwell3D>) {
|
||||||
const auto stage = static_cast<Maxwell::ShaderStage>(shader_type);
|
return engine.GetStageTexture(shader_type, entry.GetOffset());
|
||||||
return engine.GetStageTexture(stage, entry.GetOffset());
|
|
||||||
} else {
|
} else {
|
||||||
return engine.GetTexture(entry.GetOffset());
|
return engine.GetTexture(entry.GetOffset());
|
||||||
}
|
}
|
||||||
|
@ -263,7 +263,7 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
|
||||||
|
|
||||||
for (std::size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) {
|
for (std::size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) {
|
||||||
const auto& shader_config = gpu.regs.shader_config[index];
|
const auto& shader_config = gpu.regs.shader_config[index];
|
||||||
const Maxwell::ShaderProgram program{static_cast<Maxwell::ShaderProgram>(index)};
|
const auto program{static_cast<Maxwell::ShaderProgram>(index)};
|
||||||
|
|
||||||
// Skip stages that are not enabled
|
// Skip stages that are not enabled
|
||||||
if (!gpu.regs.IsShaderConfigEnabled(index)) {
|
if (!gpu.regs.IsShaderConfigEnabled(index)) {
|
||||||
|
@ -288,7 +288,7 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
|
||||||
Shader shader{shader_cache.GetStageProgram(program)};
|
Shader shader{shader_cache.GetStageProgram(program)};
|
||||||
|
|
||||||
// Stage indices are 0 - 5
|
// Stage indices are 0 - 5
|
||||||
const auto stage = static_cast<Maxwell::ShaderStage>(index == 0 ? 0 : index - 1);
|
const std::size_t stage = index == 0 ? 0 : index - 1;
|
||||||
SetupDrawConstBuffers(stage, shader);
|
SetupDrawConstBuffers(stage, shader);
|
||||||
SetupDrawGlobalMemory(stage, shader);
|
SetupDrawGlobalMemory(stage, shader);
|
||||||
SetupDrawTextures(stage, shader, base_bindings);
|
SetupDrawTextures(stage, shader, base_bindings);
|
||||||
|
@ -856,11 +856,10 @@ bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SetupDrawConstBuffers(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage,
|
void RasterizerOpenGL::SetupDrawConstBuffers(std::size_t stage_index, const Shader& shader) {
|
||||||
const Shader& shader) {
|
|
||||||
MICROPROFILE_SCOPE(OpenGL_UBO);
|
MICROPROFILE_SCOPE(OpenGL_UBO);
|
||||||
const auto& stages = system.GPU().Maxwell3D().state.shader_stages;
|
const auto& stages = system.GPU().Maxwell3D().state.shader_stages;
|
||||||
const auto& shader_stage = stages[static_cast<std::size_t>(stage)];
|
const auto& shader_stage = stages[stage_index];
|
||||||
for (const auto& entry : shader->GetShaderEntries().const_buffers) {
|
for (const auto& entry : shader->GetShaderEntries().const_buffers) {
|
||||||
const auto& buffer = shader_stage.const_buffers[entry.GetIndex()];
|
const auto& buffer = shader_stage.const_buffers[entry.GetIndex()];
|
||||||
SetupConstBuffer(buffer, entry);
|
SetupConstBuffer(buffer, entry);
|
||||||
|
@ -899,11 +898,10 @@ void RasterizerOpenGL::SetupConstBuffer(const Tegra::Engines::ConstBufferInfo& b
|
||||||
bind_ubo_pushbuffer.Push(cbuf, offset, size);
|
bind_ubo_pushbuffer.Push(cbuf, offset, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SetupDrawGlobalMemory(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage,
|
void RasterizerOpenGL::SetupDrawGlobalMemory(std::size_t stage_index, const Shader& shader) {
|
||||||
const Shader& shader) {
|
|
||||||
auto& gpu{system.GPU()};
|
auto& gpu{system.GPU()};
|
||||||
auto& memory_manager{gpu.MemoryManager()};
|
auto& memory_manager{gpu.MemoryManager()};
|
||||||
const auto cbufs{gpu.Maxwell3D().state.shader_stages[static_cast<std::size_t>(stage)]};
|
const auto cbufs{gpu.Maxwell3D().state.shader_stages[stage_index]};
|
||||||
for (const auto& entry : shader->GetShaderEntries().global_memory_entries) {
|
for (const auto& entry : shader->GetShaderEntries().global_memory_entries) {
|
||||||
const auto addr{cbufs.const_buffers[entry.GetCbufIndex()].address + entry.GetCbufOffset()};
|
const auto addr{cbufs.const_buffers[entry.GetCbufIndex()].address + entry.GetCbufOffset()};
|
||||||
const auto gpu_addr{memory_manager.Read<u64>(addr)};
|
const auto gpu_addr{memory_manager.Read<u64>(addr)};
|
||||||
|
@ -932,7 +930,7 @@ void RasterizerOpenGL::SetupGlobalMemory(const GLShader::GlobalMemoryEntry& entr
|
||||||
bind_ssbo_pushbuffer.Push(ssbo, buffer_offset, static_cast<GLsizeiptr>(size));
|
bind_ssbo_pushbuffer.Push(ssbo, buffer_offset, static_cast<GLsizeiptr>(size));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SetupDrawTextures(Maxwell::ShaderStage stage, const Shader& shader,
|
void RasterizerOpenGL::SetupDrawTextures(std::size_t stage_index, const Shader& shader,
|
||||||
BaseBindings base_bindings) {
|
BaseBindings base_bindings) {
|
||||||
MICROPROFILE_SCOPE(OpenGL_Texture);
|
MICROPROFILE_SCOPE(OpenGL_Texture);
|
||||||
const auto& gpu = system.GPU();
|
const auto& gpu = system.GPU();
|
||||||
|
@ -945,7 +943,7 @@ void RasterizerOpenGL::SetupDrawTextures(Maxwell::ShaderStage stage, const Shade
|
||||||
const auto num_entries = static_cast<u32>(entries.size());
|
const auto num_entries = static_cast<u32>(entries.size());
|
||||||
for (u32 bindpoint = 0; bindpoint < num_entries; ++bindpoint) {
|
for (u32 bindpoint = 0; bindpoint < num_entries; ++bindpoint) {
|
||||||
const auto& entry = entries[bindpoint];
|
const auto& entry = entries[bindpoint];
|
||||||
const auto shader_type = static_cast<Tegra::Engines::ShaderType>(stage);
|
const auto shader_type = static_cast<Tegra::Engines::ShaderType>(stage_index);
|
||||||
const auto texture = GetTextureInfo(maxwell3d, entry, shader_type);
|
const auto texture = GetTextureInfo(maxwell3d, entry, shader_type);
|
||||||
SetupTexture(base_bindings.sampler + bindpoint, texture, entry);
|
SetupTexture(base_bindings.sampler + bindpoint, texture, entry);
|
||||||
}
|
}
|
||||||
|
@ -988,7 +986,7 @@ void RasterizerOpenGL::SetupTexture(u32 binding, const Tegra::Texture::FullTextu
|
||||||
texture.tic.w_source);
|
texture.tic.w_source);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SetupDrawImages(Maxwell::ShaderStage stage, const Shader& shader,
|
void RasterizerOpenGL::SetupDrawImages(std::size_t stage_index, const Shader& shader,
|
||||||
BaseBindings base_bindings) {
|
BaseBindings base_bindings) {
|
||||||
const auto& maxwell3d = system.GPU().Maxwell3D();
|
const auto& maxwell3d = system.GPU().Maxwell3D();
|
||||||
const auto& entries = shader->GetShaderEntries().images;
|
const auto& entries = shader->GetShaderEntries().images;
|
||||||
|
@ -996,7 +994,7 @@ void RasterizerOpenGL::SetupDrawImages(Maxwell::ShaderStage stage, const Shader&
|
||||||
const auto num_entries = static_cast<u32>(entries.size());
|
const auto num_entries = static_cast<u32>(entries.size());
|
||||||
for (u32 bindpoint = 0; bindpoint < num_entries; ++bindpoint) {
|
for (u32 bindpoint = 0; bindpoint < num_entries; ++bindpoint) {
|
||||||
const auto& entry = entries[bindpoint];
|
const auto& entry = entries[bindpoint];
|
||||||
const auto shader_type = static_cast<Tegra::Engines::ShaderType>(stage);
|
const auto shader_type = static_cast<Tegra::Engines::ShaderType>(stage_index);
|
||||||
const auto tic = GetTextureInfo(maxwell3d, entry, shader_type).tic;
|
const auto tic = GetTextureInfo(maxwell3d, entry, shader_type).tic;
|
||||||
SetupImage(base_bindings.image + bindpoint, tic, entry);
|
SetupImage(base_bindings.image + bindpoint, tic, entry);
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,8 +83,7 @@ private:
|
||||||
bool using_depth_fb, bool using_stencil_fb);
|
bool using_depth_fb, bool using_stencil_fb);
|
||||||
|
|
||||||
/// Configures the current constbuffers to use for the draw command.
|
/// Configures the current constbuffers to use for the draw command.
|
||||||
void SetupDrawConstBuffers(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage,
|
void SetupDrawConstBuffers(std::size_t stage_index, const Shader& shader);
|
||||||
const Shader& shader);
|
|
||||||
|
|
||||||
/// Configures the current constbuffers to use for the kernel invocation.
|
/// Configures the current constbuffers to use for the kernel invocation.
|
||||||
void SetupComputeConstBuffers(const Shader& kernel);
|
void SetupComputeConstBuffers(const Shader& kernel);
|
||||||
|
@ -94,8 +93,7 @@ private:
|
||||||
const GLShader::ConstBufferEntry& entry);
|
const GLShader::ConstBufferEntry& entry);
|
||||||
|
|
||||||
/// Configures the current global memory entries to use for the draw command.
|
/// Configures the current global memory entries to use for the draw command.
|
||||||
void SetupDrawGlobalMemory(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage,
|
void SetupDrawGlobalMemory(std::size_t stage_index, const Shader& shader);
|
||||||
const Shader& shader);
|
|
||||||
|
|
||||||
/// Configures the current global memory entries to use for the kernel invocation.
|
/// Configures the current global memory entries to use for the kernel invocation.
|
||||||
void SetupComputeGlobalMemory(const Shader& kernel);
|
void SetupComputeGlobalMemory(const Shader& kernel);
|
||||||
|
@ -108,7 +106,7 @@ private:
|
||||||
void DrawPrelude();
|
void DrawPrelude();
|
||||||
|
|
||||||
/// Configures the current textures to use for the draw command.
|
/// Configures the current textures to use for the draw command.
|
||||||
void SetupDrawTextures(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, const Shader& shader,
|
void SetupDrawTextures(std::size_t stage_index, const Shader& shader,
|
||||||
BaseBindings base_bindings);
|
BaseBindings base_bindings);
|
||||||
|
|
||||||
/// Configures the textures used in a compute shader.
|
/// Configures the textures used in a compute shader.
|
||||||
|
@ -119,8 +117,7 @@ private:
|
||||||
const GLShader::SamplerEntry& entry);
|
const GLShader::SamplerEntry& entry);
|
||||||
|
|
||||||
/// Configures images in a graphics shader.
|
/// Configures images in a graphics shader.
|
||||||
void SetupDrawImages(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, const Shader& shader,
|
void SetupDrawImages(std::size_t stage_index, const Shader& shader, BaseBindings base_bindings);
|
||||||
BaseBindings base_bindings);
|
|
||||||
|
|
||||||
/// Configures images in a compute shader.
|
/// Configures images in a compute shader.
|
||||||
void SetupComputeImages(const Shader& shader);
|
void SetupComputeImages(const Shader& shader);
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "core/frontend/emu_window.h"
|
#include "core/frontend/emu_window.h"
|
||||||
#include "video_core/engines/kepler_compute.h"
|
#include "video_core/engines/kepler_compute.h"
|
||||||
#include "video_core/engines/maxwell_3d.h"
|
#include "video_core/engines/maxwell_3d.h"
|
||||||
|
#include "video_core/engines/shader_type.h"
|
||||||
#include "video_core/memory_manager.h"
|
#include "video_core/memory_manager.h"
|
||||||
#include "video_core/renderer_opengl/gl_rasterizer.h"
|
#include "video_core/renderer_opengl/gl_rasterizer.h"
|
||||||
#include "video_core/renderer_opengl/gl_shader_cache.h"
|
#include "video_core/renderer_opengl/gl_shader_cache.h"
|
||||||
|
@ -84,28 +85,26 @@ std::size_t CalculateProgramSize(const GLShader::ProgramCode& program) {
|
||||||
/// Gets the shader program code from memory for the specified address
|
/// Gets the shader program code from memory for the specified address
|
||||||
ProgramCode GetShaderCode(Tegra::MemoryManager& memory_manager, const GPUVAddr gpu_addr,
|
ProgramCode GetShaderCode(Tegra::MemoryManager& memory_manager, const GPUVAddr gpu_addr,
|
||||||
const u8* host_ptr) {
|
const u8* host_ptr) {
|
||||||
ProgramCode program_code(VideoCommon::Shader::MAX_PROGRAM_LENGTH);
|
ProgramCode code(VideoCommon::Shader::MAX_PROGRAM_LENGTH);
|
||||||
ASSERT_OR_EXECUTE(host_ptr != nullptr, {
|
ASSERT_OR_EXECUTE(host_ptr != nullptr, {
|
||||||
std::fill(program_code.begin(), program_code.end(), 0);
|
std::fill(code.begin(), code.end(), 0);
|
||||||
return program_code;
|
return code;
|
||||||
});
|
});
|
||||||
memory_manager.ReadBlockUnsafe(gpu_addr, program_code.data(),
|
memory_manager.ReadBlockUnsafe(gpu_addr, code.data(), code.size() * sizeof(u64));
|
||||||
program_code.size() * sizeof(u64));
|
code.resize(CalculateProgramSize(code));
|
||||||
program_code.resize(CalculateProgramSize(program_code));
|
return code;
|
||||||
return program_code;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the shader type from a Maxwell program type
|
/// Gets the shader type from a Maxwell program type
|
||||||
constexpr GLenum GetShaderType(ProgramType program_type) {
|
constexpr GLenum GetGLShaderType(ShaderType shader_type) {
|
||||||
switch (program_type) {
|
switch (shader_type) {
|
||||||
case ProgramType::VertexA:
|
case ShaderType::Vertex:
|
||||||
case ProgramType::VertexB:
|
|
||||||
return GL_VERTEX_SHADER;
|
return GL_VERTEX_SHADER;
|
||||||
case ProgramType::Geometry:
|
case ShaderType::Geometry:
|
||||||
return GL_GEOMETRY_SHADER;
|
return GL_GEOMETRY_SHADER;
|
||||||
case ProgramType::Fragment:
|
case ShaderType::Fragment:
|
||||||
return GL_FRAGMENT_SHADER;
|
return GL_FRAGMENT_SHADER;
|
||||||
case ProgramType::Compute:
|
case ShaderType::Compute:
|
||||||
return GL_COMPUTE_SHADER;
|
return GL_COMPUTE_SHADER;
|
||||||
default:
|
default:
|
||||||
return GL_NONE;
|
return GL_NONE;
|
||||||
|
@ -135,30 +134,11 @@ constexpr std::tuple<const char*, const char*, u32> GetPrimitiveDescription(GLen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ProgramType GetProgramType(Maxwell::ShaderProgram program) {
|
|
||||||
switch (program) {
|
|
||||||
case Maxwell::ShaderProgram::VertexA:
|
|
||||||
return ProgramType::VertexA;
|
|
||||||
case Maxwell::ShaderProgram::VertexB:
|
|
||||||
return ProgramType::VertexB;
|
|
||||||
case Maxwell::ShaderProgram::TesselationControl:
|
|
||||||
return ProgramType::TessellationControl;
|
|
||||||
case Maxwell::ShaderProgram::TesselationEval:
|
|
||||||
return ProgramType::TessellationEval;
|
|
||||||
case Maxwell::ShaderProgram::Geometry:
|
|
||||||
return ProgramType::Geometry;
|
|
||||||
case Maxwell::ShaderProgram::Fragment:
|
|
||||||
return ProgramType::Fragment;
|
|
||||||
}
|
|
||||||
UNREACHABLE();
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Hashes one (or two) program streams
|
/// Hashes one (or two) program streams
|
||||||
u64 GetUniqueIdentifier(ProgramType program_type, const ProgramCode& code,
|
u64 GetUniqueIdentifier(ShaderType shader_type, bool is_a, const ProgramCode& code,
|
||||||
const ProgramCode& code_b) {
|
const ProgramCode& code_b) {
|
||||||
u64 unique_identifier = boost::hash_value(code);
|
u64 unique_identifier = boost::hash_value(code);
|
||||||
if (program_type == ProgramType::VertexA) {
|
if (is_a) {
|
||||||
// VertexA programs include two programs
|
// VertexA programs include two programs
|
||||||
boost::hash_combine(unique_identifier, boost::hash_value(code_b));
|
boost::hash_combine(unique_identifier, boost::hash_value(code_b));
|
||||||
}
|
}
|
||||||
|
@ -166,79 +146,74 @@ u64 GetUniqueIdentifier(ProgramType program_type, const ProgramCode& code,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates an unspecialized program from code streams
|
/// Creates an unspecialized program from code streams
|
||||||
std::string GenerateGLSL(const Device& device, ProgramType program_type, const ShaderIR& ir,
|
std::string GenerateGLSL(const Device& device, ShaderType shader_type, const ShaderIR& ir,
|
||||||
const std::optional<ShaderIR>& ir_b) {
|
const std::optional<ShaderIR>& ir_b) {
|
||||||
switch (program_type) {
|
switch (shader_type) {
|
||||||
case ProgramType::VertexA:
|
case ShaderType::Vertex:
|
||||||
case ProgramType::VertexB:
|
|
||||||
return GLShader::GenerateVertexShader(device, ir, ir_b ? &*ir_b : nullptr);
|
return GLShader::GenerateVertexShader(device, ir, ir_b ? &*ir_b : nullptr);
|
||||||
case ProgramType::Geometry:
|
case ShaderType::Geometry:
|
||||||
return GLShader::GenerateGeometryShader(device, ir);
|
return GLShader::GenerateGeometryShader(device, ir);
|
||||||
case ProgramType::Fragment:
|
case ShaderType::Fragment:
|
||||||
return GLShader::GenerateFragmentShader(device, ir);
|
return GLShader::GenerateFragmentShader(device, ir);
|
||||||
case ProgramType::Compute:
|
case ShaderType::Compute:
|
||||||
return GLShader::GenerateComputeShader(device, ir);
|
return GLShader::GenerateComputeShader(device, ir);
|
||||||
default:
|
default:
|
||||||
UNIMPLEMENTED_MSG("Unimplemented program_type={}", static_cast<u32>(program_type));
|
UNIMPLEMENTED_MSG("Unimplemented shader_type={}", static_cast<u32>(shader_type));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr const char* GetProgramTypeName(ProgramType program_type) {
|
constexpr const char* GetShaderTypeName(ShaderType shader_type) {
|
||||||
switch (program_type) {
|
switch (shader_type) {
|
||||||
case ProgramType::VertexA:
|
case ShaderType::Vertex:
|
||||||
case ProgramType::VertexB:
|
|
||||||
return "VS";
|
return "VS";
|
||||||
case ProgramType::TessellationControl:
|
case ShaderType::TesselationControl:
|
||||||
return "TCS";
|
return "HS";
|
||||||
case ProgramType::TessellationEval:
|
case ShaderType::TesselationEval:
|
||||||
return "TES";
|
return "DS";
|
||||||
case ProgramType::Geometry:
|
case ShaderType::Geometry:
|
||||||
return "GS";
|
return "GS";
|
||||||
case ProgramType::Fragment:
|
case ShaderType::Fragment:
|
||||||
return "FS";
|
return "FS";
|
||||||
case ProgramType::Compute:
|
case ShaderType::Compute:
|
||||||
return "CS";
|
return "CS";
|
||||||
}
|
}
|
||||||
return "UNK";
|
return "UNK";
|
||||||
}
|
}
|
||||||
|
|
||||||
Tegra::Engines::ShaderType GetEnginesShaderType(ProgramType program_type) {
|
constexpr ShaderType GetShaderType(Maxwell::ShaderProgram program_type) {
|
||||||
switch (program_type) {
|
switch (program_type) {
|
||||||
case ProgramType::VertexA:
|
case Maxwell::ShaderProgram::VertexA:
|
||||||
case ProgramType::VertexB:
|
case Maxwell::ShaderProgram::VertexB:
|
||||||
return Tegra::Engines::ShaderType::Vertex;
|
return ShaderType::Vertex;
|
||||||
case ProgramType::TessellationControl:
|
case Maxwell::ShaderProgram::TesselationControl:
|
||||||
return Tegra::Engines::ShaderType::TesselationControl;
|
return ShaderType::TesselationControl;
|
||||||
case ProgramType::TessellationEval:
|
case Maxwell::ShaderProgram::TesselationEval:
|
||||||
return Tegra::Engines::ShaderType::TesselationEval;
|
return ShaderType::TesselationEval;
|
||||||
case ProgramType::Geometry:
|
case Maxwell::ShaderProgram::Geometry:
|
||||||
return Tegra::Engines::ShaderType::Geometry;
|
return ShaderType::Geometry;
|
||||||
case ProgramType::Fragment:
|
case Maxwell::ShaderProgram::Fragment:
|
||||||
return Tegra::Engines::ShaderType::Fragment;
|
return ShaderType::Fragment;
|
||||||
case ProgramType::Compute:
|
|
||||||
return Tegra::Engines::ShaderType::Compute;
|
|
||||||
}
|
}
|
||||||
UNREACHABLE();
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetShaderId(u64 unique_identifier, ProgramType program_type) {
|
std::string GetShaderId(u64 unique_identifier, ShaderType shader_type) {
|
||||||
return fmt::format("{}{:016X}", GetProgramTypeName(program_type), unique_identifier);
|
return fmt::format("{}{:016X}", GetShaderTypeName(shader_type), unique_identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
Tegra::Engines::ConstBufferEngineInterface& GetConstBufferEngineInterface(
|
Tegra::Engines::ConstBufferEngineInterface& GetConstBufferEngineInterface(Core::System& system,
|
||||||
Core::System& system, ProgramType program_type) {
|
ShaderType shader_type) {
|
||||||
if (program_type == ProgramType::Compute) {
|
if (shader_type == ShaderType::Compute) {
|
||||||
return system.GPU().KeplerCompute();
|
return system.GPU().KeplerCompute();
|
||||||
} else {
|
} else {
|
||||||
return system.GPU().Maxwell3D();
|
return system.GPU().Maxwell3D();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<ConstBufferLocker> MakeLocker(Core::System& system, ProgramType program_type) {
|
std::unique_ptr<ConstBufferLocker> MakeLocker(Core::System& system, ShaderType shader_type) {
|
||||||
return std::make_unique<ConstBufferLocker>(GetEnginesShaderType(program_type),
|
return std::make_unique<ConstBufferLocker>(shader_type,
|
||||||
GetConstBufferEngineInterface(system, program_type));
|
GetConstBufferEngineInterface(system, shader_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
void FillLocker(ConstBufferLocker& locker, const ShaderDiskCacheUsage& usage) {
|
void FillLocker(ConstBufferLocker& locker, const ShaderDiskCacheUsage& usage) {
|
||||||
|
@ -255,18 +230,18 @@ void FillLocker(ConstBufferLocker& locker, const ShaderDiskCacheUsage& usage) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CachedProgram BuildShader(const Device& device, u64 unique_identifier, ProgramType program_type,
|
CachedProgram BuildShader(const Device& device, u64 unique_identifier, ShaderType shader_type,
|
||||||
const ProgramCode& program_code, const ProgramCode& program_code_b,
|
const ProgramCode& code, const ProgramCode& code_b,
|
||||||
ConstBufferLocker& locker, const ProgramVariant& variant,
|
ConstBufferLocker& locker, const ProgramVariant& variant,
|
||||||
bool hint_retrievable = false) {
|
bool hint_retrievable = false) {
|
||||||
LOG_INFO(Render_OpenGL, "called. {}", GetShaderId(unique_identifier, program_type));
|
LOG_INFO(Render_OpenGL, "called. {}", GetShaderId(unique_identifier, shader_type));
|
||||||
|
|
||||||
const bool is_compute = program_type == ProgramType::Compute;
|
const bool is_compute = shader_type == ShaderType::Compute;
|
||||||
const u32 main_offset = is_compute ? KERNEL_MAIN_OFFSET : STAGE_MAIN_OFFSET;
|
const u32 main_offset = is_compute ? KERNEL_MAIN_OFFSET : STAGE_MAIN_OFFSET;
|
||||||
const ShaderIR ir(program_code, main_offset, COMPILER_SETTINGS, locker);
|
const ShaderIR ir(code, main_offset, COMPILER_SETTINGS, locker);
|
||||||
std::optional<ShaderIR> ir_b;
|
std::optional<ShaderIR> ir_b;
|
||||||
if (!program_code_b.empty()) {
|
if (!code_b.empty()) {
|
||||||
ir_b.emplace(program_code_b, main_offset, COMPILER_SETTINGS, locker);
|
ir_b.emplace(code_b, main_offset, COMPILER_SETTINGS, locker);
|
||||||
}
|
}
|
||||||
const auto entries = GLShader::GetEntries(ir);
|
const auto entries = GLShader::GetEntries(ir);
|
||||||
|
|
||||||
|
@ -274,7 +249,7 @@ CachedProgram BuildShader(const Device& device, u64 unique_identifier, ProgramTy
|
||||||
#version 430 core
|
#version 430 core
|
||||||
#extension GL_ARB_separate_shader_objects : enable
|
#extension GL_ARB_separate_shader_objects : enable
|
||||||
)",
|
)",
|
||||||
GetShaderId(unique_identifier, program_type));
|
GetShaderId(unique_identifier, shader_type));
|
||||||
if (device.HasShaderBallot()) {
|
if (device.HasShaderBallot()) {
|
||||||
source += "#extension GL_ARB_shader_ballot : require\n";
|
source += "#extension GL_ARB_shader_ballot : require\n";
|
||||||
}
|
}
|
||||||
|
@ -313,14 +288,14 @@ CachedProgram BuildShader(const Device& device, u64 unique_identifier, ProgramTy
|
||||||
fmt::format("#define IMAGE_BINDING_{} {}\n", image.GetIndex(), base_bindings.image++);
|
fmt::format("#define IMAGE_BINDING_{} {}\n", image.GetIndex(), base_bindings.image++);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (program_type == ProgramType::Geometry) {
|
if (shader_type == ShaderType::Geometry) {
|
||||||
const auto [glsl_topology, debug_name, max_vertices] =
|
const auto [glsl_topology, debug_name, max_vertices] =
|
||||||
GetPrimitiveDescription(variant.primitive_mode);
|
GetPrimitiveDescription(variant.primitive_mode);
|
||||||
|
|
||||||
source += fmt::format("layout ({}) in;\n\n", glsl_topology);
|
source += fmt::format("layout ({}) in;\n\n", glsl_topology);
|
||||||
source += fmt::format("#define MAX_VERTEX_INPUT {}\n", max_vertices);
|
source += fmt::format("#define MAX_VERTEX_INPUT {}\n", max_vertices);
|
||||||
}
|
}
|
||||||
if (program_type == ProgramType::Compute) {
|
if (shader_type == ShaderType::Compute) {
|
||||||
source +=
|
source +=
|
||||||
fmt::format("layout (local_size_x = {}, local_size_y = {}, local_size_z = {}) in;\n",
|
fmt::format("layout (local_size_x = {}, local_size_y = {}, local_size_z = {}) in;\n",
|
||||||
variant.block_x, variant.block_y, variant.block_z);
|
variant.block_x, variant.block_y, variant.block_z);
|
||||||
|
@ -337,10 +312,10 @@ CachedProgram BuildShader(const Device& device, u64 unique_identifier, ProgramTy
|
||||||
}
|
}
|
||||||
|
|
||||||
source += '\n';
|
source += '\n';
|
||||||
source += GenerateGLSL(device, program_type, ir, ir_b);
|
source += GenerateGLSL(device, shader_type, ir, ir_b);
|
||||||
|
|
||||||
OGLShader shader;
|
OGLShader shader;
|
||||||
shader.Create(source.c_str(), GetShaderType(program_type));
|
shader.Create(source.c_str(), GetGLShaderType(shader_type));
|
||||||
|
|
||||||
auto program = std::make_shared<OGLProgram>();
|
auto program = std::make_shared<OGLProgram>();
|
||||||
program->Create(true, hint_retrievable, shader.handle);
|
program->Create(true, hint_retrievable, shader.handle);
|
||||||
|
@ -363,18 +338,16 @@ std::unordered_set<GLenum> GetSupportedFormats() {
|
||||||
|
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
CachedShader::CachedShader(const ShaderParameters& params, ProgramType program_type,
|
CachedShader::CachedShader(const ShaderParameters& params, ShaderType shader_type,
|
||||||
GLShader::ShaderEntries entries, ProgramCode program_code,
|
GLShader::ShaderEntries entries, ProgramCode code, ProgramCode code_b)
|
||||||
ProgramCode program_code_b)
|
: RasterizerCacheObject{params.host_ptr}, system{params.system}, disk_cache{params.disk_cache},
|
||||||
: RasterizerCacheObject{params.host_ptr}, system{params.system},
|
device{params.device}, cpu_addr{params.cpu_addr}, unique_identifier{params.unique_identifier},
|
||||||
disk_cache{params.disk_cache}, device{params.device}, cpu_addr{params.cpu_addr},
|
shader_type{shader_type}, entries{entries}, code{std::move(code)}, code_b{std::move(code_b)} {
|
||||||
unique_identifier{params.unique_identifier}, program_type{program_type}, entries{entries},
|
|
||||||
program_code{std::move(program_code)}, program_code_b{std::move(program_code_b)} {
|
|
||||||
if (!params.precompiled_variants) {
|
if (!params.precompiled_variants) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (const auto& pair : *params.precompiled_variants) {
|
for (const auto& pair : *params.precompiled_variants) {
|
||||||
auto locker = MakeLocker(system, program_type);
|
auto locker = MakeLocker(system, shader_type);
|
||||||
const auto& usage = pair->first;
|
const auto& usage = pair->first;
|
||||||
FillLocker(*locker, usage);
|
FillLocker(*locker, usage);
|
||||||
|
|
||||||
|
@ -395,38 +368,37 @@ CachedShader::CachedShader(const ShaderParameters& params, ProgramType program_t
|
||||||
}
|
}
|
||||||
|
|
||||||
Shader CachedShader::CreateStageFromMemory(const ShaderParameters& params,
|
Shader CachedShader::CreateStageFromMemory(const ShaderParameters& params,
|
||||||
Maxwell::ShaderProgram program_type,
|
Maxwell::ShaderProgram program_type, ProgramCode code,
|
||||||
ProgramCode program_code, ProgramCode program_code_b) {
|
ProgramCode code_b) {
|
||||||
params.disk_cache.SaveRaw(ShaderDiskCacheRaw(
|
const auto shader_type = GetShaderType(program_type);
|
||||||
params.unique_identifier, GetProgramType(program_type), program_code, program_code_b));
|
params.disk_cache.SaveRaw(
|
||||||
|
ShaderDiskCacheRaw(params.unique_identifier, shader_type, code, code_b));
|
||||||
|
|
||||||
ConstBufferLocker locker(GetEnginesShaderType(GetProgramType(program_type)),
|
ConstBufferLocker locker(shader_type, params.system.GPU().Maxwell3D());
|
||||||
params.system.GPU().Maxwell3D());
|
const ShaderIR ir(code, STAGE_MAIN_OFFSET, COMPILER_SETTINGS, locker);
|
||||||
const ShaderIR ir(program_code, STAGE_MAIN_OFFSET, COMPILER_SETTINGS, locker);
|
|
||||||
// TODO(Rodrigo): Handle VertexA shaders
|
// TODO(Rodrigo): Handle VertexA shaders
|
||||||
// std::optional<ShaderIR> ir_b;
|
// std::optional<ShaderIR> ir_b;
|
||||||
// if (!program_code_b.empty()) {
|
// if (!code_b.empty()) {
|
||||||
// ir_b.emplace(program_code_b, STAGE_MAIN_OFFSET);
|
// ir_b.emplace(code_b, STAGE_MAIN_OFFSET);
|
||||||
// }
|
// }
|
||||||
return std::shared_ptr<CachedShader>(
|
return std::shared_ptr<CachedShader>(new CachedShader(
|
||||||
new CachedShader(params, GetProgramType(program_type), GLShader::GetEntries(ir),
|
params, shader_type, GLShader::GetEntries(ir), std::move(code), std::move(code_b)));
|
||||||
std::move(program_code), std::move(program_code_b)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Shader CachedShader::CreateKernelFromMemory(const ShaderParameters& params, ProgramCode code) {
|
Shader CachedShader::CreateKernelFromMemory(const ShaderParameters& params, ProgramCode code) {
|
||||||
params.disk_cache.SaveRaw(
|
params.disk_cache.SaveRaw(
|
||||||
ShaderDiskCacheRaw(params.unique_identifier, ProgramType::Compute, code));
|
ShaderDiskCacheRaw(params.unique_identifier, ShaderType::Compute, code));
|
||||||
|
|
||||||
ConstBufferLocker locker(Tegra::Engines::ShaderType::Compute,
|
ConstBufferLocker locker(Tegra::Engines::ShaderType::Compute,
|
||||||
params.system.GPU().KeplerCompute());
|
params.system.GPU().KeplerCompute());
|
||||||
const ShaderIR ir(code, KERNEL_MAIN_OFFSET, COMPILER_SETTINGS, locker);
|
const ShaderIR ir(code, KERNEL_MAIN_OFFSET, COMPILER_SETTINGS, locker);
|
||||||
return std::shared_ptr<CachedShader>(new CachedShader(
|
return std::shared_ptr<CachedShader>(new CachedShader(
|
||||||
params, ProgramType::Compute, GLShader::GetEntries(ir), std::move(code), {}));
|
params, ShaderType::Compute, GLShader::GetEntries(ir), std::move(code), {}));
|
||||||
}
|
}
|
||||||
|
|
||||||
Shader CachedShader::CreateFromCache(const ShaderParameters& params,
|
Shader CachedShader::CreateFromCache(const ShaderParameters& params,
|
||||||
const UnspecializedShader& unspecialized) {
|
const UnspecializedShader& unspecialized) {
|
||||||
return std::shared_ptr<CachedShader>(new CachedShader(params, unspecialized.program_type,
|
return std::shared_ptr<CachedShader>(new CachedShader(params, unspecialized.type,
|
||||||
unspecialized.entries, unspecialized.code,
|
unspecialized.entries, unspecialized.code,
|
||||||
unspecialized.code_b));
|
unspecialized.code_b));
|
||||||
}
|
}
|
||||||
|
@ -437,7 +409,7 @@ std::tuple<GLuint, BaseBindings> CachedShader::GetHandle(const ProgramVariant& v
|
||||||
const auto [entry, is_cache_miss] = curr_locker_variant->programs.try_emplace(variant);
|
const auto [entry, is_cache_miss] = curr_locker_variant->programs.try_emplace(variant);
|
||||||
auto& program = entry->second;
|
auto& program = entry->second;
|
||||||
if (is_cache_miss) {
|
if (is_cache_miss) {
|
||||||
program = BuildShader(device, unique_identifier, program_type, program_code, program_code_b,
|
program = BuildShader(device, unique_identifier, shader_type, code, code_b,
|
||||||
*curr_locker_variant->locker, variant);
|
*curr_locker_variant->locker, variant);
|
||||||
disk_cache.SaveUsage(GetUsage(variant, *curr_locker_variant->locker));
|
disk_cache.SaveUsage(GetUsage(variant, *curr_locker_variant->locker));
|
||||||
|
|
||||||
|
@ -469,7 +441,7 @@ bool CachedShader::EnsureValidLockerVariant() {
|
||||||
if (!curr_locker_variant) {
|
if (!curr_locker_variant) {
|
||||||
auto& new_variant = locker_variants.emplace_back();
|
auto& new_variant = locker_variants.emplace_back();
|
||||||
new_variant = std::make_unique<LockerVariant>();
|
new_variant = std::make_unique<LockerVariant>();
|
||||||
new_variant->locker = MakeLocker(system, program_type);
|
new_variant->locker = MakeLocker(system, shader_type);
|
||||||
curr_locker_variant = new_variant.get();
|
curr_locker_variant = new_variant.get();
|
||||||
}
|
}
|
||||||
return previous_variant == curr_locker_variant;
|
return previous_variant == curr_locker_variant;
|
||||||
|
@ -537,10 +509,10 @@ void ShaderCacheOpenGL::LoadDiskCache(const std::atomic_bool& stop_loading,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!shader) {
|
if (!shader) {
|
||||||
auto locker{MakeLocker(system, unspecialized.program_type)};
|
auto locker{MakeLocker(system, unspecialized.type)};
|
||||||
FillLocker(*locker, usage);
|
FillLocker(*locker, usage);
|
||||||
|
|
||||||
shader = BuildShader(device, usage.unique_identifier, unspecialized.program_type,
|
shader = BuildShader(device, usage.unique_identifier, unspecialized.type,
|
||||||
unspecialized.code, unspecialized.code_b, *locker,
|
unspecialized.code, unspecialized.code_b, *locker,
|
||||||
usage.variant, true);
|
usage.variant, true);
|
||||||
}
|
}
|
||||||
|
@ -645,7 +617,7 @@ bool ShaderCacheOpenGL::GenerateUnspecializedShaders(
|
||||||
const auto& raw{raws[i]};
|
const auto& raw{raws[i]};
|
||||||
const u64 unique_identifier{raw.GetUniqueIdentifier()};
|
const u64 unique_identifier{raw.GetUniqueIdentifier()};
|
||||||
const u64 calculated_hash{
|
const u64 calculated_hash{
|
||||||
GetUniqueIdentifier(raw.GetProgramType(), raw.GetProgramCode(), raw.GetProgramCodeB())};
|
GetUniqueIdentifier(raw.GetType(), raw.HasProgramA(), raw.GetCode(), raw.GetCodeB())};
|
||||||
if (unique_identifier != calculated_hash) {
|
if (unique_identifier != calculated_hash) {
|
||||||
LOG_ERROR(Render_OpenGL,
|
LOG_ERROR(Render_OpenGL,
|
||||||
"Invalid hash in entry={:016x} (obtained hash={:016x}) - "
|
"Invalid hash in entry={:016x} (obtained hash={:016x}) - "
|
||||||
|
@ -656,9 +628,9 @@ bool ShaderCacheOpenGL::GenerateUnspecializedShaders(
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 main_offset =
|
const u32 main_offset =
|
||||||
raw.GetProgramType() == ProgramType::Compute ? KERNEL_MAIN_OFFSET : STAGE_MAIN_OFFSET;
|
raw.GetType() == ShaderType::Compute ? KERNEL_MAIN_OFFSET : STAGE_MAIN_OFFSET;
|
||||||
ConstBufferLocker locker(GetEnginesShaderType(raw.GetProgramType()));
|
ConstBufferLocker locker(raw.GetType());
|
||||||
const ShaderIR ir(raw.GetProgramCode(), main_offset, COMPILER_SETTINGS, locker);
|
const ShaderIR ir(raw.GetCode(), main_offset, COMPILER_SETTINGS, locker);
|
||||||
// TODO(Rodrigo): Handle VertexA shaders
|
// TODO(Rodrigo): Handle VertexA shaders
|
||||||
// std::optional<ShaderIR> ir_b;
|
// std::optional<ShaderIR> ir_b;
|
||||||
// if (raw.HasProgramA()) {
|
// if (raw.HasProgramA()) {
|
||||||
|
@ -667,9 +639,9 @@ bool ShaderCacheOpenGL::GenerateUnspecializedShaders(
|
||||||
|
|
||||||
UnspecializedShader unspecialized;
|
UnspecializedShader unspecialized;
|
||||||
unspecialized.entries = GLShader::GetEntries(ir);
|
unspecialized.entries = GLShader::GetEntries(ir);
|
||||||
unspecialized.program_type = raw.GetProgramType();
|
unspecialized.type = raw.GetType();
|
||||||
unspecialized.code = raw.GetProgramCode();
|
unspecialized.code = raw.GetCode();
|
||||||
unspecialized.code_b = raw.GetProgramCodeB();
|
unspecialized.code_b = raw.GetCodeB();
|
||||||
unspecialized_shaders.emplace(raw.GetUniqueIdentifier(), unspecialized);
|
unspecialized_shaders.emplace(raw.GetUniqueIdentifier(), unspecialized);
|
||||||
|
|
||||||
if (callback) {
|
if (callback) {
|
||||||
|
@ -702,7 +674,8 @@ Shader ShaderCacheOpenGL::GetStageProgram(Maxwell::ShaderProgram program) {
|
||||||
code_b = GetShaderCode(memory_manager, address_b, memory_manager.GetPointer(address_b));
|
code_b = GetShaderCode(memory_manager, address_b, memory_manager.GetPointer(address_b));
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto unique_identifier = GetUniqueIdentifier(GetProgramType(program), code, code_b);
|
const auto unique_identifier = GetUniqueIdentifier(
|
||||||
|
GetShaderType(program), program == Maxwell::ShaderProgram::VertexA, code, code_b);
|
||||||
const auto precompiled_variants = GetPrecompiledVariants(unique_identifier);
|
const auto precompiled_variants = GetPrecompiledVariants(unique_identifier);
|
||||||
const auto cpu_addr{*memory_manager.GpuToCpuAddress(address)};
|
const auto cpu_addr{*memory_manager.GpuToCpuAddress(address)};
|
||||||
const ShaderParameters params{system, disk_cache, precompiled_variants, device,
|
const ShaderParameters params{system, disk_cache, precompiled_variants, device,
|
||||||
|
@ -730,7 +703,7 @@ Shader ShaderCacheOpenGL::GetComputeKernel(GPUVAddr code_addr) {
|
||||||
|
|
||||||
// No kernel found - create a new one
|
// No kernel found - create a new one
|
||||||
auto code{GetShaderCode(memory_manager, code_addr, host_ptr)};
|
auto code{GetShaderCode(memory_manager, code_addr, host_ptr)};
|
||||||
const auto unique_identifier{GetUniqueIdentifier(ProgramType::Compute, code, {})};
|
const auto unique_identifier{GetUniqueIdentifier(ShaderType::Compute, false, code, {})};
|
||||||
const auto precompiled_variants = GetPrecompiledVariants(unique_identifier);
|
const auto precompiled_variants = GetPrecompiledVariants(unique_identifier);
|
||||||
const auto cpu_addr{*memory_manager.GpuToCpuAddress(code_addr)};
|
const auto cpu_addr{*memory_manager.GpuToCpuAddress(code_addr)};
|
||||||
const ShaderParameters params{system, disk_cache, precompiled_variants, device,
|
const ShaderParameters params{system, disk_cache, precompiled_variants, device,
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
#include "video_core/engines/shader_type.h"
|
||||||
#include "video_core/rasterizer_cache.h"
|
#include "video_core/rasterizer_cache.h"
|
||||||
#include "video_core/renderer_opengl/gl_resource_manager.h"
|
#include "video_core/renderer_opengl/gl_resource_manager.h"
|
||||||
#include "video_core/renderer_opengl/gl_shader_decompiler.h"
|
#include "video_core/renderer_opengl/gl_shader_decompiler.h"
|
||||||
|
@ -47,7 +48,7 @@ using PrecompiledVariants = std::vector<PrecompiledPrograms::iterator>;
|
||||||
|
|
||||||
struct UnspecializedShader {
|
struct UnspecializedShader {
|
||||||
GLShader::ShaderEntries entries;
|
GLShader::ShaderEntries entries;
|
||||||
ProgramType program_type;
|
Tegra::Engines::ShaderType type;
|
||||||
ProgramCode code;
|
ProgramCode code;
|
||||||
ProgramCode code_b;
|
ProgramCode code_b;
|
||||||
};
|
};
|
||||||
|
@ -77,7 +78,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t GetSizeInBytes() const override {
|
std::size_t GetSizeInBytes() const override {
|
||||||
return program_code.size() * sizeof(u64);
|
return code.size() * sizeof(u64);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the shader entries for the shader
|
/// Gets the shader entries for the shader
|
||||||
|
@ -94,7 +95,7 @@ private:
|
||||||
std::unordered_map<ProgramVariant, CachedProgram> programs;
|
std::unordered_map<ProgramVariant, CachedProgram> programs;
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit CachedShader(const ShaderParameters& params, ProgramType program_type,
|
explicit CachedShader(const ShaderParameters& params, Tegra::Engines::ShaderType shader_type,
|
||||||
GLShader::ShaderEntries entries, ProgramCode program_code,
|
GLShader::ShaderEntries entries, ProgramCode program_code,
|
||||||
ProgramCode program_code_b);
|
ProgramCode program_code_b);
|
||||||
|
|
||||||
|
@ -110,12 +111,12 @@ private:
|
||||||
VAddr cpu_addr{};
|
VAddr cpu_addr{};
|
||||||
|
|
||||||
u64 unique_identifier{};
|
u64 unique_identifier{};
|
||||||
ProgramType program_type{};
|
Tegra::Engines::ShaderType shader_type{};
|
||||||
|
|
||||||
GLShader::ShaderEntries entries;
|
GLShader::ShaderEntries entries;
|
||||||
|
|
||||||
ProgramCode program_code;
|
ProgramCode code;
|
||||||
ProgramCode program_code_b;
|
ProgramCode code_b;
|
||||||
|
|
||||||
LockerVariant* curr_locker_variant = nullptr;
|
LockerVariant* curr_locker_variant = nullptr;
|
||||||
std::vector<std::unique_ptr<LockerVariant>> locker_variants;
|
std::vector<std::unique_ptr<LockerVariant>> locker_variants;
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "video_core/engines/maxwell_3d.h"
|
#include "video_core/engines/maxwell_3d.h"
|
||||||
|
#include "video_core/engines/shader_type.h"
|
||||||
#include "video_core/renderer_opengl/gl_device.h"
|
#include "video_core/renderer_opengl/gl_device.h"
|
||||||
#include "video_core/renderer_opengl/gl_rasterizer.h"
|
#include "video_core/renderer_opengl/gl_rasterizer.h"
|
||||||
#include "video_core/renderer_opengl/gl_shader_decompiler.h"
|
#include "video_core/renderer_opengl/gl_shader_decompiler.h"
|
||||||
|
@ -27,6 +28,7 @@ namespace OpenGL::GLShader {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
using Tegra::Engines::ShaderType;
|
||||||
using Tegra::Shader::Attribute;
|
using Tegra::Shader::Attribute;
|
||||||
using Tegra::Shader::AttributeUse;
|
using Tegra::Shader::AttributeUse;
|
||||||
using Tegra::Shader::Header;
|
using Tegra::Shader::Header;
|
||||||
|
@ -331,8 +333,8 @@ std::string FlowStackTopName(MetaStackClass stack) {
|
||||||
return fmt::format("{}_flow_stack_top", GetFlowStackPrefix(stack));
|
return fmt::format("{}_flow_stack_top", GetFlowStackPrefix(stack));
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr bool IsVertexShader(ProgramType stage) {
|
[[deprecated]] constexpr bool IsVertexShader(ShaderType stage) {
|
||||||
return stage == ProgramType::VertexA || stage == ProgramType::VertexB;
|
return stage == ShaderType::Vertex;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ASTDecompiler;
|
class ASTDecompiler;
|
||||||
|
@ -340,7 +342,7 @@ class ExprDecompiler;
|
||||||
|
|
||||||
class GLSLDecompiler final {
|
class GLSLDecompiler final {
|
||||||
public:
|
public:
|
||||||
explicit GLSLDecompiler(const Device& device, const ShaderIR& ir, ProgramType stage,
|
explicit GLSLDecompiler(const Device& device, const ShaderIR& ir, ShaderType stage,
|
||||||
std::string suffix)
|
std::string suffix)
|
||||||
: device{device}, ir{ir}, stage{stage}, suffix{suffix}, header{ir.GetHeader()} {}
|
: device{device}, ir{ir}, stage{stage}, suffix{suffix}, header{ir.GetHeader()} {}
|
||||||
|
|
||||||
|
@ -427,7 +429,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeclareGeometry() {
|
void DeclareGeometry() {
|
||||||
if (stage != ProgramType::Geometry) {
|
if (stage != ShaderType::Geometry) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -510,7 +512,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeclareLocalMemory() {
|
void DeclareLocalMemory() {
|
||||||
if (stage == ProgramType::Compute) {
|
if (stage == ShaderType::Compute) {
|
||||||
code.AddLine("#ifdef LOCAL_MEMORY_SIZE");
|
code.AddLine("#ifdef LOCAL_MEMORY_SIZE");
|
||||||
code.AddLine("uint {}[LOCAL_MEMORY_SIZE];", GetLocalMemory());
|
code.AddLine("uint {}[LOCAL_MEMORY_SIZE];", GetLocalMemory());
|
||||||
code.AddLine("#endif");
|
code.AddLine("#endif");
|
||||||
|
@ -575,12 +577,12 @@ private:
|
||||||
const u32 location{GetGenericAttributeIndex(index)};
|
const u32 location{GetGenericAttributeIndex(index)};
|
||||||
|
|
||||||
std::string name{GetInputAttribute(index)};
|
std::string name{GetInputAttribute(index)};
|
||||||
if (stage == ProgramType::Geometry) {
|
if (stage == ShaderType::Geometry) {
|
||||||
name = "gs_" + name + "[]";
|
name = "gs_" + name + "[]";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string suffix;
|
std::string suffix;
|
||||||
if (stage == ProgramType::Fragment) {
|
if (stage == ShaderType::Fragment) {
|
||||||
const auto input_mode{header.ps.GetAttributeUse(location)};
|
const auto input_mode{header.ps.GetAttributeUse(location)};
|
||||||
if (skip_unused && input_mode == AttributeUse::Unused) {
|
if (skip_unused && input_mode == AttributeUse::Unused) {
|
||||||
return;
|
return;
|
||||||
|
@ -592,7 +594,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeclareOutputAttributes() {
|
void DeclareOutputAttributes() {
|
||||||
if (ir.HasPhysicalAttributes() && stage != ProgramType::Fragment) {
|
if (ir.HasPhysicalAttributes() && stage != ShaderType::Fragment) {
|
||||||
for (u32 i = 0; i < GetNumPhysicalVaryings(); ++i) {
|
for (u32 i = 0; i < GetNumPhysicalVaryings(); ++i) {
|
||||||
DeclareOutputAttribute(ToGenericAttribute(i));
|
DeclareOutputAttribute(ToGenericAttribute(i));
|
||||||
}
|
}
|
||||||
|
@ -704,7 +706,7 @@ private:
|
||||||
constexpr u32 element_stride = 4;
|
constexpr u32 element_stride = 4;
|
||||||
const u32 address{generic_base + index * generic_stride + element * element_stride};
|
const u32 address{generic_base + index * generic_stride + element * element_stride};
|
||||||
|
|
||||||
const bool declared = stage != ProgramType::Fragment ||
|
const bool declared = stage != ShaderType::Fragment ||
|
||||||
header.ps.GetAttributeUse(index) != AttributeUse::Unused;
|
header.ps.GetAttributeUse(index) != AttributeUse::Unused;
|
||||||
const std::string value =
|
const std::string value =
|
||||||
declared ? ReadAttribute(attribute, element).AsFloat() : "0.0f";
|
declared ? ReadAttribute(attribute, element).AsFloat() : "0.0f";
|
||||||
|
@ -796,7 +798,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const auto abuf = std::get_if<AbufNode>(&*node)) {
|
if (const auto abuf = std::get_if<AbufNode>(&*node)) {
|
||||||
UNIMPLEMENTED_IF_MSG(abuf->IsPhysicalBuffer() && stage == ProgramType::Geometry,
|
UNIMPLEMENTED_IF_MSG(abuf->IsPhysicalBuffer() && stage == ShaderType::Geometry,
|
||||||
"Physical attributes in geometry shaders are not implemented");
|
"Physical attributes in geometry shaders are not implemented");
|
||||||
if (abuf->IsPhysicalBuffer()) {
|
if (abuf->IsPhysicalBuffer()) {
|
||||||
return {fmt::format("ReadPhysicalAttribute({})",
|
return {fmt::format("ReadPhysicalAttribute({})",
|
||||||
|
@ -891,7 +893,7 @@ private:
|
||||||
|
|
||||||
Expression ReadAttribute(Attribute::Index attribute, u32 element, const Node& buffer = {}) {
|
Expression ReadAttribute(Attribute::Index attribute, u32 element, const Node& buffer = {}) {
|
||||||
const auto GeometryPass = [&](std::string_view name) {
|
const auto GeometryPass = [&](std::string_view name) {
|
||||||
if (stage == ProgramType::Geometry && buffer) {
|
if (stage == ShaderType::Geometry && buffer) {
|
||||||
// TODO(Rodrigo): Guard geometry inputs against out of bound reads. Some games
|
// TODO(Rodrigo): Guard geometry inputs against out of bound reads. Some games
|
||||||
// set an 0x80000000 index for those and the shader fails to build. Find out why
|
// set an 0x80000000 index for those and the shader fails to build. Find out why
|
||||||
// this happens and what's its intent.
|
// this happens and what's its intent.
|
||||||
|
@ -903,11 +905,11 @@ private:
|
||||||
switch (attribute) {
|
switch (attribute) {
|
||||||
case Attribute::Index::Position:
|
case Attribute::Index::Position:
|
||||||
switch (stage) {
|
switch (stage) {
|
||||||
case ProgramType::Geometry:
|
case ShaderType::Geometry:
|
||||||
return {fmt::format("gl_in[{}].gl_Position{}", Visit(buffer).AsUint(),
|
return {fmt::format("gl_in[{}].gl_Position{}", Visit(buffer).AsUint(),
|
||||||
GetSwizzle(element)),
|
GetSwizzle(element)),
|
||||||
Type::Float};
|
Type::Float};
|
||||||
case ProgramType::Fragment:
|
case ShaderType::Fragment:
|
||||||
return {element == 3 ? "1.0f" : ("gl_FragCoord"s + GetSwizzle(element)),
|
return {element == 3 ? "1.0f" : ("gl_FragCoord"s + GetSwizzle(element)),
|
||||||
Type::Float};
|
Type::Float};
|
||||||
default:
|
default:
|
||||||
|
@ -941,7 +943,7 @@ private:
|
||||||
return {"0", Type::Int};
|
return {"0", Type::Int};
|
||||||
case Attribute::Index::FrontFacing:
|
case Attribute::Index::FrontFacing:
|
||||||
// TODO(Subv): Find out what the values are for the other elements.
|
// TODO(Subv): Find out what the values are for the other elements.
|
||||||
ASSERT(stage == ProgramType::Fragment);
|
ASSERT(stage == ShaderType::Fragment);
|
||||||
switch (element) {
|
switch (element) {
|
||||||
case 3:
|
case 3:
|
||||||
return {"(gl_FrontFacing ? -1 : 0)", Type::Int};
|
return {"(gl_FrontFacing ? -1 : 0)", Type::Int};
|
||||||
|
@ -967,7 +969,7 @@ private:
|
||||||
// be found in fragment shaders, so we disable precise there. There are vertex shaders that
|
// be found in fragment shaders, so we disable precise there. There are vertex shaders that
|
||||||
// also fail to build but nobody seems to care about those.
|
// also fail to build but nobody seems to care about those.
|
||||||
// Note: Only bugged drivers will skip precise.
|
// Note: Only bugged drivers will skip precise.
|
||||||
const bool disable_precise = device.HasPreciseBug() && stage == ProgramType::Fragment;
|
const bool disable_precise = device.HasPreciseBug() && stage == ShaderType::Fragment;
|
||||||
|
|
||||||
std::string temporary = code.GenerateTemporary();
|
std::string temporary = code.GenerateTemporary();
|
||||||
code.AddLine("{}{} {} = {};", disable_precise ? "" : "precise ", GetTypeString(type),
|
code.AddLine("{}{} {} = {};", disable_precise ? "" : "precise ", GetTypeString(type),
|
||||||
|
@ -1233,7 +1235,7 @@ private:
|
||||||
fmt::format("{}[{} >> 2]", GetLocalMemory(), Visit(lmem->GetAddress()).AsUint()),
|
fmt::format("{}[{} >> 2]", GetLocalMemory(), Visit(lmem->GetAddress()).AsUint()),
|
||||||
Type::Uint};
|
Type::Uint};
|
||||||
} else if (const auto smem = std::get_if<SmemNode>(&*dest)) {
|
} else if (const auto smem = std::get_if<SmemNode>(&*dest)) {
|
||||||
ASSERT(stage == ProgramType::Compute);
|
ASSERT(stage == ShaderType::Compute);
|
||||||
target = {fmt::format("smem[{} >> 2]", Visit(smem->GetAddress()).AsUint()), Type::Uint};
|
target = {fmt::format("smem[{} >> 2]", Visit(smem->GetAddress()).AsUint()), Type::Uint};
|
||||||
} else if (const auto gmem = std::get_if<GmemNode>(&*dest)) {
|
} else if (const auto gmem = std::get_if<GmemNode>(&*dest)) {
|
||||||
const std::string real = Visit(gmem->GetRealAddress()).AsUint();
|
const std::string real = Visit(gmem->GetRealAddress()).AsUint();
|
||||||
|
@ -1801,7 +1803,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreExit() {
|
void PreExit() {
|
||||||
if (stage != ProgramType::Fragment) {
|
if (stage != ShaderType::Fragment) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto& used_registers = ir.GetRegisters();
|
const auto& used_registers = ir.GetRegisters();
|
||||||
|
@ -1854,14 +1856,14 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
Expression EmitVertex(Operation operation) {
|
Expression EmitVertex(Operation operation) {
|
||||||
ASSERT_MSG(stage == ProgramType::Geometry,
|
ASSERT_MSG(stage == ShaderType::Geometry,
|
||||||
"EmitVertex is expected to be used in a geometry shader.");
|
"EmitVertex is expected to be used in a geometry shader.");
|
||||||
code.AddLine("EmitVertex();");
|
code.AddLine("EmitVertex();");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
Expression EndPrimitive(Operation operation) {
|
Expression EndPrimitive(Operation operation) {
|
||||||
ASSERT_MSG(stage == ProgramType::Geometry,
|
ASSERT_MSG(stage == ShaderType::Geometry,
|
||||||
"EndPrimitive is expected to be used in a geometry shader.");
|
"EndPrimitive is expected to be used in a geometry shader.");
|
||||||
code.AddLine("EndPrimitive();");
|
code.AddLine("EndPrimitive();");
|
||||||
return {};
|
return {};
|
||||||
|
@ -2192,7 +2194,7 @@ private:
|
||||||
|
|
||||||
const Device& device;
|
const Device& device;
|
||||||
const ShaderIR& ir;
|
const ShaderIR& ir;
|
||||||
const ProgramType stage;
|
const ShaderType stage;
|
||||||
const std::string suffix;
|
const std::string suffix;
|
||||||
const Header header;
|
const Header header;
|
||||||
|
|
||||||
|
@ -2447,7 +2449,7 @@ const float fswzadd_modifiers_b[] = float[4](-1.0f, -1.0f, 1.0f, -1.0f );
|
||||||
)";
|
)";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Decompile(const Device& device, const ShaderIR& ir, ProgramType stage,
|
std::string Decompile(const Device& device, const ShaderIR& ir, ShaderType stage,
|
||||||
const std::string& suffix) {
|
const std::string& suffix) {
|
||||||
GLSLDecompiler decompiler(device, ir, stage, suffix);
|
GLSLDecompiler decompiler(device, ir, stage, suffix);
|
||||||
decompiler.Decompile();
|
decompiler.Decompile();
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "video_core/engines/maxwell_3d.h"
|
#include "video_core/engines/maxwell_3d.h"
|
||||||
|
#include "video_core/engines/shader_type.h"
|
||||||
#include "video_core/shader/shader_ir.h"
|
#include "video_core/shader/shader_ir.h"
|
||||||
|
|
||||||
namespace VideoCommon::Shader {
|
namespace VideoCommon::Shader {
|
||||||
|
@ -17,20 +18,8 @@ class ShaderIR;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace OpenGL {
|
namespace OpenGL {
|
||||||
|
|
||||||
class Device;
|
class Device;
|
||||||
|
}
|
||||||
enum class ProgramType : u32 {
|
|
||||||
VertexA = 0,
|
|
||||||
VertexB = 1,
|
|
||||||
TessellationControl = 2,
|
|
||||||
TessellationEval = 3,
|
|
||||||
Geometry = 4,
|
|
||||||
Fragment = 5,
|
|
||||||
Compute = 6
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace OpenGL
|
|
||||||
|
|
||||||
namespace OpenGL::GLShader {
|
namespace OpenGL::GLShader {
|
||||||
|
|
||||||
|
@ -94,6 +83,6 @@ ShaderEntries GetEntries(const VideoCommon::Shader::ShaderIR& ir);
|
||||||
std::string GetCommonDeclarations();
|
std::string GetCommonDeclarations();
|
||||||
|
|
||||||
std::string Decompile(const Device& device, const VideoCommon::Shader::ShaderIR& ir,
|
std::string Decompile(const Device& device, const VideoCommon::Shader::ShaderIR& ir,
|
||||||
ProgramType stage, const std::string& suffix);
|
Tegra::Engines::ShaderType stage, const std::string& suffix);
|
||||||
|
|
||||||
} // namespace OpenGL::GLShader
|
} // namespace OpenGL::GLShader
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
|
@ -12,16 +13,16 @@
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/scm_rev.h"
|
#include "common/scm_rev.h"
|
||||||
#include "common/zstd_compression.h"
|
#include "common/zstd_compression.h"
|
||||||
|
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/hle/kernel/process.h"
|
#include "core/hle/kernel/process.h"
|
||||||
#include "core/settings.h"
|
#include "core/settings.h"
|
||||||
|
#include "video_core/engines/shader_type.h"
|
||||||
#include "video_core/renderer_opengl/gl_shader_cache.h"
|
#include "video_core/renderer_opengl/gl_shader_cache.h"
|
||||||
#include "video_core/renderer_opengl/gl_shader_disk_cache.h"
|
#include "video_core/renderer_opengl/gl_shader_disk_cache.h"
|
||||||
|
|
||||||
namespace OpenGL {
|
namespace OpenGL {
|
||||||
|
|
||||||
|
using Tegra::Engines::ShaderType;
|
||||||
using VideoCommon::Shader::BindlessSamplerMap;
|
using VideoCommon::Shader::BindlessSamplerMap;
|
||||||
using VideoCommon::Shader::BoundSamplerMap;
|
using VideoCommon::Shader::BoundSamplerMap;
|
||||||
using VideoCommon::Shader::KeyMap;
|
using VideoCommon::Shader::KeyMap;
|
||||||
|
@ -67,10 +68,10 @@ ShaderCacheVersionHash GetShaderCacheVersionHash() {
|
||||||
|
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
ShaderDiskCacheRaw::ShaderDiskCacheRaw(u64 unique_identifier, ProgramType program_type,
|
ShaderDiskCacheRaw::ShaderDiskCacheRaw(u64 unique_identifier, ShaderType type, ProgramCode code,
|
||||||
ProgramCode program_code, ProgramCode program_code_b)
|
ProgramCode code_b)
|
||||||
: unique_identifier{unique_identifier}, program_type{program_type},
|
: unique_identifier{unique_identifier}, type{type}, code{std::move(code)}, code_b{std::move(
|
||||||
program_code{std::move(program_code)}, program_code_b{std::move(program_code_b)} {}
|
code_b)} {}
|
||||||
|
|
||||||
ShaderDiskCacheRaw::ShaderDiskCacheRaw() = default;
|
ShaderDiskCacheRaw::ShaderDiskCacheRaw() = default;
|
||||||
|
|
||||||
|
@ -78,42 +79,39 @@ ShaderDiskCacheRaw::~ShaderDiskCacheRaw() = default;
|
||||||
|
|
||||||
bool ShaderDiskCacheRaw::Load(FileUtil::IOFile& file) {
|
bool ShaderDiskCacheRaw::Load(FileUtil::IOFile& file) {
|
||||||
if (file.ReadBytes(&unique_identifier, sizeof(u64)) != sizeof(u64) ||
|
if (file.ReadBytes(&unique_identifier, sizeof(u64)) != sizeof(u64) ||
|
||||||
file.ReadBytes(&program_type, sizeof(u32)) != sizeof(u32)) {
|
file.ReadBytes(&type, sizeof(u32)) != sizeof(u32)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
u32 program_code_size{};
|
u32 code_size{};
|
||||||
u32 program_code_size_b{};
|
u32 code_size_b{};
|
||||||
if (file.ReadBytes(&program_code_size, sizeof(u32)) != sizeof(u32) ||
|
if (file.ReadBytes(&code_size, sizeof(u32)) != sizeof(u32) ||
|
||||||
file.ReadBytes(&program_code_size_b, sizeof(u32)) != sizeof(u32)) {
|
file.ReadBytes(&code_size_b, sizeof(u32)) != sizeof(u32)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
program_code.resize(program_code_size);
|
code.resize(code_size);
|
||||||
program_code_b.resize(program_code_size_b);
|
code_b.resize(code_size_b);
|
||||||
|
|
||||||
if (file.ReadArray(program_code.data(), program_code_size) != program_code_size)
|
if (file.ReadArray(code.data(), code_size) != code_size)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (HasProgramA() &&
|
if (HasProgramA() && file.ReadArray(code_b.data(), code_size_b) != code_size_b) {
|
||||||
file.ReadArray(program_code_b.data(), program_code_size_b) != program_code_size_b) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ShaderDiskCacheRaw::Save(FileUtil::IOFile& file) const {
|
bool ShaderDiskCacheRaw::Save(FileUtil::IOFile& file) const {
|
||||||
if (file.WriteObject(unique_identifier) != 1 ||
|
if (file.WriteObject(unique_identifier) != 1 || file.WriteObject(static_cast<u32>(type)) != 1 ||
|
||||||
file.WriteObject(static_cast<u32>(program_type)) != 1 ||
|
file.WriteObject(static_cast<u32>(code.size())) != 1 ||
|
||||||
file.WriteObject(static_cast<u32>(program_code.size())) != 1 ||
|
file.WriteObject(static_cast<u32>(code_b.size())) != 1) {
|
||||||
file.WriteObject(static_cast<u32>(program_code_b.size())) != 1) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file.WriteArray(program_code.data(), program_code.size()) != program_code.size())
|
if (file.WriteArray(code.data(), code.size()) != code.size())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (HasProgramA() &&
|
if (HasProgramA() && file.WriteArray(code_b.data(), code_b.size()) != code_b.size()) {
|
||||||
file.WriteArray(program_code_b.data(), program_code_b.size()) != program_code_b.size()) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/file_sys/vfs_vector.h"
|
#include "core/file_sys/vfs_vector.h"
|
||||||
|
#include "video_core/engines/shader_type.h"
|
||||||
#include "video_core/renderer_opengl/gl_shader_gen.h"
|
#include "video_core/renderer_opengl/gl_shader_gen.h"
|
||||||
#include "video_core/shader/const_buffer_locker.h"
|
#include "video_core/shader/const_buffer_locker.h"
|
||||||
|
|
||||||
|
@ -154,8 +155,8 @@ namespace OpenGL {
|
||||||
/// Describes a shader how it's used by the guest GPU
|
/// Describes a shader how it's used by the guest GPU
|
||||||
class ShaderDiskCacheRaw {
|
class ShaderDiskCacheRaw {
|
||||||
public:
|
public:
|
||||||
explicit ShaderDiskCacheRaw(u64 unique_identifier, ProgramType program_type,
|
explicit ShaderDiskCacheRaw(u64 unique_identifier, Tegra::Engines::ShaderType type,
|
||||||
ProgramCode program_code, ProgramCode program_code_b = {});
|
ProgramCode code, ProgramCode code_b = {});
|
||||||
ShaderDiskCacheRaw();
|
ShaderDiskCacheRaw();
|
||||||
~ShaderDiskCacheRaw();
|
~ShaderDiskCacheRaw();
|
||||||
|
|
||||||
|
@ -168,27 +169,26 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HasProgramA() const {
|
bool HasProgramA() const {
|
||||||
return program_type == ProgramType::VertexA;
|
return !code.empty() && !code_b.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
ProgramType GetProgramType() const {
|
Tegra::Engines::ShaderType GetType() const {
|
||||||
return program_type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ProgramCode& GetProgramCode() const {
|
const ProgramCode& GetCode() const {
|
||||||
return program_code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ProgramCode& GetProgramCodeB() const {
|
const ProgramCode& GetCodeB() const {
|
||||||
return program_code_b;
|
return code_b;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
u64 unique_identifier{};
|
u64 unique_identifier{};
|
||||||
ProgramType program_type{};
|
Tegra::Engines::ShaderType type{};
|
||||||
|
ProgramCode code;
|
||||||
ProgramCode program_code;
|
ProgramCode code_b;
|
||||||
ProgramCode program_code_b;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Contains an OpenGL dumped binary program
|
/// Contains an OpenGL dumped binary program
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
#include "video_core/engines/maxwell_3d.h"
|
#include "video_core/engines/maxwell_3d.h"
|
||||||
|
#include "video_core/engines/shader_type.h"
|
||||||
#include "video_core/renderer_opengl/gl_shader_decompiler.h"
|
#include "video_core/renderer_opengl/gl_shader_decompiler.h"
|
||||||
#include "video_core/renderer_opengl/gl_shader_gen.h"
|
#include "video_core/renderer_opengl/gl_shader_gen.h"
|
||||||
#include "video_core/shader/shader_ir.h"
|
#include "video_core/shader/shader_ir.h"
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
namespace OpenGL::GLShader {
|
namespace OpenGL::GLShader {
|
||||||
|
|
||||||
using Tegra::Engines::Maxwell3D;
|
using Tegra::Engines::Maxwell3D;
|
||||||
|
using Tegra::Engines::ShaderType;
|
||||||
using VideoCommon::Shader::CompileDepth;
|
using VideoCommon::Shader::CompileDepth;
|
||||||
using VideoCommon::Shader::CompilerSettings;
|
using VideoCommon::Shader::CompilerSettings;
|
||||||
using VideoCommon::Shader::ProgramCode;
|
using VideoCommon::Shader::ProgramCode;
|
||||||
|
@ -24,10 +26,9 @@ layout (std140, binding = EMULATION_UBO_BINDING) uniform vs_config {
|
||||||
};
|
};
|
||||||
|
|
||||||
)";
|
)";
|
||||||
const auto stage = ir_b ? ProgramType::VertexA : ProgramType::VertexB;
|
out += Decompile(device, ir, ShaderType::Vertex, "vertex");
|
||||||
out += Decompile(device, ir, stage, "vertex");
|
|
||||||
if (ir_b) {
|
if (ir_b) {
|
||||||
out += Decompile(device, *ir_b, ProgramType::VertexB, "vertex_b");
|
out += Decompile(device, *ir_b, ShaderType::Vertex, "vertex_b");
|
||||||
}
|
}
|
||||||
|
|
||||||
out += R"(
|
out += R"(
|
||||||
|
@ -49,7 +50,7 @@ layout (std140, binding = EMULATION_UBO_BINDING) uniform gs_config {
|
||||||
};
|
};
|
||||||
|
|
||||||
)";
|
)";
|
||||||
out += Decompile(device, ir, ProgramType::Geometry, "geometry");
|
out += Decompile(device, ir, ShaderType::Geometry, "geometry");
|
||||||
|
|
||||||
out += R"(
|
out += R"(
|
||||||
void main() {
|
void main() {
|
||||||
|
@ -76,7 +77,7 @@ layout (std140, binding = EMULATION_UBO_BINDING) uniform fs_config {
|
||||||
};
|
};
|
||||||
|
|
||||||
)";
|
)";
|
||||||
out += Decompile(device, ir, ProgramType::Fragment, "fragment");
|
out += Decompile(device, ir, ShaderType::Fragment, "fragment");
|
||||||
|
|
||||||
out += R"(
|
out += R"(
|
||||||
void main() {
|
void main() {
|
||||||
|
@ -88,7 +89,7 @@ void main() {
|
||||||
|
|
||||||
std::string GenerateComputeShader(const Device& device, const ShaderIR& ir) {
|
std::string GenerateComputeShader(const Device& device, const ShaderIR& ir) {
|
||||||
std::string out = GetCommonDeclarations();
|
std::string out = GetCommonDeclarations();
|
||||||
out += Decompile(device, ir, ProgramType::Compute, "compute");
|
out += Decompile(device, ir, ShaderType::Compute, "compute");
|
||||||
out += R"(
|
out += R"(
|
||||||
void main() {
|
void main() {
|
||||||
execute_compute();
|
execute_compute();
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
|
|
||||||
namespace Vulkan::MaxwellToVK {
|
namespace Vulkan::MaxwellToVK {
|
||||||
|
|
||||||
|
using Maxwell = Tegra::Engines::Maxwell3D::Regs;
|
||||||
|
|
||||||
namespace Sampler {
|
namespace Sampler {
|
||||||
|
|
||||||
vk::Filter Filter(Tegra::Texture::TextureFilter filter) {
|
vk::Filter Filter(Tegra::Texture::TextureFilter filter) {
|
||||||
|
@ -196,17 +198,17 @@ std::pair<vk::Format, bool> SurfaceFormat(const VKDevice& device, FormatType for
|
||||||
return {device.GetSupportedFormat(tuple.format, usage, format_type), tuple.attachable};
|
return {device.GetSupportedFormat(tuple.format, usage, format_type), tuple.attachable};
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::ShaderStageFlagBits ShaderStage(Maxwell::ShaderStage stage) {
|
vk::ShaderStageFlagBits ShaderStage(Tegra::Engines::ShaderType stage) {
|
||||||
switch (stage) {
|
switch (stage) {
|
||||||
case Maxwell::ShaderStage::Vertex:
|
case Tegra::Engines::ShaderType::Vertex:
|
||||||
return vk::ShaderStageFlagBits::eVertex;
|
return vk::ShaderStageFlagBits::eVertex;
|
||||||
case Maxwell::ShaderStage::TesselationControl:
|
case Tegra::Engines::ShaderType::TesselationControl:
|
||||||
return vk::ShaderStageFlagBits::eTessellationControl;
|
return vk::ShaderStageFlagBits::eTessellationControl;
|
||||||
case Maxwell::ShaderStage::TesselationEval:
|
case Tegra::Engines::ShaderType::TesselationEval:
|
||||||
return vk::ShaderStageFlagBits::eTessellationEvaluation;
|
return vk::ShaderStageFlagBits::eTessellationEvaluation;
|
||||||
case Maxwell::ShaderStage::Geometry:
|
case Tegra::Engines::ShaderType::Geometry:
|
||||||
return vk::ShaderStageFlagBits::eGeometry;
|
return vk::ShaderStageFlagBits::eGeometry;
|
||||||
case Maxwell::ShaderStage::Fragment:
|
case Tegra::Engines::ShaderType::Fragment:
|
||||||
return vk::ShaderStageFlagBits::eFragment;
|
return vk::ShaderStageFlagBits::eFragment;
|
||||||
}
|
}
|
||||||
UNIMPLEMENTED_MSG("Unimplemented shader stage={}", static_cast<u32>(stage));
|
UNIMPLEMENTED_MSG("Unimplemented shader stage={}", static_cast<u32>(stage));
|
||||||
|
|
|
@ -32,7 +32,7 @@ vk::CompareOp DepthCompareFunction(Tegra::Texture::DepthCompareFunc depth_compar
|
||||||
std::pair<vk::Format, bool> SurfaceFormat(const VKDevice& device, FormatType format_type,
|
std::pair<vk::Format, bool> SurfaceFormat(const VKDevice& device, FormatType format_type,
|
||||||
PixelFormat pixel_format);
|
PixelFormat pixel_format);
|
||||||
|
|
||||||
vk::ShaderStageFlagBits ShaderStage(Maxwell::ShaderStage stage);
|
vk::ShaderStageFlagBits ShaderStage(Tegra::Engines::ShaderType stage);
|
||||||
|
|
||||||
vk::PrimitiveTopology PrimitiveTopology(Maxwell::PrimitiveTopology topology);
|
vk::PrimitiveTopology PrimitiveTopology(Maxwell::PrimitiveTopology topology);
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "video_core/engines/maxwell_3d.h"
|
#include "video_core/engines/maxwell_3d.h"
|
||||||
#include "video_core/engines/shader_bytecode.h"
|
#include "video_core/engines/shader_bytecode.h"
|
||||||
#include "video_core/engines/shader_header.h"
|
#include "video_core/engines/shader_header.h"
|
||||||
|
#include "video_core/engines/shader_type.h"
|
||||||
#include "video_core/renderer_vulkan/vk_device.h"
|
#include "video_core/renderer_vulkan/vk_device.h"
|
||||||
#include "video_core/renderer_vulkan/vk_shader_decompiler.h"
|
#include "video_core/renderer_vulkan/vk_shader_decompiler.h"
|
||||||
#include "video_core/shader/node.h"
|
#include "video_core/shader/node.h"
|
||||||
|
@ -25,13 +26,13 @@
|
||||||
namespace Vulkan::VKShader {
|
namespace Vulkan::VKShader {
|
||||||
|
|
||||||
using Sirit::Id;
|
using Sirit::Id;
|
||||||
|
using Tegra::Engines::ShaderType;
|
||||||
using Tegra::Shader::Attribute;
|
using Tegra::Shader::Attribute;
|
||||||
using Tegra::Shader::AttributeUse;
|
using Tegra::Shader::AttributeUse;
|
||||||
using Tegra::Shader::Register;
|
using Tegra::Shader::Register;
|
||||||
using namespace VideoCommon::Shader;
|
using namespace VideoCommon::Shader;
|
||||||
|
|
||||||
using Maxwell = Tegra::Engines::Maxwell3D::Regs;
|
using Maxwell = Tegra::Engines::Maxwell3D::Regs;
|
||||||
using ShaderStage = Tegra::Engines::Maxwell3D::Regs::ShaderStage;
|
|
||||||
using Operation = const OperationNode&;
|
using Operation = const OperationNode&;
|
||||||
|
|
||||||
// TODO(Rodrigo): Use rasterizer's value
|
// TODO(Rodrigo): Use rasterizer's value
|
||||||
|
@ -93,7 +94,7 @@ class ExprDecompiler;
|
||||||
|
|
||||||
class SPIRVDecompiler : public Sirit::Module {
|
class SPIRVDecompiler : public Sirit::Module {
|
||||||
public:
|
public:
|
||||||
explicit SPIRVDecompiler(const VKDevice& device, const ShaderIR& ir, ShaderStage stage)
|
explicit SPIRVDecompiler(const VKDevice& device, const ShaderIR& ir, ShaderType stage)
|
||||||
: Module(0x00010300), device{device}, ir{ir}, stage{stage}, header{ir.GetHeader()} {
|
: Module(0x00010300), device{device}, ir{ir}, stage{stage}, header{ir.GetHeader()} {
|
||||||
AddCapability(spv::Capability::Shader);
|
AddCapability(spv::Capability::Shader);
|
||||||
AddExtension("SPV_KHR_storage_buffer_storage_class");
|
AddExtension("SPV_KHR_storage_buffer_storage_class");
|
||||||
|
@ -256,21 +257,21 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeclareVertex() {
|
void DeclareVertex() {
|
||||||
if (stage != ShaderStage::Vertex)
|
if (stage != ShaderType::Vertex)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
DeclareVertexRedeclarations();
|
DeclareVertexRedeclarations();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeclareGeometry() {
|
void DeclareGeometry() {
|
||||||
if (stage != ShaderStage::Geometry)
|
if (stage != ShaderType::Geometry)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
UNIMPLEMENTED();
|
UNIMPLEMENTED();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeclareFragment() {
|
void DeclareFragment() {
|
||||||
if (stage != ShaderStage::Fragment)
|
if (stage != ShaderType::Fragment)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (u32 rt = 0; rt < static_cast<u32>(frag_colors.size()); ++rt) {
|
for (u32 rt = 0; rt < static_cast<u32>(frag_colors.size()); ++rt) {
|
||||||
|
@ -354,7 +355,7 @@ private:
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
UNIMPLEMENTED_IF(stage == ShaderStage::Geometry);
|
UNIMPLEMENTED_IF(stage == ShaderType::Geometry);
|
||||||
|
|
||||||
const u32 location = GetGenericAttributeLocation(index);
|
const u32 location = GetGenericAttributeLocation(index);
|
||||||
const Id id = OpVariable(t_in_float4, spv::StorageClass::Input);
|
const Id id = OpVariable(t_in_float4, spv::StorageClass::Input);
|
||||||
|
@ -364,7 +365,7 @@ private:
|
||||||
|
|
||||||
Decorate(id, spv::Decoration::Location, location);
|
Decorate(id, spv::Decoration::Location, location);
|
||||||
|
|
||||||
if (stage != ShaderStage::Fragment) {
|
if (stage != ShaderType::Fragment) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
switch (header.ps.GetAttributeUse(location)) {
|
switch (header.ps.GetAttributeUse(location)) {
|
||||||
|
@ -548,7 +549,7 @@ private:
|
||||||
|
|
||||||
switch (attribute) {
|
switch (attribute) {
|
||||||
case Attribute::Index::Position:
|
case Attribute::Index::Position:
|
||||||
if (stage != ShaderStage::Fragment) {
|
if (stage != ShaderType::Fragment) {
|
||||||
UNIMPLEMENTED();
|
UNIMPLEMENTED();
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
|
@ -561,7 +562,7 @@ private:
|
||||||
// TODO(Subv): Find out what the values are for the first two elements when inside a
|
// TODO(Subv): Find out what the values are for the first two elements when inside a
|
||||||
// vertex shader, and what's the value of the fourth element when inside a Tess Eval
|
// vertex shader, and what's the value of the fourth element when inside a Tess Eval
|
||||||
// shader.
|
// shader.
|
||||||
ASSERT(stage == ShaderStage::Vertex);
|
ASSERT(stage == ShaderType::Vertex);
|
||||||
switch (element) {
|
switch (element) {
|
||||||
case 2:
|
case 2:
|
||||||
return BitcastFrom<Type::Uint>(Emit(OpLoad(t_uint, instance_index)));
|
return BitcastFrom<Type::Uint>(Emit(OpLoad(t_uint, instance_index)));
|
||||||
|
@ -572,7 +573,7 @@ private:
|
||||||
return Constant(t_float, 0);
|
return Constant(t_float, 0);
|
||||||
case Attribute::Index::FrontFacing:
|
case Attribute::Index::FrontFacing:
|
||||||
// TODO(Subv): Find out what the values are for the other elements.
|
// TODO(Subv): Find out what the values are for the other elements.
|
||||||
ASSERT(stage == ShaderStage::Fragment);
|
ASSERT(stage == ShaderType::Fragment);
|
||||||
if (element == 3) {
|
if (element == 3) {
|
||||||
const Id is_front_facing = Emit(OpLoad(t_bool, front_facing));
|
const Id is_front_facing = Emit(OpLoad(t_bool, front_facing));
|
||||||
const Id true_value =
|
const Id true_value =
|
||||||
|
@ -1075,7 +1076,7 @@ private:
|
||||||
|
|
||||||
Id PreExit() {
|
Id PreExit() {
|
||||||
switch (stage) {
|
switch (stage) {
|
||||||
case ShaderStage::Vertex: {
|
case ShaderType::Vertex: {
|
||||||
// TODO(Rodrigo): We should use VK_EXT_depth_range_unrestricted instead, but it doesn't
|
// TODO(Rodrigo): We should use VK_EXT_depth_range_unrestricted instead, but it doesn't
|
||||||
// seem to be working on Nvidia's drivers and Intel (mesa and blob) doesn't support it.
|
// seem to be working on Nvidia's drivers and Intel (mesa and blob) doesn't support it.
|
||||||
const Id z_pointer = AccessElement(t_out_float, per_vertex, position_index, 2u);
|
const Id z_pointer = AccessElement(t_out_float, per_vertex, position_index, 2u);
|
||||||
|
@ -1085,7 +1086,7 @@ private:
|
||||||
Emit(OpStore(z_pointer, depth));
|
Emit(OpStore(z_pointer, depth));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ShaderStage::Fragment: {
|
case ShaderType::Fragment: {
|
||||||
const auto SafeGetRegister = [&](u32 reg) {
|
const auto SafeGetRegister = [&](u32 reg) {
|
||||||
// TODO(Rodrigo): Replace with contains once C++20 releases
|
// TODO(Rodrigo): Replace with contains once C++20 releases
|
||||||
if (const auto it = registers.find(reg); it != registers.end()) {
|
if (const auto it = registers.find(reg); it != registers.end()) {
|
||||||
|
@ -1511,7 +1512,7 @@ private:
|
||||||
|
|
||||||
const VKDevice& device;
|
const VKDevice& device;
|
||||||
const ShaderIR& ir;
|
const ShaderIR& ir;
|
||||||
const ShaderStage stage;
|
const ShaderType stage;
|
||||||
const Tegra::Shader::Header header;
|
const Tegra::Shader::Header header;
|
||||||
u64 conditional_nest_count{};
|
u64 conditional_nest_count{};
|
||||||
u64 inside_branch{};
|
u64 inside_branch{};
|
||||||
|
@ -1843,7 +1844,7 @@ void SPIRVDecompiler::DecompileAST() {
|
||||||
}
|
}
|
||||||
|
|
||||||
DecompilerResult Decompile(const VKDevice& device, const VideoCommon::Shader::ShaderIR& ir,
|
DecompilerResult Decompile(const VKDevice& device, const VideoCommon::Shader::ShaderIR& ir,
|
||||||
Maxwell::ShaderStage stage) {
|
ShaderType stage) {
|
||||||
auto decompiler = std::make_unique<SPIRVDecompiler>(device, ir, stage);
|
auto decompiler = std::make_unique<SPIRVDecompiler>(device, ir, stage);
|
||||||
decompiler->Decompile();
|
decompiler->Decompile();
|
||||||
return {std::move(decompiler), decompiler->GetShaderEntries()};
|
return {std::move(decompiler), decompiler->GetShaderEntries()};
|
||||||
|
|
|
@ -79,6 +79,6 @@ struct ShaderEntries {
|
||||||
using DecompilerResult = std::pair<std::unique_ptr<Sirit::Module>, ShaderEntries>;
|
using DecompilerResult = std::pair<std::unique_ptr<Sirit::Module>, ShaderEntries>;
|
||||||
|
|
||||||
DecompilerResult Decompile(const VKDevice& device, const VideoCommon::Shader::ShaderIR& ir,
|
DecompilerResult Decompile(const VKDevice& device, const VideoCommon::Shader::ShaderIR& ir,
|
||||||
Maxwell::ShaderStage stage);
|
Tegra::Engines::ShaderType stage);
|
||||||
|
|
||||||
} // namespace Vulkan::VKShader
|
} // namespace Vulkan::VKShader
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "video_core/engines/maxwell_3d.h"
|
#include "video_core/engines/maxwell_3d.h"
|
||||||
|
#include "video_core/engines/shader_type.h"
|
||||||
#include "video_core/shader/const_buffer_locker.h"
|
#include "video_core/shader/const_buffer_locker.h"
|
||||||
|
|
||||||
namespace VideoCommon::Shader {
|
namespace VideoCommon::Shader {
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/hash.h"
|
#include "common/hash.h"
|
||||||
#include "video_core/engines/const_buffer_engine_interface.h"
|
#include "video_core/engines/const_buffer_engine_interface.h"
|
||||||
|
#include "video_core/engines/shader_type.h"
|
||||||
|
|
||||||
namespace VideoCommon::Shader {
|
namespace VideoCommon::Shader {
|
||||||
|
|
||||||
|
@ -20,7 +21,7 @@ using BindlessSamplerMap =
|
||||||
* The ConstBufferLocker is a class use to interface the 3D and compute engines with the shader
|
* The ConstBufferLocker is a class use to interface the 3D and compute engines with the shader
|
||||||
* compiler. with it, the shader can obtain required data from GPU state and store it for disk
|
* compiler. with it, the shader can obtain required data from GPU state and store it for disk
|
||||||
* shader compilation.
|
* shader compilation.
|
||||||
**/
|
*/
|
||||||
class ConstBufferLocker {
|
class ConstBufferLocker {
|
||||||
public:
|
public:
|
||||||
explicit ConstBufferLocker(Tegra::Engines::ShaderType shader_stage);
|
explicit ConstBufferLocker(Tegra::Engines::ShaderType shader_stage);
|
||||||
|
|
Loading…
Reference in a new issue