예제 #1
0
void ShaderCache::LoadAndSetActiveShaders(DSTALPHA_MODE ps_dst_alpha_mode, u32 gs_primitive_type)
{
  SetCurrentPrimitiveTopology(gs_primitive_type);

  GeometryShaderUid gs_uid = GetGeometryShaderUid(gs_primitive_type);
  PixelShaderUid ps_uid = GetPixelShaderUid(ps_dst_alpha_mode);
  VertexShaderUid vs_uid = GetVertexShaderUid();

  bool gs_changed = gs_uid != s_last_geometry_shader_uid;
  bool ps_changed = ps_uid != s_last_pixel_shader_uid;
  bool vs_changed = vs_uid != s_last_vertex_shader_uid;

  if (!gs_changed && !ps_changed && !vs_changed)
  {
    return;
  }

  if (gs_changed)
  {
    HandleGSUIDChange(gs_uid, gs_primitive_type);
  }

  if (ps_changed)
  {
    HandlePSUIDChange(ps_uid, ps_dst_alpha_mode);
  }

  if (vs_changed)
  {
    HandleVSUIDChange(vs_uid);
  }

  // A Uid has changed, so the PSO will need to be reset at next ApplyState.
  D3D::command_list_mgr->SetCommandListDirtyState(COMMAND_LIST_STATE_PSO, true);
}
예제 #2
0
bool StateTracker::CheckForShaderChanges(u32 gx_primitive_type, u32 components, PIXEL_SHADER_RENDER_MODE dstalpha_mode)
{
	VertexShaderUid vs_uid;
	GetVertexShaderUID(vs_uid, components, xfmem, bpmem);
	PixelShaderUid ps_uid;
	GetPixelShaderUID(ps_uid, dstalpha_mode, components, xfmem, bpmem);

	bool changed = false;

	if (vs_uid != m_vs_uid)
	{
		m_pipeline_state.vs = g_object_cache->GetVertexShaderForUid(vs_uid);
		m_vs_uid = vs_uid;
		changed = true;
	}

	if (g_vulkan_context->SupportsGeometryShaders())
	{
		GeometryShaderUid gs_uid;
		GetGeometryShaderUid(gs_uid, gx_primitive_type, xfmem, components);
		if (gs_uid != m_gs_uid)
		{
			if (gs_uid.GetUidData().IsPassthrough())
				m_pipeline_state.gs = VK_NULL_HANDLE;
			else
				m_pipeline_state.gs = g_object_cache->GetGeometryShaderForUid(gs_uid);

			m_gs_uid = gs_uid;
			changed = true;
		}
	}

	if (ps_uid != m_ps_uid)
	{
		m_pipeline_state.ps = g_object_cache->GetPixelShaderForUid(ps_uid);
		m_ps_uid = ps_uid;
		changed = true;
	}

	if (m_dstalpha_mode != dstalpha_mode)
	{
		// Switching to/from alpha pass requires a pipeline change, since the blend state
		// is overridden in the destination alpha pass.
		if (m_dstalpha_mode == PIXEL_SHADER_RENDER_MODE::PSRM_ALPHA_PASS || dstalpha_mode == PIXEL_SHADER_RENDER_MODE::PSRM_ALPHA_PASS)
			changed = true;

		m_dstalpha_mode = dstalpha_mode;
	}

	if (changed)
		m_dirty_flags |= DIRTY_FLAG_PIPELINE;

	return changed;
}
예제 #3
0
bool GeometryShaderCache::SetShader(u32 primitive_type)
{
  GeometryShaderUid uid = GetGeometryShaderUid(primitive_type);

  // Check if the shader is already set
  if (last_entry)
  {
    if (uid == last_uid)
    {
      GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
      return true;
    }
  }

  last_uid = uid;

  // Check if the shader is a pass-through shader
  if (uid.GetUidData()->IsPassthrough())
  {
    // Return the default pass-through shader
    last_entry = &pass_entry;
    return true;
  }

  // Check if the shader is already in the cache
  GSCache::iterator iter;
  iter = GeometryShaders.find(uid);
  if (iter != GeometryShaders.end())
  {
    const GSCacheEntry& entry = iter->second;
    last_entry = &entry;

    return (entry.shader != nullptr);
  }

  // Need to compile a new shader
  ShaderCode code =
      GenerateGeometryShaderCode(APIType::D3D, ShaderHostConfig::GetCurrent(), uid.GetUidData());

  D3DBlob* pbytecode;
  if (!D3D::CompileGeometryShader(code.GetBuffer(), &pbytecode))
  {
    GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true);
    return false;
  }

  // Insert the bytecode into the caches
  g_gs_disk_cache.Append(uid, pbytecode->Data(), pbytecode->Size());

  bool success = InsertByteCode(uid, pbytecode->Data(), pbytecode->Size());
  pbytecode->Release();

  return success;
}
예제 #4
0
void ProgramShaderCache::GetShaderId(SHADERUID* uid, DSTALPHA_MODE dstAlphaMode, u32 components, u32 primitive_type)
{
	GetPixelShaderUid(uid->puid, dstAlphaMode, API_OPENGL, components);
	GetVertexShaderUid(uid->vuid, components, API_OPENGL);
	GetGeometryShaderUid(uid->guid, primitive_type, API_OPENGL);

	if (g_ActiveConfig.bEnableShaderDebugging)
	{
		PixelShaderCode pcode;
		GeneratePixelShaderCode(pcode, dstAlphaMode, API_OPENGL, components);
		pixel_uid_checker.AddToIndexAndCheck(pcode, uid->puid, "Pixel", "p");

		VertexShaderCode vcode;
		GenerateVertexShaderCode(vcode, components, API_OPENGL);
		vertex_uid_checker.AddToIndexAndCheck(vcode, uid->vuid, "Vertex", "v");

		ShaderCode gcode;
		GenerateGeometryShaderCode(gcode, primitive_type, API_OPENGL);
		geometry_uid_checker.AddToIndexAndCheck(gcode, uid->guid, "Geometry", "g");
	}
}
예제 #5
0
void GeometryShaderCache::PrepareShader(
	u32 primitive_type,
	const XFMemory &xfr,
	const u32 components,
	bool ongputhread)
{
	GeometryShaderUid uid;
	GetGeometryShaderUid(uid, primitive_type, xfr, components);
	if (ongputhread)
	{
		s_compiler->ProcCompilationResults();
		// Check if the shader is already set
		if (s_last_entry)
		{
			if (uid == s_last_uid)
			{
				return;
			}
		}
		s_last_uid = uid;
		// Check if the shader is a pass-through shader
		if (uid.GetUidData().IsPassthrough())
		{
			// Return the default pass-through shader
			s_last_entry = &s_pass_entry;
			return;
		}
		GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
	}
	else
	{
		if (s_external_last_uid == uid)
		{
			return;
		}
		s_external_last_uid = uid;
	}
	CompileGShader(uid, ongputhread);
}
예제 #6
0
void ShaderCache::PrepareShaders(PIXEL_SHADER_RENDER_MODE render_mode,
	u32 gs_primitive_type,
	u32 components,
	const XFMemory &xfr,
	const BPMemory &bpm, bool on_gpu_thread)
{
	SetCurrentPrimitiveTopology(gs_primitive_type);
	GeometryShaderUid gs_uid;
	GetGeometryShaderUid(gs_uid, gs_primitive_type, xfr, components);
	PixelShaderUid ps_uid;
	GetPixelShaderUID(ps_uid, render_mode, components, xfr, bpm);
	VertexShaderUid vs_uid;
	GetVertexShaderUID(vs_uid, components, xfr, bpm);
	TessellationShaderUid ts_uid;
	bool tessellationenabled = false;
	if (gs_primitive_type == PrimitiveType::PRIMITIVE_TRIANGLES
		&& g_ActiveConfig.TessellationEnabled()
		&& xfr.projection.type == GX_PERSPECTIVE
		&& (g_ActiveConfig.bForcedLighting || g_ActiveConfig.PixelLightingEnabled(xfr, components)))
	{
		GetTessellationShaderUID(ts_uid, xfr, bpm, components);
		tessellationenabled = true;
	}

	bool gs_changed = false;
	bool ps_changed = false;
	bool vs_changed = false;
	bool ts_changed = false;

	if (on_gpu_thread)
	{
		s_compiler->ProcCompilationResults();
		gs_changed = gs_uid != s_last_geometry_shader_uid;
		ps_changed = ps_uid != s_last_pixel_shader_uid;
		vs_changed = vs_uid != s_last_vertex_shader_uid;
		ts_changed = tessellationenabled && ts_uid != s_last_tessellation_shader_uid;
	}
	else
	{
		gs_changed = gs_uid != s_last_cpu_geometry_shader_uid;
		ps_changed = ps_uid != s_last_cpu_pixel_shader_uid;
		vs_changed = vs_uid != s_last_cpu_vertex_shader_uid;
		ts_changed = tessellationenabled && ts_uid != s_last_cpu_tessellation_shader_uid;
	}

	if (!gs_changed && !ps_changed && !vs_changed && !ts_changed)
	{
		return;
	}

	if (on_gpu_thread)
	{
		if (gs_changed)
		{
			s_last_geometry_shader_uid = gs_uid;
		}

		if (ps_changed)
		{
			s_last_pixel_shader_uid = ps_uid;
		}

		if (vs_changed)
		{
			s_last_vertex_shader_uid = vs_uid;
		}
		if (ts_changed)
		{
			s_last_tessellation_shader_uid = ts_uid;
		}
		// A Uid has changed, so the PSO will need to be reset at next ApplyState.
		D3D::command_list_mgr->SetCommandListDirtyState(COMMAND_LIST_STATE_PSO, true);
	}
	else
	{
		if (gs_changed)
		{
			s_last_cpu_geometry_shader_uid = gs_uid;
		}

		if (ps_changed)
		{
			s_last_cpu_pixel_shader_uid = ps_uid;
		}

		if (vs_changed)
		{
			s_last_cpu_vertex_shader_uid = vs_uid;
		}

		if (ts_changed)
		{
			s_last_cpu_tessellation_shader_uid = ts_uid;
		}
	}

	if (vs_changed)
	{
		HandleVSUIDChange(vs_uid, on_gpu_thread);
	}

	if (ts_changed)
	{
		HandleTSUIDChange(ts_uid, on_gpu_thread);
	}
	else
	{
		if (on_gpu_thread)
		{
			s_last_domain_shader_bytecode = &s_pass_entry;
			s_last_hull_shader_bytecode = &s_pass_entry;
		}
	}

	if (gs_changed)
	{
		HandleGSUIDChange(gs_uid, on_gpu_thread);
	}

	if (ps_changed)
	{
		HandlePSUIDChange(ps_uid, on_gpu_thread);
	}
}
예제 #7
0
bool GeometryShaderCache::SetShader(u32 primitive_type)
{
	switch (primitive_type)
	{
	case PRIMITIVE_TRIANGLES:
		currentPrimitiveTopology = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
		break;
	case PRIMITIVE_LINES:
		currentPrimitiveTopology = D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE;
		break;
	case PRIMITIVE_POINTS:
		currentPrimitiveTopology = D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT;
		break;
	default:
		CHECK(0, "Invalid primitive type.");
		break;
	}

	GeometryShaderUid uid = GetGeometryShaderUid(primitive_type, API_D3D);

	// Check if the shader is already set
	if (uid == last_uid)
	{
		GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE,true);
		return true;
	}

	last_uid = uid;
	D3D::commandListMgr->dirtyPso = true;

	if (g_ActiveConfig.bEnableShaderDebugging)
	{
		ShaderCode code = GenerateGeometryShaderCode(primitive_type, API_D3D);
		geometry_uid_checker.AddToIndexAndCheck(code, uid, "Geometry", "g");
	}

	// Check if the shader is a pass-through shader
	if (uid.GetUidData()->IsPassthrough())
	{
		// Return the default pass-through shader
		last_entry = &pass_entry;
		return true;
	}

	// Check if the shader is already in the cache
	GSCache::iterator iter;
	iter = GeometryShaders.find(uid);
	if (iter != GeometryShaders.end())
	{
		const GSCacheEntry &entry = iter->second;
		last_entry = &entry;

		return (entry.shader12.pShaderBytecode != nullptr);
	}

	// Need to compile a new shader
	ShaderCode code = GenerateGeometryShaderCode(primitive_type, API_D3D);

	D3DBlob* pbytecode;
	if (!D3D::CompileGeometryShader(code.GetBuffer(), &pbytecode))
	{
		GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true);
		return false;
	}

	// Insert the bytecode into the caches
	g_gs_disk_cache.Append(uid, pbytecode->Data(), pbytecode->Size());

	bool success = InsertByteCode(uid, pbytecode->Data(), pbytecode->Size());
	pbytecode->Release();

	if (g_ActiveConfig.bEnableShaderDebugging && success)
	{
		GeometryShaders[uid].code = code.GetBuffer();
	}

	return success;
}
bool GeometryShaderCache::SetShader(u32 primitive_type)
{
	GeometryShaderUid uid;
	GetGeometryShaderUid(uid, primitive_type, API_D3D);
	if (g_ActiveConfig.bEnableShaderDebugging)
	{
		ShaderCode code;
		GenerateGeometryShaderCode(code, primitive_type, API_D3D);
		geometry_uid_checker.AddToIndexAndCheck(code, uid, "Geometry", "g");
	}

	// Check if the shader is already set
	if (last_entry)
	{
		if (uid == last_uid)
		{
			GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE,true);
			return true;
		}
	}

	last_uid = uid;

	// Check if the shader is a pass-through shader
	if (uid.GetUidData()->IsPassthrough())
	{
		// Return the default pass-through shader
		last_entry = &pass_entry;
		return true;
	}

	// Check if the shader is already in the cache
	GSCache::iterator iter;
	iter = GeometryShaders.find(uid);
	if (iter != GeometryShaders.end())
	{
		const GSCacheEntry &entry = iter->second;
		last_entry = &entry;

		return (entry.shader != nullptr);
	}

	// Need to compile a new shader
	ShaderCode code;
	GenerateGeometryShaderCode(code, primitive_type, API_D3D);

	D3DBlob* pbytecode;
	if (!D3D::CompileGeometryShader(code.GetBuffer(), &pbytecode))
	{
		GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true);
		return false;
	}

	// Insert the bytecode into the caches
	g_gs_disk_cache.Append(uid, pbytecode->Data(), pbytecode->Size());

	bool success = InsertByteCode(uid, pbytecode->Data(), pbytecode->Size());
	pbytecode->Release();

	if (g_ActiveConfig.bEnableShaderDebugging && success)
	{
		GeometryShaders[uid].code = code.GetBuffer();
	}

	return success;
}