video_core: Move some common state management out of specific render backends. (#15)
This commit is contained in:
@@ -221,6 +221,42 @@ RasterizerAccelerated::VertexArrayInfo RasterizerAccelerated::AnalyzeVertexArray
|
|||||||
return {vertex_min, vertex_max, vs_input_size};
|
return {vertex_min, vertex_max, vs_input_size};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RasterizerAccelerated::SyncEntireState() {
|
||||||
|
// Sync renderer-specific fixed-function state
|
||||||
|
SyncFixedState();
|
||||||
|
|
||||||
|
// Sync uniforms
|
||||||
|
SyncClipCoef();
|
||||||
|
SyncDepthScale();
|
||||||
|
SyncDepthOffset();
|
||||||
|
SyncAlphaTest();
|
||||||
|
SyncCombinerColor();
|
||||||
|
auto& tev_stages = Pica::g_state.regs.texturing.GetTevStages();
|
||||||
|
for (std::size_t index = 0; index < tev_stages.size(); ++index)
|
||||||
|
SyncTevConstColor(index, tev_stages[index]);
|
||||||
|
|
||||||
|
SyncGlobalAmbient();
|
||||||
|
for (unsigned light_index = 0; light_index < 8; light_index++) {
|
||||||
|
SyncLightSpecular0(light_index);
|
||||||
|
SyncLightSpecular1(light_index);
|
||||||
|
SyncLightDiffuse(light_index);
|
||||||
|
SyncLightAmbient(light_index);
|
||||||
|
SyncLightPosition(light_index);
|
||||||
|
SyncLightDistanceAttenuationBias(light_index);
|
||||||
|
SyncLightDistanceAttenuationScale(light_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
SyncFogColor();
|
||||||
|
SyncProcTexNoise();
|
||||||
|
SyncProcTexBias();
|
||||||
|
SyncShadowBias();
|
||||||
|
SyncShadowTextureBias();
|
||||||
|
|
||||||
|
for (unsigned tex_index = 0; tex_index < 3; tex_index++) {
|
||||||
|
SyncTextureLodBias(tex_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RasterizerAccelerated::NotifyPicaRegisterChanged(u32 id) {
|
void RasterizerAccelerated::NotifyPicaRegisterChanged(u32 id) {
|
||||||
const auto& regs = Pica::g_state.regs;
|
const auto& regs = Pica::g_state.regs;
|
||||||
|
|
||||||
@@ -655,6 +691,14 @@ void RasterizerAccelerated::NotifyPicaRegisterChanged(u32 id) {
|
|||||||
SyncTextureLodBias(2);
|
SyncTextureLodBias(2);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// Clipping plane
|
||||||
|
case PICA_REG_INDEX(rasterizer.clip_coef[0]):
|
||||||
|
case PICA_REG_INDEX(rasterizer.clip_coef[1]):
|
||||||
|
case PICA_REG_INDEX(rasterizer.clip_coef[2]):
|
||||||
|
case PICA_REG_INDEX(rasterizer.clip_coef[3]):
|
||||||
|
SyncClipCoef();
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Forward registers that map to fixed function API features to the video backend
|
// Forward registers that map to fixed function API features to the video backend
|
||||||
NotifyFixedFunctionPicaRegisterChanged(id);
|
NotifyFixedFunctionPicaRegisterChanged(id);
|
||||||
@@ -682,40 +726,52 @@ void RasterizerAccelerated::SyncDepthOffset() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerAccelerated::SyncFogColor() {
|
void RasterizerAccelerated::SyncFogColor() {
|
||||||
const auto& regs = Pica::g_state.regs;
|
const auto& fog_color_regs = Pica::g_state.regs.texturing.fog_color;
|
||||||
uniform_block_data.data.fog_color = {
|
const Common::Vec3f fog_color = {
|
||||||
regs.texturing.fog_color.r.Value() / 255.0f,
|
fog_color_regs.r.Value() / 255.0f,
|
||||||
regs.texturing.fog_color.g.Value() / 255.0f,
|
fog_color_regs.g.Value() / 255.0f,
|
||||||
regs.texturing.fog_color.b.Value() / 255.0f,
|
fog_color_regs.b.Value() / 255.0f,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (fog_color != uniform_block_data.data.fog_color) {
|
||||||
|
uniform_block_data.data.fog_color = fog_color;
|
||||||
uniform_block_data.dirty = true;
|
uniform_block_data.dirty = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerAccelerated::SyncProcTexNoise() {
|
void RasterizerAccelerated::SyncProcTexNoise() {
|
||||||
const auto& regs = Pica::g_state.regs.texturing;
|
const auto& regs = Pica::g_state.regs.texturing;
|
||||||
uniform_block_data.data.proctex_noise_f = {
|
const Common::Vec2f proctex_noise_f = {
|
||||||
Pica::float16::FromRaw(regs.proctex_noise_frequency.u).ToFloat32(),
|
Pica::float16::FromRaw(regs.proctex_noise_frequency.u).ToFloat32(),
|
||||||
Pica::float16::FromRaw(regs.proctex_noise_frequency.v).ToFloat32(),
|
Pica::float16::FromRaw(regs.proctex_noise_frequency.v).ToFloat32(),
|
||||||
};
|
};
|
||||||
uniform_block_data.data.proctex_noise_a = {
|
const Common::Vec2f proctex_noise_a = {
|
||||||
regs.proctex_noise_u.amplitude / 4095.0f,
|
regs.proctex_noise_u.amplitude / 4095.0f,
|
||||||
regs.proctex_noise_v.amplitude / 4095.0f,
|
regs.proctex_noise_v.amplitude / 4095.0f,
|
||||||
};
|
};
|
||||||
uniform_block_data.data.proctex_noise_p = {
|
const Common::Vec2f proctex_noise_p = {
|
||||||
Pica::float16::FromRaw(regs.proctex_noise_u.phase).ToFloat32(),
|
Pica::float16::FromRaw(regs.proctex_noise_u.phase).ToFloat32(),
|
||||||
Pica::float16::FromRaw(regs.proctex_noise_v.phase).ToFloat32(),
|
Pica::float16::FromRaw(regs.proctex_noise_v.phase).ToFloat32(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (proctex_noise_f != uniform_block_data.data.proctex_noise_f ||
|
||||||
|
proctex_noise_a != uniform_block_data.data.proctex_noise_a ||
|
||||||
|
proctex_noise_p != uniform_block_data.data.proctex_noise_p) {
|
||||||
|
uniform_block_data.data.proctex_noise_f = proctex_noise_f;
|
||||||
|
uniform_block_data.data.proctex_noise_a = proctex_noise_a;
|
||||||
|
uniform_block_data.data.proctex_noise_p = proctex_noise_p;
|
||||||
uniform_block_data.dirty = true;
|
uniform_block_data.dirty = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerAccelerated::SyncProcTexBias() {
|
void RasterizerAccelerated::SyncProcTexBias() {
|
||||||
const auto& regs = Pica::g_state.regs.texturing;
|
const auto& regs = Pica::g_state.regs.texturing;
|
||||||
uniform_block_data.data.proctex_bias =
|
const auto proctex_bias = Pica::float16::FromRaw(regs.proctex.bias_low |
|
||||||
Pica::float16::FromRaw(regs.proctex.bias_low | (regs.proctex_lut.bias_high << 8))
|
(regs.proctex_lut.bias_high << 8)).ToFloat32();
|
||||||
.ToFloat32();
|
if (proctex_bias != uniform_block_data.data.proctex_bias) {
|
||||||
|
uniform_block_data.data.proctex_bias = proctex_bias;
|
||||||
uniform_block_data.dirty = true;
|
uniform_block_data.dirty = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerAccelerated::SyncAlphaTest() {
|
void RasterizerAccelerated::SyncAlphaTest() {
|
||||||
@@ -790,7 +846,8 @@ void RasterizerAccelerated::SyncLightPosition(int light_index) {
|
|||||||
const Common::Vec3f position = {
|
const Common::Vec3f position = {
|
||||||
Pica::float16::FromRaw(Pica::g_state.regs.lighting.light[light_index].x).ToFloat32(),
|
Pica::float16::FromRaw(Pica::g_state.regs.lighting.light[light_index].x).ToFloat32(),
|
||||||
Pica::float16::FromRaw(Pica::g_state.regs.lighting.light[light_index].y).ToFloat32(),
|
Pica::float16::FromRaw(Pica::g_state.regs.lighting.light[light_index].y).ToFloat32(),
|
||||||
Pica::float16::FromRaw(Pica::g_state.regs.lighting.light[light_index].z).ToFloat32()};
|
Pica::float16::FromRaw(Pica::g_state.regs.lighting.light[light_index].z).ToFloat32(),
|
||||||
|
};
|
||||||
|
|
||||||
if (position != uniform_block_data.data.light_src[light_index].position) {
|
if (position != uniform_block_data.data.light_src[light_index].position) {
|
||||||
uniform_block_data.data.light_src[light_index].position = position;
|
uniform_block_data.data.light_src[light_index].position = position;
|
||||||
@@ -861,4 +918,14 @@ void RasterizerAccelerated::SyncTextureLodBias(int tex_index) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RasterizerAccelerated::SyncClipCoef() {
|
||||||
|
const auto raw_clip_coef = Pica::g_state.regs.rasterizer.GetClipCoef();
|
||||||
|
const Common::Vec4f new_clip_coef = {raw_clip_coef.x.ToFloat32(), raw_clip_coef.y.ToFloat32(),
|
||||||
|
raw_clip_coef.z.ToFloat32(), raw_clip_coef.w.ToFloat32()};
|
||||||
|
if (new_clip_coef != uniform_block_data.data.clip_coef) {
|
||||||
|
uniform_block_data.data.clip_coef = new_clip_coef;
|
||||||
|
uniform_block_data.dirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace VideoCore
|
} // namespace VideoCore
|
||||||
|
@@ -23,6 +23,12 @@ public:
|
|||||||
void NotifyPicaRegisterChanged(u32 id) override;
|
void NotifyPicaRegisterChanged(u32 id) override;
|
||||||
void ClearAll(bool flush) override;
|
void ClearAll(bool flush) override;
|
||||||
|
|
||||||
|
/// Syncs entire status to match PICA registers
|
||||||
|
void SyncEntireState() override;
|
||||||
|
|
||||||
|
/// Sync fixed-function pipeline state
|
||||||
|
virtual void SyncFixedState() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// Notifies that a fixed function PICA register changed to the video backend
|
/// Notifies that a fixed function PICA register changed to the video backend
|
||||||
virtual void NotifyFixedFunctionPicaRegisterChanged(u32 id) = 0;
|
virtual void NotifyFixedFunctionPicaRegisterChanged(u32 id) = 0;
|
||||||
@@ -88,6 +94,9 @@ protected:
|
|||||||
/// Syncs the texture LOD bias to match the PICA register
|
/// Syncs the texture LOD bias to match the PICA register
|
||||||
void SyncTextureLodBias(int tex_index);
|
void SyncTextureLodBias(int tex_index);
|
||||||
|
|
||||||
|
/// Syncs the clip coefficients to match the PICA register
|
||||||
|
void SyncClipCoef();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// Structure that keeps tracks of the uniform state
|
/// Structure that keeps tracks of the uniform state
|
||||||
struct UniformBlockData {
|
struct UniformBlockData {
|
||||||
|
@@ -60,9 +60,9 @@ RasterizerOpenGL::RasterizerOpenGL(Frontend::EmuWindow& emu_window, Driver& driv
|
|||||||
|
|
||||||
glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &uniform_buffer_alignment);
|
glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &uniform_buffer_alignment);
|
||||||
uniform_size_aligned_vs =
|
uniform_size_aligned_vs =
|
||||||
Common::AlignUp<std::size_t>(sizeof(VSUniformData), uniform_buffer_alignment);
|
Common::AlignUp<std::size_t>(sizeof(Pica::Shader::VSUniformData), uniform_buffer_alignment);
|
||||||
uniform_size_aligned_fs =
|
uniform_size_aligned_fs =
|
||||||
Common::AlignUp<std::size_t>(sizeof(UniformData), uniform_buffer_alignment);
|
Common::AlignUp<std::size_t>(sizeof(Pica::Shader::UniformData), uniform_buffer_alignment);
|
||||||
|
|
||||||
// Set vertex attributes for software shader path
|
// Set vertex attributes for software shader path
|
||||||
state.draw.vertex_array = sw_vao.handle;
|
state.draw.vertex_array = sw_vao.handle;
|
||||||
@@ -136,8 +136,7 @@ void RasterizerOpenGL::LoadDiskResources(const std::atomic_bool& stop_loading,
|
|||||||
shader_program_manager.LoadDiskCache(stop_loading, callback);
|
shader_program_manager.LoadDiskCache(stop_loading, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SyncEntireState() {
|
void RasterizerOpenGL::SyncFixedState() {
|
||||||
// Sync fixed function OpenGL state
|
|
||||||
SyncClipEnabled();
|
SyncClipEnabled();
|
||||||
SyncCullMode();
|
SyncCullMode();
|
||||||
SyncBlendEnabled();
|
SyncBlendEnabled();
|
||||||
@@ -149,37 +148,6 @@ void RasterizerOpenGL::SyncEntireState() {
|
|||||||
SyncColorWriteMask();
|
SyncColorWriteMask();
|
||||||
SyncStencilWriteMask();
|
SyncStencilWriteMask();
|
||||||
SyncDepthWriteMask();
|
SyncDepthWriteMask();
|
||||||
|
|
||||||
// Sync uniforms
|
|
||||||
SyncClipCoef();
|
|
||||||
SyncDepthScale();
|
|
||||||
SyncDepthOffset();
|
|
||||||
SyncAlphaTest();
|
|
||||||
SyncCombinerColor();
|
|
||||||
auto& tev_stages = Pica::g_state.regs.texturing.GetTevStages();
|
|
||||||
for (std::size_t index = 0; index < tev_stages.size(); ++index)
|
|
||||||
SyncTevConstColor(index, tev_stages[index]);
|
|
||||||
|
|
||||||
SyncGlobalAmbient();
|
|
||||||
for (unsigned light_index = 0; light_index < 8; light_index++) {
|
|
||||||
SyncLightSpecular0(light_index);
|
|
||||||
SyncLightSpecular1(light_index);
|
|
||||||
SyncLightDiffuse(light_index);
|
|
||||||
SyncLightAmbient(light_index);
|
|
||||||
SyncLightPosition(light_index);
|
|
||||||
SyncLightDistanceAttenuationBias(light_index);
|
|
||||||
SyncLightDistanceAttenuationScale(light_index);
|
|
||||||
}
|
|
||||||
|
|
||||||
SyncFogColor();
|
|
||||||
SyncProcTexNoise();
|
|
||||||
SyncProcTexBias();
|
|
||||||
SyncShadowBias();
|
|
||||||
SyncShadowTextureBias();
|
|
||||||
|
|
||||||
for (unsigned tex_index = 0; tex_index < 3; tex_index++) {
|
|
||||||
SyncTextureLodBias(tex_index);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr std::array<GLenum, 4> vs_attrib_types{
|
static constexpr std::array<GLenum, 4> vs_attrib_types{
|
||||||
@@ -717,30 +685,22 @@ bool RasterizerOpenGL::Draw(bool accelerate, bool is_indexed) {
|
|||||||
|
|
||||||
void RasterizerOpenGL::NotifyFixedFunctionPicaRegisterChanged(u32 id) {
|
void RasterizerOpenGL::NotifyFixedFunctionPicaRegisterChanged(u32 id) {
|
||||||
switch (id) {
|
switch (id) {
|
||||||
// Culling
|
|
||||||
case PICA_REG_INDEX(rasterizer.cull_mode):
|
|
||||||
SyncCullMode();
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Clipping plane
|
// Clipping plane
|
||||||
case PICA_REG_INDEX(rasterizer.clip_enable):
|
case PICA_REG_INDEX(rasterizer.clip_enable):
|
||||||
SyncClipEnabled();
|
SyncClipEnabled();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PICA_REG_INDEX(rasterizer.clip_coef[0]):
|
// Culling
|
||||||
case PICA_REG_INDEX(rasterizer.clip_coef[1]):
|
case PICA_REG_INDEX(rasterizer.cull_mode):
|
||||||
case PICA_REG_INDEX(rasterizer.clip_coef[2]):
|
SyncCullMode();
|
||||||
case PICA_REG_INDEX(rasterizer.clip_coef[3]):
|
|
||||||
SyncClipCoef();
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Blending
|
// Blending
|
||||||
case PICA_REG_INDEX(framebuffer.output_merger.alphablend_enable):
|
case PICA_REG_INDEX(framebuffer.output_merger.alphablend_enable):
|
||||||
if (driver.IsOpenGLES()) {
|
|
||||||
// With GLES, we need this in the fragment shader to emulate logic operations
|
|
||||||
shader_dirty = true;
|
|
||||||
}
|
|
||||||
SyncBlendEnabled();
|
SyncBlendEnabled();
|
||||||
|
// Update since logic op emulation depends on alpha blend enable.
|
||||||
|
SyncLogicOp();
|
||||||
|
SyncColorWriteMask();
|
||||||
break;
|
break;
|
||||||
case PICA_REG_INDEX(framebuffer.output_merger.alpha_blending):
|
case PICA_REG_INDEX(framebuffer.output_merger.alpha_blending):
|
||||||
SyncBlendFuncs();
|
SyncBlendFuncs();
|
||||||
@@ -783,11 +743,9 @@ void RasterizerOpenGL::NotifyFixedFunctionPicaRegisterChanged(u32 id) {
|
|||||||
|
|
||||||
// Logic op
|
// Logic op
|
||||||
case PICA_REG_INDEX(framebuffer.output_merger.logic_op):
|
case PICA_REG_INDEX(framebuffer.output_merger.logic_op):
|
||||||
if (driver.IsOpenGLES()) {
|
|
||||||
// With GLES, we need this in the fragment shader to emulate logic operations
|
|
||||||
shader_dirty = true;
|
|
||||||
}
|
|
||||||
SyncLogicOp();
|
SyncLogicOp();
|
||||||
|
// Update since color write mask is used to emulate no-op.
|
||||||
|
SyncColorWriteMask();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1066,16 +1024,6 @@ void RasterizerOpenGL::SyncClipEnabled() {
|
|||||||
state.clip_distance[1] = Pica::g_state.regs.rasterizer.clip_enable != 0;
|
state.clip_distance[1] = Pica::g_state.regs.rasterizer.clip_enable != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SyncClipCoef() {
|
|
||||||
const auto raw_clip_coef = Pica::g_state.regs.rasterizer.GetClipCoef();
|
|
||||||
const Common::Vec4f new_clip_coef = {raw_clip_coef.x.ToFloat32(), raw_clip_coef.y.ToFloat32(),
|
|
||||||
raw_clip_coef.z.ToFloat32(), raw_clip_coef.w.ToFloat32()};
|
|
||||||
if (new_clip_coef != uniform_block_data.data.clip_coef) {
|
|
||||||
uniform_block_data.data.clip_coef = new_clip_coef;
|
|
||||||
uniform_block_data.dirty = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RasterizerOpenGL::SyncCullMode() {
|
void RasterizerOpenGL::SyncCullMode() {
|
||||||
const auto& regs = Pica::g_state.regs;
|
const auto& regs = Pica::g_state.regs;
|
||||||
|
|
||||||
@@ -1132,6 +1080,11 @@ void RasterizerOpenGL::SyncBlendColor() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SyncLogicOp() {
|
void RasterizerOpenGL::SyncLogicOp() {
|
||||||
|
if (driver.IsOpenGLES()) {
|
||||||
|
// With GLES, we need this in the fragment shader to emulate logic operations
|
||||||
|
shader_dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
const auto& regs = Pica::g_state.regs;
|
const auto& regs = Pica::g_state.regs;
|
||||||
state.logic_op = PicaToGL::LogicOp(regs.framebuffer.output_merger.logic_op);
|
state.logic_op = PicaToGL::LogicOp(regs.framebuffer.output_merger.logic_op);
|
||||||
|
|
||||||
@@ -1410,18 +1363,18 @@ void RasterizerOpenGL::UploadUniforms(bool accelerate_draw) {
|
|||||||
uniform_buffer.Map(uniform_size, uniform_buffer_alignment);
|
uniform_buffer.Map(uniform_size, uniform_buffer_alignment);
|
||||||
|
|
||||||
if (sync_vs) {
|
if (sync_vs) {
|
||||||
VSUniformData vs_uniforms;
|
Pica::Shader::VSUniformData vs_uniforms;
|
||||||
vs_uniforms.uniforms.SetFromRegs(Pica::g_state.regs.vs, Pica::g_state.vs);
|
vs_uniforms.uniforms.SetFromRegs(Pica::g_state.regs.vs, Pica::g_state.vs);
|
||||||
std::memcpy(uniforms + used_bytes, &vs_uniforms, sizeof(vs_uniforms));
|
std::memcpy(uniforms + used_bytes, &vs_uniforms, sizeof(vs_uniforms));
|
||||||
glBindBufferRange(GL_UNIFORM_BUFFER, static_cast<GLuint>(UniformBindings::VS),
|
glBindBufferRange(GL_UNIFORM_BUFFER, static_cast<GLuint>(Pica::Shader::UniformBindings::VS),
|
||||||
uniform_buffer.GetHandle(), offset + used_bytes, sizeof(VSUniformData));
|
uniform_buffer.GetHandle(), offset + used_bytes, sizeof(vs_uniforms));
|
||||||
used_bytes += uniform_size_aligned_vs;
|
used_bytes += uniform_size_aligned_vs;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sync_fs || invalidate) {
|
if (sync_fs || invalidate) {
|
||||||
std::memcpy(uniforms + used_bytes, &uniform_block_data.data, sizeof(UniformData));
|
std::memcpy(uniforms + used_bytes, &uniform_block_data.data, sizeof(Pica::Shader::UniformData));
|
||||||
glBindBufferRange(GL_UNIFORM_BUFFER, static_cast<GLuint>(UniformBindings::Common),
|
glBindBufferRange(GL_UNIFORM_BUFFER, static_cast<GLuint>(Pica::Shader::UniformBindings::Common),
|
||||||
uniform_buffer.GetHandle(), offset + used_bytes, sizeof(UniformData));
|
uniform_buffer.GetHandle(), offset + used_bytes, sizeof(Pica::Shader::UniformData));
|
||||||
uniform_block_data.dirty = false;
|
uniform_block_data.dirty = false;
|
||||||
used_bytes += uniform_size_aligned_fs;
|
used_bytes += uniform_size_aligned_fs;
|
||||||
}
|
}
|
||||||
|
@@ -42,8 +42,7 @@ public:
|
|||||||
u32 pixel_stride, ScreenInfo& screen_info);
|
u32 pixel_stride, ScreenInfo& screen_info);
|
||||||
bool AccelerateDrawBatch(bool is_indexed) override;
|
bool AccelerateDrawBatch(bool is_indexed) override;
|
||||||
|
|
||||||
/// Syncs entire status to match PICA registers
|
void SyncFixedState() override;
|
||||||
void SyncEntireState() override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct SamplerInfo {
|
struct SamplerInfo {
|
||||||
@@ -76,9 +75,6 @@ private:
|
|||||||
/// Syncs the clip enabled status to match the PICA register
|
/// Syncs the clip enabled status to match the PICA register
|
||||||
void SyncClipEnabled();
|
void SyncClipEnabled();
|
||||||
|
|
||||||
/// Syncs the clip coefficients to match the PICA register
|
|
||||||
void SyncClipCoef();
|
|
||||||
|
|
||||||
/// Sets the OpenGL shader in accordance with the current PICA register state
|
/// Sets the OpenGL shader in accordance with the current PICA register state
|
||||||
void SetShader();
|
void SetShader();
|
||||||
|
|
||||||
|
@@ -12,6 +12,7 @@
|
|||||||
#include "video_core/renderer_opengl/gl_shader_gen.h"
|
#include "video_core/renderer_opengl/gl_shader_gen.h"
|
||||||
#include "video_core/renderer_opengl/gl_shader_util.h"
|
#include "video_core/renderer_opengl/gl_shader_util.h"
|
||||||
#include "video_core/renderer_opengl/gl_vars.h"
|
#include "video_core/renderer_opengl/gl_vars.h"
|
||||||
|
#include "video_core/shader/shader_uniforms.h"
|
||||||
#include "video_core/video_core.h"
|
#include "video_core/video_core.h"
|
||||||
|
|
||||||
using Pica::FramebufferRegs;
|
using Pica::FramebufferRegs;
|
||||||
@@ -23,54 +24,7 @@ using VSOutputAttributes = RasterizerRegs::VSOutputAttributes;
|
|||||||
|
|
||||||
namespace OpenGL {
|
namespace OpenGL {
|
||||||
|
|
||||||
constexpr std::string_view UniformBlockDef = R"(
|
const std::string UniformBlockDef = Pica::Shader::BuildShaderUniformDefinitions();
|
||||||
#define NUM_TEV_STAGES 6
|
|
||||||
#define NUM_LIGHTS 8
|
|
||||||
#define NUM_LIGHTING_SAMPLERS 24
|
|
||||||
|
|
||||||
struct LightSrc {
|
|
||||||
vec3 specular_0;
|
|
||||||
vec3 specular_1;
|
|
||||||
vec3 diffuse;
|
|
||||||
vec3 ambient;
|
|
||||||
vec3 position;
|
|
||||||
vec3 spot_direction;
|
|
||||||
float dist_atten_bias;
|
|
||||||
float dist_atten_scale;
|
|
||||||
};
|
|
||||||
|
|
||||||
layout (std140) uniform shader_data {
|
|
||||||
int framebuffer_scale;
|
|
||||||
int alphatest_ref;
|
|
||||||
float depth_scale;
|
|
||||||
float depth_offset;
|
|
||||||
float shadow_bias_constant;
|
|
||||||
float shadow_bias_linear;
|
|
||||||
int scissor_x1;
|
|
||||||
int scissor_y1;
|
|
||||||
int scissor_x2;
|
|
||||||
int scissor_y2;
|
|
||||||
int fog_lut_offset;
|
|
||||||
int proctex_noise_lut_offset;
|
|
||||||
int proctex_color_map_offset;
|
|
||||||
int proctex_alpha_map_offset;
|
|
||||||
int proctex_lut_offset;
|
|
||||||
int proctex_diff_lut_offset;
|
|
||||||
float proctex_bias;
|
|
||||||
int shadow_texture_bias;
|
|
||||||
ivec4 lighting_lut_offset[NUM_LIGHTING_SAMPLERS / 4];
|
|
||||||
vec3 fog_color;
|
|
||||||
vec2 proctex_noise_f;
|
|
||||||
vec2 proctex_noise_a;
|
|
||||||
vec2 proctex_noise_p;
|
|
||||||
vec3 lighting_global_ambient;
|
|
||||||
LightSrc light_src[NUM_LIGHTS];
|
|
||||||
vec4 const_color[NUM_TEV_STAGES];
|
|
||||||
vec4 tev_combiner_buffer_color;
|
|
||||||
vec3 tex_lod_bias;
|
|
||||||
vec4 clip_coef;
|
|
||||||
};
|
|
||||||
)";
|
|
||||||
|
|
||||||
static std::string GetVertexInterfaceDeclaration(bool is_output, bool separable_shader) {
|
static std::string GetVertexInterfaceDeclaration(bool is_output, bool separable_shader) {
|
||||||
std::string out;
|
std::string out;
|
||||||
|
@@ -12,6 +12,7 @@
|
|||||||
#include "video_core/renderer_opengl/gl_shader_disk_cache.h"
|
#include "video_core/renderer_opengl/gl_shader_disk_cache.h"
|
||||||
#include "video_core/renderer_opengl/gl_shader_manager.h"
|
#include "video_core/renderer_opengl/gl_shader_manager.h"
|
||||||
#include "video_core/renderer_opengl/gl_state.h"
|
#include "video_core/renderer_opengl/gl_state.h"
|
||||||
|
#include "video_core/shader/shader_uniforms.h"
|
||||||
#include "video_core/video_core.h"
|
#include "video_core/video_core.h"
|
||||||
|
|
||||||
namespace OpenGL {
|
namespace OpenGL {
|
||||||
@@ -84,7 +85,7 @@ static std::tuple<PicaVSConfig, Pica::Shader::ShaderSetup> BuildVSConfigFromRaw(
|
|||||||
return {PicaVSConfig{raw.GetRawShaderConfig().vs, setup}, setup};
|
return {PicaVSConfig{raw.GetRawShaderConfig().vs, setup}, setup};
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SetShaderUniformBlockBinding(GLuint shader, const char* name, UniformBindings binding,
|
static void SetShaderUniformBlockBinding(GLuint shader, const char* name, Pica::Shader::UniformBindings binding,
|
||||||
std::size_t expected_size) {
|
std::size_t expected_size) {
|
||||||
const GLuint ub_index = glGetUniformBlockIndex(shader, name);
|
const GLuint ub_index = glGetUniformBlockIndex(shader, name);
|
||||||
if (ub_index == GL_INVALID_INDEX) {
|
if (ub_index == GL_INVALID_INDEX) {
|
||||||
@@ -99,9 +100,10 @@ static void SetShaderUniformBlockBinding(GLuint shader, const char* name, Unifor
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void SetShaderUniformBlockBindings(GLuint shader) {
|
static void SetShaderUniformBlockBindings(GLuint shader) {
|
||||||
SetShaderUniformBlockBinding(shader, "shader_data", UniformBindings::Common,
|
SetShaderUniformBlockBinding(shader, "shader_data", Pica::Shader::UniformBindings::Common,
|
||||||
sizeof(UniformData));
|
sizeof(Pica::Shader::UniformData));
|
||||||
SetShaderUniformBlockBinding(shader, "vs_config", UniformBindings::VS, sizeof(VSUniformData));
|
SetShaderUniformBlockBinding(shader, "vs_config", Pica::Shader::UniformBindings::VS,
|
||||||
|
sizeof(Pica::Shader::VSUniformData));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SetShaderSamplerBinding(GLuint shader, const char* name,
|
static void SetShaderSamplerBinding(GLuint shader, const char* name,
|
||||||
@@ -147,21 +149,6 @@ static void SetShaderSamplerBindings(GLuint shader) {
|
|||||||
cur_state.Apply();
|
cur_state.Apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PicaUniformsData::SetFromRegs(const Pica::ShaderRegs& regs,
|
|
||||||
const Pica::Shader::ShaderSetup& setup) {
|
|
||||||
std::transform(std::begin(setup.uniforms.b), std::end(setup.uniforms.b), std::begin(bools),
|
|
||||||
[](bool value) -> BoolAligned { return {value ? GL_TRUE : GL_FALSE}; });
|
|
||||||
std::transform(std::begin(regs.int_uniforms), std::end(regs.int_uniforms), std::begin(i),
|
|
||||||
[](const auto& value) -> Common::Vec4u {
|
|
||||||
return {value.x.Value(), value.y.Value(), value.z.Value(), value.w.Value()};
|
|
||||||
});
|
|
||||||
std::transform(std::begin(setup.uniforms.f), std::end(setup.uniforms.f), std::begin(f),
|
|
||||||
[](const auto& value) -> Common::Vec4f {
|
|
||||||
return {value.x.ToFloat32(), value.y.ToFloat32(), value.z.ToFloat32(),
|
|
||||||
value.w.ToFloat32()};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An object representing a shader program staging. It can be either a shader object or a program
|
* An object representing a shader program staging. It can be either a shader object or a program
|
||||||
* object, depending on whether separable program is used.
|
* object, depending on whether separable program is used.
|
||||||
|
@@ -28,86 +28,6 @@ struct ShaderSetup;
|
|||||||
|
|
||||||
namespace OpenGL {
|
namespace OpenGL {
|
||||||
|
|
||||||
enum class UniformBindings : u32 { Common, VS, GS };
|
|
||||||
|
|
||||||
struct LightSrc {
|
|
||||||
alignas(16) Common::Vec3f specular_0;
|
|
||||||
alignas(16) Common::Vec3f specular_1;
|
|
||||||
alignas(16) Common::Vec3f diffuse;
|
|
||||||
alignas(16) Common::Vec3f ambient;
|
|
||||||
alignas(16) Common::Vec3f position;
|
|
||||||
alignas(16) Common::Vec3f spot_direction; // negated
|
|
||||||
float dist_atten_bias;
|
|
||||||
float dist_atten_scale;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Uniform structure for the Uniform Buffer Object, all vectors must be 16-byte aligned
|
|
||||||
* NOTE: Always keep a vec4 at the end. The GL spec is not clear wether 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 UniformData {
|
|
||||||
int framebuffer_scale;
|
|
||||||
int alphatest_ref;
|
|
||||||
float depth_scale;
|
|
||||||
float depth_offset;
|
|
||||||
float shadow_bias_constant;
|
|
||||||
float shadow_bias_linear;
|
|
||||||
int scissor_x1;
|
|
||||||
int scissor_y1;
|
|
||||||
int scissor_x2;
|
|
||||||
int scissor_y2;
|
|
||||||
int fog_lut_offset;
|
|
||||||
int proctex_noise_lut_offset;
|
|
||||||
int proctex_color_map_offset;
|
|
||||||
int proctex_alpha_map_offset;
|
|
||||||
int proctex_lut_offset;
|
|
||||||
int proctex_diff_lut_offset;
|
|
||||||
float proctex_bias;
|
|
||||||
int shadow_texture_bias;
|
|
||||||
alignas(16) Common::Vec4i lighting_lut_offset[Pica::LightingRegs::NumLightingSampler / 4];
|
|
||||||
alignas(16) Common::Vec3f fog_color;
|
|
||||||
alignas(8) Common::Vec2f proctex_noise_f;
|
|
||||||
alignas(8) Common::Vec2f proctex_noise_a;
|
|
||||||
alignas(8) Common::Vec2f proctex_noise_p;
|
|
||||||
alignas(16) Common::Vec3f lighting_global_ambient;
|
|
||||||
LightSrc light_src[8];
|
|
||||||
alignas(16) Common::Vec4f const_color[6]; // A vec4 color for each of the six tev stages
|
|
||||||
alignas(16) Common::Vec4f tev_combiner_buffer_color;
|
|
||||||
alignas(16) Common::Vec3f tex_lod_bias;
|
|
||||||
alignas(16) Common::Vec4f clip_coef;
|
|
||||||
};
|
|
||||||
|
|
||||||
static_assert(sizeof(UniformData) == 0x500,
|
|
||||||
"The size of the UniformData does not match the structure in the shader");
|
|
||||||
static_assert(sizeof(UniformData) < 16384,
|
|
||||||
"UniformData structure must be less than 16kb as per the OpenGL spec");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Uniform struct for the Uniform Buffer Object that contains PICA vertex/geometry shader uniforms.
|
|
||||||
* NOTE: the same rule from UniformData also applies here.
|
|
||||||
*/
|
|
||||||
struct PicaUniformsData {
|
|
||||||
void SetFromRegs(const Pica::ShaderRegs& regs, const Pica::Shader::ShaderSetup& setup);
|
|
||||||
|
|
||||||
struct BoolAligned {
|
|
||||||
alignas(16) int b;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::array<BoolAligned, 16> bools;
|
|
||||||
alignas(16) std::array<Common::Vec4u, 4> i;
|
|
||||||
alignas(16) std::array<Common::Vec4f, 96> f;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct VSUniformData {
|
|
||||||
PicaUniformsData uniforms;
|
|
||||||
};
|
|
||||||
static_assert(sizeof(VSUniformData) == 1856,
|
|
||||||
"The size of the VSUniformData does not match the structure in the shader");
|
|
||||||
static_assert(sizeof(VSUniformData) < 16384,
|
|
||||||
"VSUniformData structure must be less than 16kb as per the OpenGL spec");
|
|
||||||
|
|
||||||
class Driver;
|
class Driver;
|
||||||
class OpenGLState;
|
class OpenGLState;
|
||||||
|
|
||||||
|
@@ -42,8 +42,9 @@ DebugHandler(VkDebugUtilsMessageSeverityFlagBitsEXT severity, VkDebugUtilsMessag
|
|||||||
level = Log::Level::Info;
|
level = Log::Level::Info;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_GENERIC(Log::Class::Render_Vulkan, level, "{}: {}", callback_data->pMessageIdName,
|
LOG_GENERIC(Log::Class::Render_Vulkan, level, "{}: {}",
|
||||||
callback_data->pMessage);
|
callback_data->pMessageIdName ? callback_data->pMessageIdName : "<null>",
|
||||||
|
callback_data->pMessage ? callback_data->pMessage : "<null>");
|
||||||
|
|
||||||
return VK_FALSE;
|
return VK_FALSE;
|
||||||
}
|
}
|
||||||
|
@@ -156,42 +156,6 @@ void RasterizerVulkan::LoadDiskResources(const std::atomic_bool& stop_loading,
|
|||||||
pipeline_cache.LoadDiskCache();
|
pipeline_cache.LoadDiskCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerVulkan::SyncEntireState() {
|
|
||||||
// Sync fixed function Vulkan state
|
|
||||||
SyncFixedState();
|
|
||||||
|
|
||||||
// Sync uniforms
|
|
||||||
SyncClipCoef();
|
|
||||||
SyncDepthScale();
|
|
||||||
SyncDepthOffset();
|
|
||||||
SyncAlphaTest();
|
|
||||||
SyncCombinerColor();
|
|
||||||
auto& tev_stages = Pica::g_state.regs.texturing.GetTevStages();
|
|
||||||
for (std::size_t index = 0; index < tev_stages.size(); ++index)
|
|
||||||
SyncTevConstColor(index, tev_stages[index]);
|
|
||||||
|
|
||||||
SyncGlobalAmbient();
|
|
||||||
for (unsigned light_index = 0; light_index < 8; light_index++) {
|
|
||||||
SyncLightSpecular0(light_index);
|
|
||||||
SyncLightSpecular1(light_index);
|
|
||||||
SyncLightDiffuse(light_index);
|
|
||||||
SyncLightAmbient(light_index);
|
|
||||||
SyncLightPosition(light_index);
|
|
||||||
SyncLightDistanceAttenuationBias(light_index);
|
|
||||||
SyncLightDistanceAttenuationScale(light_index);
|
|
||||||
}
|
|
||||||
|
|
||||||
SyncFogColor();
|
|
||||||
SyncProcTexNoise();
|
|
||||||
SyncProcTexBias();
|
|
||||||
SyncShadowBias();
|
|
||||||
SyncShadowTextureBias();
|
|
||||||
|
|
||||||
for (unsigned tex_index = 0; tex_index < 3; tex_index++) {
|
|
||||||
SyncTextureLodBias(tex_index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RasterizerVulkan::SyncFixedState() {
|
void RasterizerVulkan::SyncFixedState() {
|
||||||
SyncClipEnabled();
|
SyncClipEnabled();
|
||||||
SyncCullMode();
|
SyncCullMode();
|
||||||
@@ -834,30 +798,22 @@ bool RasterizerVulkan::Draw(bool accelerate, bool is_indexed) {
|
|||||||
|
|
||||||
void RasterizerVulkan::NotifyFixedFunctionPicaRegisterChanged(u32 id) {
|
void RasterizerVulkan::NotifyFixedFunctionPicaRegisterChanged(u32 id) {
|
||||||
switch (id) {
|
switch (id) {
|
||||||
// Culling
|
|
||||||
case PICA_REG_INDEX(rasterizer.cull_mode):
|
|
||||||
SyncCullMode();
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Clipping plane
|
// Clipping plane
|
||||||
case PICA_REG_INDEX(rasterizer.clip_enable):
|
case PICA_REG_INDEX(rasterizer.clip_enable):
|
||||||
SyncClipEnabled();
|
SyncClipEnabled();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PICA_REG_INDEX(rasterizer.clip_coef[0]):
|
// Culling
|
||||||
case PICA_REG_INDEX(rasterizer.clip_coef[1]):
|
case PICA_REG_INDEX(rasterizer.cull_mode):
|
||||||
case PICA_REG_INDEX(rasterizer.clip_coef[2]):
|
SyncCullMode();
|
||||||
case PICA_REG_INDEX(rasterizer.clip_coef[3]):
|
|
||||||
SyncClipCoef();
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Blending
|
// Blending
|
||||||
case PICA_REG_INDEX(framebuffer.output_merger.alphablend_enable):
|
case PICA_REG_INDEX(framebuffer.output_merger.alphablend_enable):
|
||||||
if (instance.NeedsLogicOpEmulation()) {
|
|
||||||
// We need this in the fragment shader to emulate logic operations
|
|
||||||
shader_dirty = true;
|
|
||||||
}
|
|
||||||
SyncBlendEnabled();
|
SyncBlendEnabled();
|
||||||
|
// Update since logic op emulation depends on alpha blend enable.
|
||||||
|
SyncLogicOp();
|
||||||
|
SyncColorWriteMask();
|
||||||
break;
|
break;
|
||||||
case PICA_REG_INDEX(framebuffer.output_merger.alpha_blending):
|
case PICA_REG_INDEX(framebuffer.output_merger.alpha_blending):
|
||||||
SyncBlendFuncs();
|
SyncBlendFuncs();
|
||||||
@@ -900,11 +856,9 @@ void RasterizerVulkan::NotifyFixedFunctionPicaRegisterChanged(u32 id) {
|
|||||||
|
|
||||||
// Logic op
|
// Logic op
|
||||||
case PICA_REG_INDEX(framebuffer.output_merger.logic_op):
|
case PICA_REG_INDEX(framebuffer.output_merger.logic_op):
|
||||||
if (instance.NeedsLogicOpEmulation()) {
|
|
||||||
// We need this in the fragment shader to emulate logic operations
|
|
||||||
shader_dirty = true;
|
|
||||||
}
|
|
||||||
SyncLogicOp();
|
SyncLogicOp();
|
||||||
|
// Update since color write mask is used to emulate no-op.
|
||||||
|
SyncColorWriteMask();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1188,15 +1142,9 @@ vk::Framebuffer RasterizerVulkan::CreateFramebuffer(const FramebufferInfo& info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerVulkan::SyncClipEnabled() {
|
void RasterizerVulkan::SyncClipEnabled() {
|
||||||
uniform_block_data.data.enable_clip1 = Pica::g_state.regs.rasterizer.clip_enable != 0;
|
bool clip_enabled = Pica::g_state.regs.rasterizer.clip_enable != 0;
|
||||||
}
|
if (clip_enabled != uniform_block_data.data.enable_clip1) {
|
||||||
|
uniform_block_data.data.enable_clip1 = clip_enabled;
|
||||||
void RasterizerVulkan::SyncClipCoef() {
|
|
||||||
const auto raw_clip_coef = Pica::g_state.regs.rasterizer.GetClipCoef();
|
|
||||||
const Common::Vec4f new_clip_coef = {raw_clip_coef.x.ToFloat32(), raw_clip_coef.y.ToFloat32(),
|
|
||||||
raw_clip_coef.z.ToFloat32(), raw_clip_coef.w.ToFloat32()};
|
|
||||||
if (new_clip_coef != uniform_block_data.data.clip_coef) {
|
|
||||||
uniform_block_data.data.clip_coef = new_clip_coef;
|
|
||||||
uniform_block_data.dirty = true;
|
uniform_block_data.dirty = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1234,7 +1182,13 @@ void RasterizerVulkan::SyncBlendColor() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerVulkan::SyncLogicOp() {
|
void RasterizerVulkan::SyncLogicOp() {
|
||||||
|
if (instance.NeedsLogicOpEmulation()) {
|
||||||
|
// We need this in the fragment shader to emulate logic operations
|
||||||
|
shader_dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
const auto& regs = Pica::g_state.regs;
|
const auto& regs = Pica::g_state.regs;
|
||||||
|
pipeline_info.blending.logic_op.Assign(regs.framebuffer.output_merger.logic_op);
|
||||||
|
|
||||||
const bool is_logic_op_emulated =
|
const bool is_logic_op_emulated =
|
||||||
instance.NeedsLogicOpEmulation() && !regs.framebuffer.output_merger.alphablend_enable;
|
instance.NeedsLogicOpEmulation() && !regs.framebuffer.output_merger.alphablend_enable;
|
||||||
@@ -1244,14 +1198,14 @@ void RasterizerVulkan::SyncLogicOp() {
|
|||||||
// Color output is disabled by logic operation. We use color write mask to skip
|
// Color output is disabled by logic operation. We use color write mask to skip
|
||||||
// color but allow depth write.
|
// color but allow depth write.
|
||||||
pipeline_info.blending.color_write_mask.Assign(0);
|
pipeline_info.blending.color_write_mask.Assign(0);
|
||||||
} else {
|
|
||||||
pipeline_info.blending.logic_op.Assign(regs.framebuffer.output_merger.logic_op);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerVulkan::SyncColorWriteMask() {
|
void RasterizerVulkan::SyncColorWriteMask() {
|
||||||
const auto& regs = Pica::g_state.regs;
|
const auto& regs = Pica::g_state.regs;
|
||||||
const u32 color_mask = (regs.framebuffer.output_merger.depth_color_mask >> 8) & 0xF;
|
const u32 color_mask = regs.framebuffer.framebuffer.allow_color_write != 0
|
||||||
|
? (regs.framebuffer.output_merger.depth_color_mask >> 8) & 0xF
|
||||||
|
: 0;
|
||||||
|
|
||||||
const bool is_logic_op_emulated =
|
const bool is_logic_op_emulated =
|
||||||
instance.NeedsLogicOpEmulation() && !regs.framebuffer.output_merger.alphablend_enable;
|
instance.NeedsLogicOpEmulation() && !regs.framebuffer.output_merger.alphablend_enable;
|
||||||
|
@@ -95,11 +95,7 @@ public:
|
|||||||
u32 pixel_stride, ScreenInfo& screen_info);
|
u32 pixel_stride, ScreenInfo& screen_info);
|
||||||
bool AccelerateDrawBatch(bool is_indexed) override;
|
bool AccelerateDrawBatch(bool is_indexed) override;
|
||||||
|
|
||||||
/// Syncs entire status to match PICA registers
|
void SyncFixedState() override;
|
||||||
void SyncEntireState() override;
|
|
||||||
|
|
||||||
/// Sync fixed function pipeline state
|
|
||||||
void SyncFixedState();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void NotifyFixedFunctionPicaRegisterChanged(u32 id) override;
|
void NotifyFixedFunctionPicaRegisterChanged(u32 id) override;
|
||||||
@@ -107,9 +103,6 @@ private:
|
|||||||
/// Syncs the clip enabled status to match the PICA register
|
/// Syncs the clip enabled status to match the PICA register
|
||||||
void SyncClipEnabled();
|
void SyncClipEnabled();
|
||||||
|
|
||||||
/// Syncs the clip coefficients to match the PICA register
|
|
||||||
void SyncClipCoef();
|
|
||||||
|
|
||||||
/// Syncs the cull mode to match the PICA register
|
/// Syncs the cull mode to match the PICA register
|
||||||
void SyncCullMode();
|
void SyncCullMode();
|
||||||
|
|
||||||
|
@@ -12,6 +12,7 @@
|
|||||||
#include "video_core/renderer_opengl/gl_shader_decompiler.h"
|
#include "video_core/renderer_opengl/gl_shader_decompiler.h"
|
||||||
#include "video_core/renderer_vulkan/vk_instance.h"
|
#include "video_core/renderer_vulkan/vk_instance.h"
|
||||||
#include "video_core/renderer_vulkan/vk_shader_gen.h"
|
#include "video_core/renderer_vulkan/vk_shader_gen.h"
|
||||||
|
#include "video_core/shader/shader_uniforms.h"
|
||||||
#include "video_core/video_core.h"
|
#include "video_core/video_core.h"
|
||||||
|
|
||||||
using Pica::FramebufferRegs;
|
using Pica::FramebufferRegs;
|
||||||
@@ -23,55 +24,7 @@ using VSOutputAttributes = RasterizerRegs::VSOutputAttributes;
|
|||||||
|
|
||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
|
|
||||||
constexpr std::string_view UniformBlockDef = R"(
|
const std::string UniformBlockDef = Pica::Shader::BuildShaderUniformDefinitions("binding = 1,");
|
||||||
#define NUM_TEV_STAGES 6
|
|
||||||
#define NUM_LIGHTS 8
|
|
||||||
#define NUM_LIGHTING_SAMPLERS 24
|
|
||||||
|
|
||||||
struct LightSrc {
|
|
||||||
vec3 specular_0;
|
|
||||||
vec3 specular_1;
|
|
||||||
vec3 diffuse;
|
|
||||||
vec3 ambient;
|
|
||||||
vec3 position;
|
|
||||||
vec3 spot_direction;
|
|
||||||
float dist_atten_bias;
|
|
||||||
float dist_atten_scale;
|
|
||||||
};
|
|
||||||
|
|
||||||
layout (set = 0, binding = 1, std140) uniform shader_data {
|
|
||||||
int framebuffer_scale;
|
|
||||||
int alphatest_ref;
|
|
||||||
float depth_scale;
|
|
||||||
float depth_offset;
|
|
||||||
float shadow_bias_constant;
|
|
||||||
float shadow_bias_linear;
|
|
||||||
int scissor_x1;
|
|
||||||
int scissor_y1;
|
|
||||||
int scissor_x2;
|
|
||||||
int scissor_y2;
|
|
||||||
int fog_lut_offset;
|
|
||||||
int proctex_noise_lut_offset;
|
|
||||||
int proctex_color_map_offset;
|
|
||||||
int proctex_alpha_map_offset;
|
|
||||||
int proctex_lut_offset;
|
|
||||||
int proctex_diff_lut_offset;
|
|
||||||
float proctex_bias;
|
|
||||||
int shadow_texture_bias;
|
|
||||||
bool enable_clip1;
|
|
||||||
ivec4 lighting_lut_offset[NUM_LIGHTING_SAMPLERS / 4];
|
|
||||||
vec3 fog_color;
|
|
||||||
vec2 proctex_noise_f;
|
|
||||||
vec2 proctex_noise_a;
|
|
||||||
vec2 proctex_noise_p;
|
|
||||||
vec3 lighting_global_ambient;
|
|
||||||
LightSrc light_src[NUM_LIGHTS];
|
|
||||||
vec4 const_color[NUM_TEV_STAGES];
|
|
||||||
vec4 tev_combiner_buffer_color;
|
|
||||||
vec3 tex_lod_bias;
|
|
||||||
vec4 clip_coef;
|
|
||||||
};
|
|
||||||
)";
|
|
||||||
|
|
||||||
static std::string GetVertexInterfaceDeclaration(bool is_output) {
|
static std::string GetVertexInterfaceDeclaration(bool is_output) {
|
||||||
std::string out;
|
std::string out;
|
||||||
|
@@ -23,4 +23,56 @@ void PicaUniformsData::SetFromRegs(const Pica::ShaderRegs& regs,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr std::string_view UniformBlockDefFormat = R"(
|
||||||
|
#define NUM_TEV_STAGES 6
|
||||||
|
#define NUM_LIGHTS 8
|
||||||
|
#define NUM_LIGHTING_SAMPLERS 24
|
||||||
|
struct LightSrc {{
|
||||||
|
vec3 specular_0;
|
||||||
|
vec3 specular_1;
|
||||||
|
vec3 diffuse;
|
||||||
|
vec3 ambient;
|
||||||
|
vec3 position;
|
||||||
|
vec3 spot_direction;
|
||||||
|
float dist_atten_bias;
|
||||||
|
float dist_atten_scale;
|
||||||
|
}};
|
||||||
|
layout ({}std140) uniform shader_data {{
|
||||||
|
int framebuffer_scale;
|
||||||
|
int alphatest_ref;
|
||||||
|
float depth_scale;
|
||||||
|
float depth_offset;
|
||||||
|
float shadow_bias_constant;
|
||||||
|
float shadow_bias_linear;
|
||||||
|
int scissor_x1;
|
||||||
|
int scissor_y1;
|
||||||
|
int scissor_x2;
|
||||||
|
int scissor_y2;
|
||||||
|
int fog_lut_offset;
|
||||||
|
int proctex_noise_lut_offset;
|
||||||
|
int proctex_color_map_offset;
|
||||||
|
int proctex_alpha_map_offset;
|
||||||
|
int proctex_lut_offset;
|
||||||
|
int proctex_diff_lut_offset;
|
||||||
|
float proctex_bias;
|
||||||
|
int shadow_texture_bias;
|
||||||
|
bool enable_clip1;
|
||||||
|
ivec4 lighting_lut_offset[NUM_LIGHTING_SAMPLERS / 4];
|
||||||
|
vec3 fog_color;
|
||||||
|
vec2 proctex_noise_f;
|
||||||
|
vec2 proctex_noise_a;
|
||||||
|
vec2 proctex_noise_p;
|
||||||
|
vec3 lighting_global_ambient;
|
||||||
|
LightSrc light_src[NUM_LIGHTS];
|
||||||
|
vec4 const_color[NUM_TEV_STAGES];
|
||||||
|
vec4 tev_combiner_buffer_color;
|
||||||
|
vec3 tex_lod_bias;
|
||||||
|
vec4 clip_coef;
|
||||||
|
}};
|
||||||
|
)";
|
||||||
|
|
||||||
|
std::string BuildShaderUniformDefinitions(const std::string& extra_layout_parameters) {
|
||||||
|
return fmt::format(UniformBlockDefFormat, extra_layout_parameters);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Pica::Shader
|
} // namespace Pica::Shader
|
||||||
|
@@ -96,4 +96,6 @@ static_assert(sizeof(VSUniformData) == 1856,
|
|||||||
static_assert(sizeof(VSUniformData) < 16384,
|
static_assert(sizeof(VSUniformData) < 16384,
|
||||||
"VSUniformData structure must be less than 16kb as per the OpenGL spec");
|
"VSUniformData structure must be less than 16kb as per the OpenGL spec");
|
||||||
|
|
||||||
|
std::string BuildShaderUniformDefinitions(const std::string& extra_layout_parameters = "");
|
||||||
|
|
||||||
} // namespace Pica::Shader
|
} // namespace Pica::Shader
|
||||||
|
Reference in New Issue
Block a user