mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-02-14 00:09:24 +01:00
Shader Disk Cache implementation for D3D. Saves generated shaders on disk. Eliminates "freeze jerks" in D3D plugin the _second_ and later times you play something.... not much to do about the first time. The D3D shader compiler is just slow.
Also assorted cleanup around the shader code. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4869 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
f599fdcec5
commit
3e01152793
@ -720,6 +720,14 @@
|
|||||||
RelativePath=".\Src\IniFile.h"
|
RelativePath=".\Src\IniFile.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Src\LinearDiskCache.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Src\LinearDiskCache.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\Src\MathUtil.cpp"
|
RelativePath=".\Src\MathUtil.cpp"
|
||||||
>
|
>
|
||||||
|
@ -66,6 +66,7 @@
|
|||||||
#define GAMECONFIG_DIR "GameConfig"
|
#define GAMECONFIG_DIR "GameConfig"
|
||||||
#define MAPS_DIR "Maps"
|
#define MAPS_DIR "Maps"
|
||||||
#define CACHE_DIR "Cache"
|
#define CACHE_DIR "Cache"
|
||||||
|
#define SHADERCACHE_DIR "ShaderCache"
|
||||||
#define STATESAVES_DIR "StateSaves"
|
#define STATESAVES_DIR "StateSaves"
|
||||||
#define SCREENSHOTS_DIR "ScreenShots"
|
#define SCREENSHOTS_DIR "ScreenShots"
|
||||||
#define DUMP_DIR "Dump"
|
#define DUMP_DIR "Dump"
|
||||||
@ -128,6 +129,7 @@
|
|||||||
|
|
||||||
#define FULL_CONFIG_DIR FULL_USERDATA_DIR CONFIG_DIR DIR_SEP
|
#define FULL_CONFIG_DIR FULL_USERDATA_DIR CONFIG_DIR DIR_SEP
|
||||||
#define FULL_CACHE_DIR FULL_USERDATA_DIR CACHE_DIR DIR_SEP
|
#define FULL_CACHE_DIR FULL_USERDATA_DIR CACHE_DIR DIR_SEP
|
||||||
|
#define FULL_SHADERCACHE_DIR FULL_USERDATA_DIR SHADERCACHE_DIR DIR_SEP
|
||||||
#define FULL_STATESAVES_DIR FULL_USERDATA_DIR STATESAVES_DIR DIR_SEP
|
#define FULL_STATESAVES_DIR FULL_USERDATA_DIR STATESAVES_DIR DIR_SEP
|
||||||
#define FULL_SCREENSHOTS_DIR FULL_USERDATA_DIR SCREENSHOTS_DIR DIR_SEP
|
#define FULL_SCREENSHOTS_DIR FULL_USERDATA_DIR SCREENSHOTS_DIR DIR_SEP
|
||||||
#define FULL_FRAMES_DIR FULL_USERDATA_DIR DUMP_DIR DIR_SEP DUMP_FRAMES_DIR
|
#define FULL_FRAMES_DIR FULL_USERDATA_DIR DUMP_DIR DIR_SEP DUMP_FRAMES_DIR
|
||||||
|
149
Source/Core/Common/Src/LinearDiskCache.cpp
Normal file
149
Source/Core/Common/Src/LinearDiskCache.cpp
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
// Copyright (C) 2003 Dolphin Project.
|
||||||
|
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
|
// Official SVN repository and contact information can be found at
|
||||||
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
|
#include "LinearDiskCache.h"
|
||||||
|
|
||||||
|
static const char ID[4] = {'D', 'C', 'A', 'C'};
|
||||||
|
const int version = 1; // TODO: Get from SVN_REV
|
||||||
|
|
||||||
|
LinearDiskCache::LinearDiskCache()
|
||||||
|
: file_(NULL), num_entries_(0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void LinearDiskCache::WriteHeader() {
|
||||||
|
fwrite(ID, 4, 1, file_);
|
||||||
|
fwrite(&version, 4, 1, file_);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LinearDiskCache::ValidateHeader() {
|
||||||
|
char header_id[4];
|
||||||
|
int header_version;
|
||||||
|
fread(&header_id, 4, 1, file_);
|
||||||
|
fread(&header_version, 4, 1, file_);
|
||||||
|
if (memcmp(header_id, ID, 4) != 0)
|
||||||
|
return false;
|
||||||
|
if (header_version != version)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int LinearDiskCache::OpenAndRead(const char *filename, LinearDiskCacheReader *reader) {
|
||||||
|
int items_read_count = 0;
|
||||||
|
file_ = fopen(filename, "rb");
|
||||||
|
int file_size = 0;
|
||||||
|
if (file_) {
|
||||||
|
fseek(file_, 0, SEEK_END);
|
||||||
|
file_size = (int)ftell(file_);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool file_corrupt = false;
|
||||||
|
if (file_size == 0) {
|
||||||
|
if (file_)
|
||||||
|
fclose(file_);
|
||||||
|
// Reopen for writing.
|
||||||
|
file_ = fopen(filename, "wb");
|
||||||
|
// Cache empty, let's initialize a header.
|
||||||
|
WriteHeader();
|
||||||
|
num_entries_ = 0;
|
||||||
|
} else {
|
||||||
|
// file_ must be != 0 here.
|
||||||
|
// Back to the start we go.
|
||||||
|
fseek(file_, 0, SEEK_SET);
|
||||||
|
// Check that the file is valid
|
||||||
|
if (!ValidateHeader()) {
|
||||||
|
// Not valid - delete the file and start over.
|
||||||
|
fclose(file_);
|
||||||
|
unlink(filename);
|
||||||
|
|
||||||
|
PanicAlert("LinearDiskCache file header broken.");
|
||||||
|
|
||||||
|
file_ = fopen(filename, "wb");
|
||||||
|
WriteHeader();
|
||||||
|
num_entries_ = 0;
|
||||||
|
} else {
|
||||||
|
// Valid - blow through it.
|
||||||
|
// We're past the header already thanks to ValidateHeader.
|
||||||
|
while (!feof(file_)) {
|
||||||
|
int key_size, value_size;
|
||||||
|
int key_size_size = fread(&key_size, 1, sizeof(key_size), file_);
|
||||||
|
int value_size_size = fread(&value_size, 1, sizeof(value_size), file_);
|
||||||
|
if (key_size_size == 0 && value_size_size == 0) {
|
||||||
|
// I guess feof isn't doing it's job - we're at the end.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (key_size <= 0 || value_size < 0 || key_size_size != 4 || value_size_size != 4) {
|
||||||
|
PanicAlert("Disk cache file %s corrupted/truncated! ks: %i vs %i kss %i vss %i", filename,
|
||||||
|
key_size, value_size, key_size_size, value_size_size);
|
||||||
|
file_corrupt = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
u8 *key = new u8[key_size];
|
||||||
|
u8 *value = new u8[value_size];
|
||||||
|
int actual_key_size = (int)fread(key, 1, key_size, file_);
|
||||||
|
int actual_value_size = (int)fread(value, 1, value_size, file_);
|
||||||
|
if (actual_key_size != key_size || actual_value_size != value_size) {
|
||||||
|
PanicAlert("Disk cache file %s corrupted/truncated! ks: %i actual ks: %i vs: %i actual vs: %i", filename,
|
||||||
|
key_size, actual_key_size, value_size, actual_value_size);
|
||||||
|
file_corrupt = true;
|
||||||
|
} else {
|
||||||
|
reader->Read(key, key_size, value, value_size);
|
||||||
|
items_read_count++;
|
||||||
|
}
|
||||||
|
delete [] key;
|
||||||
|
delete [] value;
|
||||||
|
}
|
||||||
|
fclose(file_);
|
||||||
|
// Done reading.
|
||||||
|
|
||||||
|
// Reopen file for append.
|
||||||
|
// At this point, ftell() will be at the end of the file,
|
||||||
|
// which happens to be exactly what we want.
|
||||||
|
file_ = fopen(filename, "ab");
|
||||||
|
fseek(file_, 0, SEEK_END);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file_corrupt) {
|
||||||
|
// Restore sanity, start over.
|
||||||
|
fclose(file_);
|
||||||
|
unlink(filename);
|
||||||
|
|
||||||
|
file_ = fopen(filename, "wb+");
|
||||||
|
WriteHeader();
|
||||||
|
}
|
||||||
|
|
||||||
|
return items_read_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LinearDiskCache::Append(
|
||||||
|
const u8 *key, int key_size, const u8 *value, int value_size) {
|
||||||
|
// Should do a check that we don't already have "key"?
|
||||||
|
fwrite(&key_size, 1, sizeof(key_size), file_);
|
||||||
|
fwrite(&value_size, 1, sizeof(value_size), file_);
|
||||||
|
fwrite(key, 1, key_size, file_);
|
||||||
|
fwrite(value, 1, value_size, file_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LinearDiskCache::Sync() {
|
||||||
|
fflush(file_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LinearDiskCache::Close() {
|
||||||
|
fclose(file_);
|
||||||
|
file_ = 0;
|
||||||
|
num_entries_ = 0;
|
||||||
|
}
|
67
Source/Core/Common/Src/LinearDiskCache.h
Normal file
67
Source/Core/Common/Src/LinearDiskCache.h
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
// Copyright (C) 2003 Dolphin Project.
|
||||||
|
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
|
// Official SVN repository and contact information can be found at
|
||||||
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
|
#ifndef _LINEAR_DISKCACHE
|
||||||
|
#define _LINEAR_DISKCACHE
|
||||||
|
|
||||||
|
#include "Common.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
// On disk format:
|
||||||
|
// uint32 'DCAC'
|
||||||
|
// uint32 version; // svn_rev
|
||||||
|
// uint32 key_length;
|
||||||
|
// uint32 value_length;
|
||||||
|
// .... key;
|
||||||
|
// .... value;
|
||||||
|
|
||||||
|
class LinearDiskCacheReader {
|
||||||
|
public:
|
||||||
|
virtual void Read(const u8 *key, int key_size, const u8 *value, int value_size) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Dead simple unsorted key-value store with append functionality.
|
||||||
|
// No random read functionality, all reading is done in OpenAndRead.
|
||||||
|
// Keys and values can contain any characters, including \0.
|
||||||
|
//
|
||||||
|
// Suitable for caching generated shader bytecode between executions.
|
||||||
|
// Not tuned for extreme performance but should be reasonably fast.
|
||||||
|
// Does not support keys or values larger than 2GB, which should be reasonable.
|
||||||
|
// Keys must have non-zero length; values can have zero length.
|
||||||
|
class LinearDiskCache {
|
||||||
|
public:
|
||||||
|
LinearDiskCache();
|
||||||
|
|
||||||
|
// Returns the number of items read from the cache.
|
||||||
|
int OpenAndRead(const char *filename, LinearDiskCacheReader *reader);
|
||||||
|
void Close();
|
||||||
|
void Sync();
|
||||||
|
|
||||||
|
// Appends a key-value pair to the store.
|
||||||
|
void Append(const u8 *key, int key_size, const u8 *value, int value_size);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void WriteHeader();
|
||||||
|
bool ValidateHeader();
|
||||||
|
|
||||||
|
FILE *file_;
|
||||||
|
int num_entries_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _LINEAR_DISKCACHE
|
@ -232,8 +232,8 @@ inline u32 ConvertToSingle(u64 x)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// this is said to be undefined
|
// This is said to be undefined.
|
||||||
// based on hardware tests
|
// The code is based on hardware tests.
|
||||||
return ((x >> 32) & 0xc0000000) | ((x >> 29) & 0x3fffffff);
|
return ((x >> 32) & 0xc0000000) | ((x >> 29) & 0x3fffffff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ PIXELSHADERUID last_pixel_shader_uid;
|
|||||||
// a unique identifier, basically containing all the bits. Yup, it's a lot ....
|
// a unique identifier, basically containing all the bits. Yup, it's a lot ....
|
||||||
// It would likely be a lot more efficient to build this incrementally as the attributes
|
// It would likely be a lot more efficient to build this incrementally as the attributes
|
||||||
// are set...
|
// are set...
|
||||||
void GetPixelShaderId(PIXELSHADERUID &uid, u32 texturemask, u32 dstAlphaEnable)
|
void GetPixelShaderId(PIXELSHADERUID *uid, u32 texturemask, u32 dstAlphaEnable)
|
||||||
{
|
{
|
||||||
u32 projtexcoords = 0;
|
u32 projtexcoords = 0;
|
||||||
for (u32 i = 0; i < (u32)bpmem.genMode.numtevstages + 1; i++)
|
for (u32 i = 0; i < (u32)bpmem.genMode.numtevstages + 1; i++)
|
||||||
@ -43,7 +43,7 @@ void GetPixelShaderId(PIXELSHADERUID &uid, u32 texturemask, u32 dstAlphaEnable)
|
|||||||
projtexcoords |= 1 << texcoord;
|
projtexcoords |= 1 << texcoord;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
uid.values[0] = (u32)bpmem.genMode.numtevstages |
|
uid->values[0] = (u32)bpmem.genMode.numtevstages |
|
||||||
((u32)bpmem.genMode.numindstages << 4) |
|
((u32)bpmem.genMode.numindstages << 4) |
|
||||||
((u32)bpmem.genMode.numtexgens << 7) |
|
((u32)bpmem.genMode.numtexgens << 7) |
|
||||||
((u32)dstAlphaEnable << 11) |
|
((u32)dstAlphaEnable << 11) |
|
||||||
@ -51,21 +51,21 @@ void GetPixelShaderId(PIXELSHADERUID &uid, u32 texturemask, u32 dstAlphaEnable)
|
|||||||
(projtexcoords << 20) |
|
(projtexcoords << 20) |
|
||||||
((u32)bpmem.ztex2.op << 28);
|
((u32)bpmem.ztex2.op << 28);
|
||||||
|
|
||||||
uid.values[0] = (uid.values[0] & ~0x0ff00000) | (projtexcoords << 20);
|
uid->values[0] = (uid->values[0] & ~0x0ff00000) | (projtexcoords << 20);
|
||||||
// swap table
|
// swap table
|
||||||
for (int i = 0; i < 8; i += 2)
|
for (int i = 0; i < 8; i += 2)
|
||||||
((u8*)&uid.values[1])[i / 2] = (bpmem.tevksel[i].hex & 0xf) | ((bpmem.tevksel[i + 1].hex & 0xf) << 4);
|
((u8*)&uid->values[1])[i / 2] = (bpmem.tevksel[i].hex & 0xf) | ((bpmem.tevksel[i + 1].hex & 0xf) << 4);
|
||||||
|
|
||||||
uid.values[2] = texturemask;
|
uid->values[2] = texturemask;
|
||||||
|
|
||||||
u32 enableZTexture = (!bpmem.zcontrol.zcomploc && bpmem.zmode.testenable && bpmem.zmode.updateenable)?1:0;
|
u32 enableZTexture = (!bpmem.zcontrol.zcomploc && bpmem.zmode.testenable && bpmem.zmode.updateenable)?1:0;
|
||||||
|
|
||||||
uid.values[3] = (u32)bpmem.fog.c_proj_fsel.fsel |
|
uid->values[3] = (u32)bpmem.fog.c_proj_fsel.fsel |
|
||||||
((u32)bpmem.fog.c_proj_fsel.proj << 3) |
|
((u32)bpmem.fog.c_proj_fsel.proj << 3) |
|
||||||
((u32)enableZTexture << 4);
|
((u32)enableZTexture << 4);
|
||||||
|
|
||||||
int hdr = 4;
|
int hdr = 4;
|
||||||
u32* pcurvalue = &uid.values[hdr];
|
u32 *pcurvalue = &uid->values[hdr];
|
||||||
for (u32 i = 0; i < (u32)bpmem.genMode.numtevstages + 1; ++i)
|
for (u32 i = 0; i < (u32)bpmem.genMode.numtevstages + 1; ++i)
|
||||||
{
|
{
|
||||||
TevStageCombiner::ColorCombiner &cc = bpmem.combiners[i].colorC;
|
TevStageCombiner::ColorCombiner &cc = bpmem.combiners[i].colorC;
|
||||||
@ -119,7 +119,7 @@ void GetPixelShaderId(PIXELSHADERUID &uid, u32 texturemask, u32 dstAlphaEnable)
|
|||||||
if ((bpmem.genMode.numtevstages % 3) != 2)
|
if ((bpmem.genMode.numtevstages % 3) != 2)
|
||||||
++pcurvalue;
|
++pcurvalue;
|
||||||
|
|
||||||
uid.tevstages = (u32)(pcurvalue - &uid.values[0] - hdr);
|
uid->tevstages = (u32)(pcurvalue - &uid->values[0] - hdr);
|
||||||
|
|
||||||
for (u32 i = 0; i < bpmem.genMode.numindstages; ++i)
|
for (u32 i = 0; i < bpmem.genMode.numindstages; ++i)
|
||||||
{
|
{
|
||||||
@ -134,7 +134,7 @@ void GetPixelShaderId(PIXELSHADERUID &uid, u32 texturemask, u32 dstAlphaEnable)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// yeah, well ....
|
// yeah, well ....
|
||||||
uid.indstages = (u32)(pcurvalue - &uid.values[0] - (hdr - 1) - uid.tevstages);
|
uid->indstages = (u32)(pcurvalue - &uid->values[0] - (hdr - 1) - uid->tevstages);
|
||||||
}
|
}
|
||||||
|
|
||||||
// old tev->pixelshader notes
|
// old tev->pixelshader notes
|
||||||
@ -385,7 +385,7 @@ static void BuildSwapModeTable()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *GeneratePixelShader(u32 texture_mask, bool dstAlphaEnable, u32 HLSL)
|
const char *GeneratePixelShaderCode(u32 texture_mask, bool dstAlphaEnable, u32 HLSL)
|
||||||
{
|
{
|
||||||
setlocale(LC_NUMERIC, "C"); // Reset locale for compilation
|
setlocale(LC_NUMERIC, "C"); // Reset locale for compilation
|
||||||
text[sizeof(text) - 1] = 0x7C; // canary
|
text[sizeof(text) - 1] = 0x7C; // canary
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
#define C_COLORMATRIX (C_FOG + 2)
|
#define C_COLORMATRIX (C_FOG + 2)
|
||||||
#define PIXELSHADERUID_MAX_VALUES (5 + 32 + 6 + 11)
|
#define PIXELSHADERUID_MAX_VALUES (5 + 32 + 6 + 11)
|
||||||
|
|
||||||
|
// DO NOT make anything in this class virtual.
|
||||||
class PIXELSHADERUID
|
class PIXELSHADERUID
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -100,8 +101,9 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *GeneratePixelShader(u32 texture_mask, bool dstAlphaEnable, u32 HLSL = 0);
|
const char *GeneratePixelShaderCode(u32 texture_mask, bool dstAlphaEnable, u32 HLSL = 0);
|
||||||
void GetPixelShaderId(PIXELSHADERUID &, u32 texturemask, u32 dstAlphaEnable);
|
void GetPixelShaderId(PIXELSHADERUID *uid, u32 texturemask, u32 dstAlphaEnable);
|
||||||
|
|
||||||
extern PIXELSHADERUID last_pixel_shader_uid;
|
extern PIXELSHADERUID last_pixel_shader_uid;
|
||||||
|
|
||||||
#endif // GCOGL_PIXELSHADER_H
|
#endif // GCOGL_PIXELSHADER_H
|
||||||
|
@ -25,7 +25,7 @@ namespace TextureConversionShader
|
|||||||
{
|
{
|
||||||
u16 GetEncodedSampleCount(u32 format);
|
u16 GetEncodedSampleCount(u32 format);
|
||||||
|
|
||||||
const char *GenerateEncodingShader(u32 format,bool HLSL = false);
|
const char *GenerateEncodingShader(u32 format, bool HLSL = false);
|
||||||
|
|
||||||
void SetShaderParameters(float width, float height, float offsetX, float offsetY, float widthStride, float heightStride,float buffW = 0.0f,float buffH = 0.0f);
|
void SetShaderParameters(float width, float height, float offsetX, float offsetY, float widthStride, float heightStride,float buffW = 0.0f,float buffH = 0.0f);
|
||||||
|
|
||||||
|
@ -29,27 +29,27 @@ VERTEXSHADERUID last_vertex_shader_uid;
|
|||||||
|
|
||||||
// Mash together all the inputs that contribute to the code of a generated vertex shader into
|
// Mash together all the inputs that contribute to the code of a generated vertex shader into
|
||||||
// a unique identifier, basically containing all the bits. Yup, it's a lot ....
|
// a unique identifier, basically containing all the bits. Yup, it's a lot ....
|
||||||
void GetVertexShaderId(VERTEXSHADERUID& vid, u32 components)
|
void GetVertexShaderId(VERTEXSHADERUID *uid, u32 components)
|
||||||
{
|
{
|
||||||
vid.values[0] = components |
|
uid->values[0] = components |
|
||||||
(xfregs.numTexGens << 23) |
|
(xfregs.numTexGens << 23) |
|
||||||
(xfregs.nNumChans << 27) |
|
(xfregs.nNumChans << 27) |
|
||||||
((u32)xfregs.bEnableDualTexTransform << 29);
|
((u32)xfregs.bEnableDualTexTransform << 29);
|
||||||
|
|
||||||
for (int i = 0; i < 2; ++i) {
|
for (int i = 0; i < 2; ++i) {
|
||||||
vid.values[1+i] = xfregs.colChans[i].color.enablelighting ?
|
uid->values[1+i] = xfregs.colChans[i].color.enablelighting ?
|
||||||
(u32)xfregs.colChans[i].color.hex :
|
(u32)xfregs.colChans[i].color.hex :
|
||||||
(u32)xfregs.colChans[i].color.matsource;
|
(u32)xfregs.colChans[i].color.matsource;
|
||||||
vid.values[1+i] |= (xfregs.colChans[i].alpha.enablelighting ?
|
uid->values[1+i] |= (xfregs.colChans[i].alpha.enablelighting ?
|
||||||
(u32)xfregs.colChans[i].alpha.hex :
|
(u32)xfregs.colChans[i].alpha.hex :
|
||||||
(u32)xfregs.colChans[i].alpha.matsource) << 15;
|
(u32)xfregs.colChans[i].alpha.matsource) << 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
// fog
|
// fog
|
||||||
vid.values[1] |= (((u32)bpmem.fog.c_proj_fsel.fsel & 3) << 30);
|
uid->values[1] |= (((u32)bpmem.fog.c_proj_fsel.fsel & 3) << 30);
|
||||||
vid.values[2] |= (((u32)bpmem.fog.c_proj_fsel.fsel >> 2) << 30);
|
uid->values[2] |= (((u32)bpmem.fog.c_proj_fsel.fsel >> 2) << 30);
|
||||||
|
|
||||||
u32* pcurvalue = &vid.values[3];
|
u32 *pcurvalue = &uid->values[3];
|
||||||
for (int i = 0; i < xfregs.numTexGens; ++i) {
|
for (int i = 0; i < xfregs.numTexGens; ++i) {
|
||||||
TexMtxInfo tinfo = xfregs.texcoords[i].texmtxinfo;
|
TexMtxInfo tinfo = xfregs.texcoords[i].texmtxinfo;
|
||||||
if (tinfo.texgentype != XF_TEXGEN_EMBOSS_MAP)
|
if (tinfo.texgentype != XF_TEXGEN_EMBOSS_MAP)
|
||||||
@ -78,16 +78,16 @@ static char text[16384];
|
|||||||
|
|
||||||
#define LIGHTS_POS ""
|
#define LIGHTS_POS ""
|
||||||
|
|
||||||
char *GenerateLightShader(char* p, int index, const LitChannel& chan, const char* dest, int coloralpha);
|
char *GenerateLightShader(char *p, int index, const LitChannel& chan, const char *dest, int coloralpha);
|
||||||
|
|
||||||
const char *GenerateVertexShader(u32 components, bool D3D)
|
const char *GenerateVertexShaderCode(u32 components, bool D3D)
|
||||||
{
|
{
|
||||||
setlocale(LC_NUMERIC, "C"); // Reset locale for compilation
|
setlocale(LC_NUMERIC, "C"); // Reset locale for compilation
|
||||||
text[sizeof(text) - 1] = 0x7C; // canary
|
text[sizeof(text) - 1] = 0x7C; // canary
|
||||||
DVSTARTPROFILE();
|
DVSTARTPROFILE();
|
||||||
|
|
||||||
_assert_( bpmem.genMode.numtexgens == xfregs.numTexGens);
|
_assert_(bpmem.genMode.numtexgens == xfregs.numTexGens);
|
||||||
_assert_( bpmem.genMode.numcolchans == xfregs.nNumChans);
|
_assert_(bpmem.genMode.numcolchans == xfregs.nNumChans);
|
||||||
|
|
||||||
u32 lightMask = 0;
|
u32 lightMask = 0;
|
||||||
if (xfregs.nNumChans > 0)
|
if (xfregs.nNumChans > 0)
|
||||||
@ -125,9 +125,8 @@ const char *GenerateVertexShader(u32 components, bool D3D)
|
|||||||
WRITE(p, "};\n");
|
WRITE(p, "};\n");
|
||||||
|
|
||||||
// uniforms
|
// uniforms
|
||||||
// bool bTexMtx = ((components & VB_HAS_TEXMTXIDXALL)<<VB_HAS_UVTEXMTXSHIFT)!=0; unused TODO: keep?
|
|
||||||
|
|
||||||
WRITE(p, "uniform s_"I_TRANSFORMMATRICES" "I_TRANSFORMMATRICES" : register(c%d);\n", C_TRANSFORMMATRICES);
|
WRITE(p, "uniform s_"I_TRANSFORMMATRICES" "I_TRANSFORMMATRICES" : register(c%d);\n", C_TRANSFORMMATRICES);
|
||||||
WRITE(p, "uniform s_"I_TEXMATRICES" "I_TEXMATRICES" : register(c%d);\n", C_TEXMATRICES); // also using tex matrices
|
WRITE(p, "uniform s_"I_TEXMATRICES" "I_TEXMATRICES" : register(c%d);\n", C_TEXMATRICES); // also using tex matrices
|
||||||
WRITE(p, "uniform s_"I_NORMALMATRICES" "I_NORMALMATRICES" : register(c%d);\n", C_NORMALMATRICES);
|
WRITE(p, "uniform s_"I_NORMALMATRICES" "I_NORMALMATRICES" : register(c%d);\n", C_NORMALMATRICES);
|
||||||
WRITE(p, "uniform s_"I_POSNORMALMATRIX" "I_POSNORMALMATRIX" : register(c%d);\n", C_POSNORMALMATRIX);
|
WRITE(p, "uniform s_"I_POSNORMALMATRIX" "I_POSNORMALMATRIX" : register(c%d);\n", C_POSNORMALMATRIX);
|
||||||
@ -406,7 +405,7 @@ const char *GenerateVertexShader(u32 components, bool D3D)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(xfregs.bEnableDualTexTransform && texinfo.texgentype == XF_TEXGEN_REGULAR) { // only works for regular tex gen types?
|
if (xfregs.bEnableDualTexTransform && texinfo.texgentype == XF_TEXGEN_REGULAR) { // only works for regular tex gen types?
|
||||||
int postidx = xfregs.texcoords[i].postmtxinfo.index;
|
int postidx = xfregs.texcoords[i].postmtxinfo.index;
|
||||||
WRITE(p, "float4 P0 = "I_POSTTRANSFORMMATRICES".T[%d].t;\n"
|
WRITE(p, "float4 P0 = "I_POSTTRANSFORMMATRICES".T[%d].t;\n"
|
||||||
"float4 P1 = "I_POSTTRANSFORMMATRICES".T[%d].t;\n"
|
"float4 P1 = "I_POSTTRANSFORMMATRICES".T[%d].t;\n"
|
||||||
@ -461,7 +460,7 @@ const char *GenerateVertexShader(u32 components, bool D3D)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// coloralpha - 1 if color, 2 if alpha
|
// coloralpha - 1 if color, 2 if alpha
|
||||||
char* GenerateLightShader(char* p, int index, const LitChannel& chan, const char* dest, int coloralpha)
|
char *GenerateLightShader(char *p, int index, const LitChannel& chan, const char *dest, int coloralpha)
|
||||||
{
|
{
|
||||||
const char* swizzle = "xyzw";
|
const char* swizzle = "xyzw";
|
||||||
if (coloralpha == 1 ) swizzle = "xyz";
|
if (coloralpha == 1 ) swizzle = "xyz";
|
||||||
|
@ -99,8 +99,10 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *GenerateVertexShader(u32 components, bool D3D);
|
// components is included in the uid.
|
||||||
void GetVertexShaderId(VERTEXSHADERUID& vid, u32 components);
|
const char *GenerateVertexShaderCode(u32 components, bool D3D);
|
||||||
|
void GetVertexShaderId(VERTEXSHADERUID *uid, u32 components);
|
||||||
|
|
||||||
extern VERTEXSHADERUID last_vertex_shader_uid;
|
extern VERTEXSHADERUID last_vertex_shader_uid;
|
||||||
|
|
||||||
#endif // GCOGL_VERTEXSHADER_H
|
#endif // GCOGL_VERTEXSHADER_H
|
||||||
|
@ -112,7 +112,11 @@ struct Resolution
|
|||||||
|
|
||||||
struct AALevel
|
struct AALevel
|
||||||
{
|
{
|
||||||
AALevel(const char *n, D3DMULTISAMPLE_TYPE m, int q) {strcpy(name, n); ms_setting=m; qual_setting=q;}
|
AALevel(const char *n, D3DMULTISAMPLE_TYPE m, int q) {
|
||||||
|
strcpy(name, n);
|
||||||
|
ms_setting = m;
|
||||||
|
qual_setting = q;
|
||||||
|
}
|
||||||
char name[32];
|
char name[32];
|
||||||
D3DMULTISAMPLE_TYPE ms_setting;
|
D3DMULTISAMPLE_TYPE ms_setting;
|
||||||
int qual_setting;
|
int qual_setting;
|
||||||
|
@ -24,12 +24,22 @@
|
|||||||
namespace D3D
|
namespace D3D
|
||||||
{
|
{
|
||||||
|
|
||||||
LPDIRECT3DVERTEXSHADER9 CompileVertexShader(const char *code, int len)
|
// Bytecode->shader.
|
||||||
|
LPDIRECT3DVERTEXSHADER9 CreateVertexShaderFromByteCode(const u8 *bytecode, int len)
|
||||||
|
{
|
||||||
|
LPDIRECT3DVERTEXSHADER9 v_shader;
|
||||||
|
HRESULT hr = D3D::dev->CreateVertexShader((DWORD *)bytecode, &v_shader);
|
||||||
|
if (FAILED(hr))
|
||||||
|
v_shader = 0;
|
||||||
|
return v_shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Code->bytecode.
|
||||||
|
bool CompileVertexShader(const char *code, int len, u8 **bytecode, int *bytecodelen)
|
||||||
{
|
{
|
||||||
//try to compile
|
//try to compile
|
||||||
LPD3DXBUFFER shaderBuffer = 0;
|
LPD3DXBUFFER shaderBuffer = 0;
|
||||||
LPD3DXBUFFER errorBuffer = 0;
|
LPD3DXBUFFER errorBuffer = 0;
|
||||||
LPDIRECT3DVERTEXSHADER9 vShader = 0;
|
|
||||||
HRESULT hr = D3DXCompileShader(code, len, 0, 0, "main", D3D::VertexShaderVersionString(),
|
HRESULT hr = D3DXCompileShader(code, len, 0, 0, "main", D3D::VertexShaderVersionString(),
|
||||||
0, &shaderBuffer, &errorBuffer, 0);
|
0, &shaderBuffer, &errorBuffer, 0);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
@ -39,20 +49,16 @@ LPDIRECT3DVERTEXSHADER9 CompileVertexShader(const char *code, int len)
|
|||||||
std::string hello = (char*)errorBuffer->GetBufferPointer();
|
std::string hello = (char*)errorBuffer->GetBufferPointer();
|
||||||
hello += "\n\n";
|
hello += "\n\n";
|
||||||
hello += code;
|
hello += code;
|
||||||
MessageBoxA(0, hello.c_str(), "Error assembling vertex shader", MB_ICONERROR);
|
MessageBoxA(0, hello.c_str(), "Error compiling vertex shader", MB_ICONERROR);
|
||||||
}
|
}
|
||||||
vShader = 0;
|
*bytecode = 0;
|
||||||
|
*bytecodelen = 0;
|
||||||
}
|
}
|
||||||
else if (SUCCEEDED(hr))
|
else if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
//create it
|
*bytecodelen = shaderBuffer->GetBufferSize();
|
||||||
HRESULT hr = E_FAIL;
|
*bytecode = new u8[*bytecodelen];
|
||||||
if (shaderBuffer)
|
memcpy(*bytecode, shaderBuffer->GetBufferPointer(), *bytecodelen);
|
||||||
hr = D3D::dev->CreateVertexShader((DWORD *)shaderBuffer->GetBufferPointer(), &vShader);
|
|
||||||
if ((FAILED(hr) || vShader == 0) && g_ActiveConfig.bShowShaderErrors)
|
|
||||||
{
|
|
||||||
MessageBoxA(0, code, (char*)errorBuffer->GetBufferPointer(), MB_ICONERROR);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
@ -60,14 +66,25 @@ LPDIRECT3DVERTEXSHADER9 CompileVertexShader(const char *code, int len)
|
|||||||
shaderBuffer->Release();
|
shaderBuffer->Release();
|
||||||
if (errorBuffer)
|
if (errorBuffer)
|
||||||
errorBuffer->Release();
|
errorBuffer->Release();
|
||||||
return vShader;
|
return SUCCEEDED(hr) ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
LPDIRECT3DPIXELSHADER9 CompilePixelShader(const char *code, int len)
|
|
||||||
|
// Bytecode->shader.
|
||||||
|
LPDIRECT3DPIXELSHADER9 CreatePixelShaderFromByteCode(const u8 *bytecode, int len)
|
||||||
|
{
|
||||||
|
LPDIRECT3DPIXELSHADER9 p_shader;
|
||||||
|
HRESULT hr = D3D::dev->CreatePixelShader((DWORD *)bytecode, &p_shader);
|
||||||
|
if (FAILED(hr))
|
||||||
|
p_shader = 0;
|
||||||
|
return p_shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CompilePixelShader(const char *code, int len, u8 **bytecode, int *bytecodelen)
|
||||||
{
|
{
|
||||||
LPD3DXBUFFER shaderBuffer = 0;
|
LPD3DXBUFFER shaderBuffer = 0;
|
||||||
LPD3DXBUFFER errorBuffer = 0;
|
LPD3DXBUFFER errorBuffer = 0;
|
||||||
LPDIRECT3DPIXELSHADER9 pShader = 0;
|
|
||||||
|
|
||||||
// Someone:
|
// Someone:
|
||||||
// For some reason, I had this kind of errors : "Shader uses texture addressing operations
|
// For some reason, I had this kind of errors : "Shader uses texture addressing operations
|
||||||
@ -81,18 +98,16 @@ LPDIRECT3DPIXELSHADER9 CompilePixelShader(const char *code, int len)
|
|||||||
std::string hello = (char*)errorBuffer->GetBufferPointer();
|
std::string hello = (char*)errorBuffer->GetBufferPointer();
|
||||||
hello += "\n\n";
|
hello += "\n\n";
|
||||||
hello += code;
|
hello += code;
|
||||||
MessageBoxA(0, hello.c_str(), "Error assembling pixel shader", MB_ICONERROR);
|
MessageBoxA(0, hello.c_str(), "Error compiling pixel shader", MB_ICONERROR);
|
||||||
}
|
}
|
||||||
pShader = 0;
|
*bytecode = 0;
|
||||||
|
*bytecodelen = 0;
|
||||||
}
|
}
|
||||||
else
|
else if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
//create it
|
*bytecodelen = shaderBuffer->GetBufferSize();
|
||||||
HRESULT hr = D3D::dev->CreatePixelShader((DWORD *)shaderBuffer->GetBufferPointer(), &pShader);
|
*bytecode = new u8[*bytecodelen];
|
||||||
if ((FAILED(hr) || pShader == 0) && g_ActiveConfig.bShowShaderErrors)
|
memcpy(*bytecode, shaderBuffer->GetBufferPointer(), *bytecodelen);
|
||||||
{
|
|
||||||
MessageBoxA(0, "damn", "error creating pixelshader", MB_ICONERROR);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
@ -100,7 +115,31 @@ LPDIRECT3DPIXELSHADER9 CompilePixelShader(const char *code, int len)
|
|||||||
shaderBuffer->Release();
|
shaderBuffer->Release();
|
||||||
if (errorBuffer)
|
if (errorBuffer)
|
||||||
errorBuffer->Release();
|
errorBuffer->Release();
|
||||||
return pShader;
|
return SUCCEEDED(hr) ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LPDIRECT3DVERTEXSHADER9 CompileAndCreateVertexShader(const char *code, int len) {
|
||||||
|
u8 *bytecode;
|
||||||
|
int bytecodelen;
|
||||||
|
if (CompileVertexShader(code, len, &bytecode, &bytecodelen)) {
|
||||||
|
LPDIRECT3DVERTEXSHADER9 v_shader = CreateVertexShaderFromByteCode(bytecode, len);
|
||||||
|
delete [] bytecode;
|
||||||
|
return v_shader;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LPDIRECT3DPIXELSHADER9 CompileAndCreatePixelShader(const char *code, int len) {
|
||||||
|
u8 *bytecode;
|
||||||
|
int bytecodelen;
|
||||||
|
if (CompilePixelShader(code, len, &bytecode, &bytecodelen)) {
|
||||||
|
LPDIRECT3DPIXELSHADER9 p_shader = CreatePixelShaderFromByteCode(bytecode, len);
|
||||||
|
delete [] bytecode;
|
||||||
|
return p_shader;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -21,6 +21,14 @@
|
|||||||
|
|
||||||
namespace D3D
|
namespace D3D
|
||||||
{
|
{
|
||||||
LPDIRECT3DVERTEXSHADER9 CompileVertexShader(const char *code, int len);
|
LPDIRECT3DVERTEXSHADER9 CreateVertexShaderFromByteCode(const u8 *bytecode, int len);
|
||||||
LPDIRECT3DPIXELSHADER9 CompilePixelShader(const char *code, int len);
|
LPDIRECT3DPIXELSHADER9 CreatePixelShaderFromByteCode(const u8 *bytecode, int len);
|
||||||
|
|
||||||
|
// The returned bytecode buffers should be delete[]-d.
|
||||||
|
bool CompileVertexShader(const char *code, int len, u8 **bytecode, int *bytecodelen);
|
||||||
|
bool CompilePixelShader(const char *code, int len, u8 **bytecode, int *bytecodelen);
|
||||||
|
|
||||||
|
// Utility functions
|
||||||
|
LPDIRECT3DVERTEXSHADER9 CompileAndCreateVertexShader(const char *code, int len);
|
||||||
|
LPDIRECT3DPIXELSHADER9 CompileAndCreatePixelShader(const char *code, int len);
|
||||||
}
|
}
|
@ -15,11 +15,15 @@
|
|||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
|
#include "Common.h"
|
||||||
|
#include "FileUtil.h"
|
||||||
|
#include "LinearDiskCache.h"
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
#include "D3DBase.h"
|
#include "D3DBase.h"
|
||||||
#include "D3DShader.h"
|
#include "D3DShader.h"
|
||||||
#include "Statistics.h"
|
#include "Statistics.h"
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
#include "Profiler.h"
|
|
||||||
#include "VideoConfig.h"
|
#include "VideoConfig.h"
|
||||||
#include "PixelShaderGen.h"
|
#include "PixelShaderGen.h"
|
||||||
#include "PixelShaderManager.h"
|
#include "PixelShaderManager.h"
|
||||||
@ -29,10 +33,13 @@
|
|||||||
#include "XFMemory.h"
|
#include "XFMemory.h"
|
||||||
#include "ImageWrite.h"
|
#include "ImageWrite.h"
|
||||||
|
|
||||||
#include "debugger/debugger.h"
|
#include "Debugger/Debugger.h"
|
||||||
|
|
||||||
PixelShaderCache::PSCache PixelShaderCache::PixelShaders;
|
PixelShaderCache::PSCache PixelShaderCache::PixelShaders;
|
||||||
const PixelShaderCache::PSCacheEntry *PixelShaderCache::last_entry;
|
const PixelShaderCache::PSCacheEntry *PixelShaderCache::last_entry;
|
||||||
|
|
||||||
|
LinearDiskCache g_ps_disk_cache;
|
||||||
|
|
||||||
static float lastPSconstants[C_COLORMATRIX+16][4];
|
static float lastPSconstants[C_COLORMATRIX+16][4];
|
||||||
|
|
||||||
static LPDIRECT3DPIXELSHADER9 s_ColorMatrixProgram = 0;
|
static LPDIRECT3DPIXELSHADER9 s_ColorMatrixProgram = 0;
|
||||||
@ -41,7 +48,6 @@ static LPDIRECT3DPIXELSHADER9 s_ClearProgram = 0;
|
|||||||
static LPDIRECT3DPIXELSHADER9 s_ClearZProgram = 0;
|
static LPDIRECT3DPIXELSHADER9 s_ClearZProgram = 0;
|
||||||
static LPDIRECT3DPIXELSHADER9 s_DepthMatrixProgram = 0;
|
static LPDIRECT3DPIXELSHADER9 s_DepthMatrixProgram = 0;
|
||||||
|
|
||||||
|
|
||||||
LPDIRECT3DPIXELSHADER9 PixelShaderCache::GetColorMatrixProgram()
|
LPDIRECT3DPIXELSHADER9 PixelShaderCache::GetColorMatrixProgram()
|
||||||
{
|
{
|
||||||
return s_ColorMatrixProgram;
|
return s_ColorMatrixProgram;
|
||||||
@ -64,7 +70,7 @@ LPDIRECT3DPIXELSHADER9 PixelShaderCache::GetClearProgram()
|
|||||||
|
|
||||||
void SetPSConstant4f(int const_number, float f1, float f2, float f3, float f4)
|
void SetPSConstant4f(int const_number, float f1, float f2, float f3, float f4)
|
||||||
{
|
{
|
||||||
if( lastPSconstants[const_number][0] != f1 || lastPSconstants[const_number][1] != f2 ||
|
if (lastPSconstants[const_number][0] != f1 || lastPSconstants[const_number][1] != f2 ||
|
||||||
lastPSconstants[const_number][2] != f3 || lastPSconstants[const_number][3] != f4 )
|
lastPSconstants[const_number][2] != f3 || lastPSconstants[const_number][3] != f4 )
|
||||||
{
|
{
|
||||||
const float f[4] = {f1, f2, f3, f4};
|
const float f[4] = {f1, f2, f3, f4};
|
||||||
@ -78,7 +84,7 @@ void SetPSConstant4f(int const_number, float f1, float f2, float f3, float f4)
|
|||||||
|
|
||||||
void SetPSConstant4fv(int const_number, const float *f)
|
void SetPSConstant4fv(int const_number, const float *f)
|
||||||
{
|
{
|
||||||
if( lastPSconstants[const_number][0] != f[0] || lastPSconstants[const_number][1] != f[1] ||
|
if (lastPSconstants[const_number][0] != f[0] || lastPSconstants[const_number][1] != f[1] ||
|
||||||
lastPSconstants[const_number][2] != f[2] || lastPSconstants[const_number][3] != f[3] )
|
lastPSconstants[const_number][2] != f[2] || lastPSconstants[const_number][3] != f[3] )
|
||||||
{
|
{
|
||||||
D3D::dev->SetPixelShaderConstantF(const_number, f, 1);
|
D3D::dev->SetPixelShaderConstantF(const_number, f, 1);
|
||||||
@ -89,25 +95,39 @@ void SetPSConstant4fv(int const_number, const float *f)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class PixelShaderCacheInserter : public LinearDiskCacheReader {
|
||||||
|
public:
|
||||||
|
void Read(const u8 *key, int key_size, const u8 *value, int value_size)
|
||||||
|
{
|
||||||
|
PIXELSHADERUID uid;
|
||||||
|
if (key_size != sizeof(uid)) {
|
||||||
|
ERROR_LOG(VIDEO, "Wrong key size in pixel shader cache");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memcpy(&uid, key, key_size);
|
||||||
|
PixelShaderCache::InsertByteCode(uid, value, value_size, false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void PixelShaderCache::Init()
|
void PixelShaderCache::Init()
|
||||||
{
|
{
|
||||||
char pprog[1024];
|
char pprog[1024];
|
||||||
sprintf(pprog,"void main(\n"
|
sprintf(pprog, "void main(\n"
|
||||||
"out float4 ocol0 : COLOR0,\n"
|
"out float4 ocol0 : COLOR0,\n"
|
||||||
" in float4 incol0 : COLOR0){\n"
|
" in float4 incol0 : COLOR0){\n"
|
||||||
"ocol0 = incol0;\n"
|
"ocol0 = incol0;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
s_ClearProgram = D3D::CompilePixelShader(pprog, (int)strlen(pprog));
|
s_ClearProgram = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
|
||||||
|
|
||||||
sprintf(pprog,"uniform sampler samp0 : register(s0);\n"
|
sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
|
||||||
"void main(\n"
|
"void main(\n"
|
||||||
"out float4 ocol0 : COLOR0,\n"
|
"out float4 ocol0 : COLOR0,\n"
|
||||||
" in float3 uv0 : TEXCOORD0){\n"
|
" in float3 uv0 : TEXCOORD0){\n"
|
||||||
"ocol0 = tex2D(samp0,uv0.xy);\n"
|
"ocol0 = tex2D(samp0,uv0.xy);\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
s_ColorCopyProgram = D3D::CompilePixelShader(pprog, (int)strlen(pprog));
|
s_ColorCopyProgram = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
|
||||||
|
|
||||||
sprintf(pprog,"uniform sampler samp0 : register(s0);\n"
|
sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
|
||||||
"uniform float4 cColMatrix[5] : register(c%d);\n"
|
"uniform float4 cColMatrix[5] : register(c%d);\n"
|
||||||
"void main(\n"
|
"void main(\n"
|
||||||
"out float4 ocol0 : COLOR0,\n"
|
"out float4 ocol0 : COLOR0,\n"
|
||||||
@ -115,9 +135,9 @@ void PixelShaderCache::Init()
|
|||||||
"float4 texcol = tex2D(samp0,uv0.xy);\n"
|
"float4 texcol = tex2D(samp0,uv0.xy);\n"
|
||||||
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
|
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
|
||||||
"}\n",C_COLORMATRIX);
|
"}\n",C_COLORMATRIX);
|
||||||
s_ColorMatrixProgram = D3D::CompilePixelShader(pprog, (int)strlen(pprog));
|
s_ColorMatrixProgram = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
|
||||||
|
|
||||||
sprintf(pprog,"uniform sampler samp0 : register(s0);\n"
|
sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
|
||||||
"uniform float4 cColMatrix[5] : register(c%d);\n"
|
"uniform float4 cColMatrix[5] : register(c%d);\n"
|
||||||
"void main(\n"
|
"void main(\n"
|
||||||
"out float4 ocol0 : COLOR0,\n"
|
"out float4 ocol0 : COLOR0,\n"
|
||||||
@ -127,10 +147,19 @@ void PixelShaderCache::Init()
|
|||||||
"texcol = float4((EncodedDepth.rgb * (16777216.0f/16777215.0f)),1.0f);\n"
|
"texcol = float4((EncodedDepth.rgb * (16777216.0f/16777215.0f)),1.0f);\n"
|
||||||
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
|
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
|
||||||
"}\n",C_COLORMATRIX);
|
"}\n",C_COLORMATRIX);
|
||||||
s_DepthMatrixProgram = D3D::CompilePixelShader(pprog, (int)strlen(pprog));
|
s_DepthMatrixProgram = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
|
||||||
Clear();
|
Clear();
|
||||||
|
|
||||||
|
if (!File::Exists(FULL_SHADERCACHE_DIR))
|
||||||
|
File::CreateDir(FULL_SHADERCACHE_DIR);
|
||||||
|
|
||||||
|
char cache_filename[MAX_PATH];
|
||||||
|
sprintf(cache_filename, "%s%s-ps.cache", FULL_SHADERCACHE_DIR, globals->unique_id);
|
||||||
|
PixelShaderCacheInserter inserter;
|
||||||
|
int read_items = g_ps_disk_cache.OpenAndRead(cache_filename, &inserter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ONLY to be used during shutdown.
|
||||||
void PixelShaderCache::Clear()
|
void PixelShaderCache::Clear()
|
||||||
{
|
{
|
||||||
PSCache::iterator iter = PixelShaders.begin();
|
PSCache::iterator iter = PixelShaders.begin();
|
||||||
@ -139,45 +168,44 @@ void PixelShaderCache::Clear()
|
|||||||
PixelShaders.clear();
|
PixelShaders.clear();
|
||||||
|
|
||||||
for (int i = 0; i < (C_COLORMATRIX + 16) * 4; i++)
|
for (int i = 0; i < (C_COLORMATRIX + 16) * 4; i++)
|
||||||
lastPSconstants[i/4][i%4] = -100000000.0f;
|
lastPSconstants[i / 4][i % 4] = -100000000.0f;
|
||||||
memset(&last_pixel_shader_uid, 0xFF, sizeof(last_pixel_shader_uid));
|
memset(&last_pixel_shader_uid, 0xFF, sizeof(last_pixel_shader_uid));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PixelShaderCache::Shutdown()
|
void PixelShaderCache::Shutdown()
|
||||||
{
|
{
|
||||||
if(s_ColorMatrixProgram)
|
if (s_ColorMatrixProgram) s_ColorMatrixProgram->Release();
|
||||||
s_ColorMatrixProgram->Release();
|
|
||||||
s_ColorMatrixProgram = NULL;
|
s_ColorMatrixProgram = NULL;
|
||||||
if(s_ColorCopyProgram)
|
if (s_ColorCopyProgram) s_ColorCopyProgram->Release();
|
||||||
s_ColorCopyProgram->Release();
|
s_ColorCopyProgram = NULL;
|
||||||
s_ColorCopyProgram=NULL;
|
if (s_DepthMatrixProgram) s_DepthMatrixProgram->Release();
|
||||||
if(s_DepthMatrixProgram)
|
|
||||||
s_DepthMatrixProgram->Release();
|
|
||||||
s_DepthMatrixProgram = NULL;
|
s_DepthMatrixProgram = NULL;
|
||||||
if(s_ClearProgram)
|
if (s_ClearProgram) s_ClearProgram->Release();
|
||||||
s_ClearProgram->Release();
|
s_ClearProgram = NULL;
|
||||||
s_ClearProgram=NULL;
|
|
||||||
|
|
||||||
Clear();
|
Clear();
|
||||||
|
g_ps_disk_cache.Sync();
|
||||||
|
g_ps_disk_cache.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PixelShaderCache::SetShader(bool dstAlpha)
|
bool PixelShaderCache::SetShader(bool dstAlpha)
|
||||||
{
|
{
|
||||||
DVSTARTPROFILE();
|
|
||||||
|
|
||||||
PIXELSHADERUID uid;
|
PIXELSHADERUID uid;
|
||||||
GetPixelShaderId(uid, PixelShaderManager::GetTextureMask(), dstAlpha);
|
GetPixelShaderId(&uid, PixelShaderManager::GetTextureMask(), dstAlpha);
|
||||||
|
|
||||||
|
// Is the shader already set?
|
||||||
if (uid == last_pixel_shader_uid && PixelShaders[uid].frameCount == frameCount)
|
if (uid == last_pixel_shader_uid && PixelShaders[uid].frameCount == frameCount)
|
||||||
{
|
{
|
||||||
PSCache::const_iterator iter = PixelShaders.find(uid);
|
PSCache::const_iterator iter = PixelShaders.find(uid);
|
||||||
if (iter != PixelShaders.end() && iter->second.shader)
|
if (iter != PixelShaders.end() && iter->second.shader)
|
||||||
return true;
|
return true; // Sure, we're done.
|
||||||
else
|
else
|
||||||
return false;
|
return false; // ?? something is wrong.
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(&last_pixel_shader_uid, &uid, sizeof(PIXELSHADERUID));
|
memcpy(&last_pixel_shader_uid, &uid, sizeof(PIXELSHADERUID));
|
||||||
|
|
||||||
|
// Is the shader already in the cache?
|
||||||
PSCache::iterator iter;
|
PSCache::iterator iter;
|
||||||
iter = PixelShaders.find(uid);
|
iter = PixelShaders.find(uid);
|
||||||
if (iter != PixelShaders.end())
|
if (iter != PixelShaders.end())
|
||||||
@ -186,7 +214,6 @@ bool PixelShaderCache::SetShader(bool dstAlpha)
|
|||||||
const PSCacheEntry &entry = iter->second;
|
const PSCacheEntry &entry = iter->second;
|
||||||
last_entry = &entry;
|
last_entry = &entry;
|
||||||
|
|
||||||
|
|
||||||
DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE,true);
|
DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE,true);
|
||||||
|
|
||||||
if (entry.shader)
|
if (entry.shader)
|
||||||
@ -198,7 +225,8 @@ bool PixelShaderCache::SetShader(bool dstAlpha)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *code = GeneratePixelShader(PixelShaderManager::GetTextureMask(), dstAlpha, 2);
|
// OK, need to generate and compile it.
|
||||||
|
const char *code = GeneratePixelShaderCode(PixelShaderManager::GetTextureMask(), dstAlpha, 2);
|
||||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||||
if (g_ActiveConfig.iLog & CONF_SAVESHADERS && code) {
|
if (g_ActiveConfig.iLog & CONF_SAVESHADERS && code) {
|
||||||
static int counter = 0;
|
static int counter = 0;
|
||||||
@ -208,7 +236,29 @@ bool PixelShaderCache::SetShader(bool dstAlpha)
|
|||||||
SaveData(szTemp, code);
|
SaveData(szTemp, code);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
LPDIRECT3DPIXELSHADER9 shader = D3D::CompilePixelShader(code, (int)strlen(code));
|
|
||||||
|
u8 *bytecode = 0;
|
||||||
|
int bytecodelen = 0;
|
||||||
|
if (!D3D::CompilePixelShader(code, (int)strlen(code), &bytecode, &bytecodelen)) {
|
||||||
|
if (g_ActiveConfig.bShowShaderErrors)
|
||||||
|
{
|
||||||
|
PanicAlert("Failed to compile Pixel Shader:\n\n%s", code);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Here we have the UID and the byte code. Insert it into the disk cache.
|
||||||
|
g_ps_disk_cache.Append((u8 *)&uid, sizeof(uid), bytecode, bytecodelen);
|
||||||
|
g_ps_disk_cache.Sync();
|
||||||
|
|
||||||
|
// And insert it into the shader cache.
|
||||||
|
bool result = InsertByteCode(uid, bytecode, bytecodelen, true);
|
||||||
|
delete [] bytecode;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PixelShaderCache::InsertByteCode(const PIXELSHADERUID &uid, const u8 *bytecode, int bytecodelen, bool activate) {
|
||||||
|
LPDIRECT3DPIXELSHADER9 shader = D3D::CreatePixelShaderFromByteCode(bytecode, bytecodelen);
|
||||||
|
|
||||||
// Make an entry in the table
|
// Make an entry in the table
|
||||||
PSCacheEntry newentry;
|
PSCacheEntry newentry;
|
||||||
@ -220,44 +270,21 @@ bool PixelShaderCache::SetShader(bool dstAlpha)
|
|||||||
PixelShaders[uid] = newentry;
|
PixelShaders[uid] = newentry;
|
||||||
last_entry = &PixelShaders[uid];
|
last_entry = &PixelShaders[uid];
|
||||||
|
|
||||||
|
if (!shader) {
|
||||||
|
// INCSTAT(stats.numPixelShadersFailed);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
INCSTAT(stats.numPixelShadersCreated);
|
INCSTAT(stats.numPixelShadersCreated);
|
||||||
SETSTAT(stats.numPixelShadersAlive, (int)PixelShaders.size());
|
SETSTAT(stats.numPixelShadersAlive, (int)PixelShaders.size());
|
||||||
if (shader)
|
if (activate)
|
||||||
{
|
{
|
||||||
D3D::SetPixelShader(shader);
|
D3D::SetPixelShader(shader);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
if (g_ActiveConfig.bShowShaderErrors)
|
|
||||||
{
|
|
||||||
PanicAlert("Failed to compile Pixel Shader:\n\n%s", code);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PixelShaderCache::Cleanup()
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
PSCache::iterator iter;
|
|
||||||
iter = PixelShaders.begin();
|
|
||||||
while (iter != PixelShaders.end())
|
|
||||||
{
|
|
||||||
PSCacheEntry &entry = iter->second;
|
|
||||||
if (entry.frameCount < frameCount - 1400)
|
|
||||||
{
|
|
||||||
entry.Destroy();
|
|
||||||
iter = PixelShaders.erase(iter);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
iter++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SETSTAT(stats.numPixelShadersAlive, (int)PixelShaders.size());
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||||
std::string PixelShaderCache::GetCurrentShaderCode()
|
std::string PixelShaderCache::GetCurrentShaderCode()
|
||||||
{
|
{
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
#ifndef _PIXELSHADERCACHE_H
|
#ifndef _PIXELSHADERCACHE_H
|
||||||
#define _PIXELSHADERCACHE_H
|
#define _PIXELSHADERCACHE_H
|
||||||
|
|
||||||
|
#include "Common.h"
|
||||||
|
#include "LinearDiskCache.h"
|
||||||
#include "D3DBase.h"
|
#include "D3DBase.h"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
@ -53,12 +55,13 @@ private:
|
|||||||
static PSCache PixelShaders;
|
static PSCache PixelShaders;
|
||||||
static const PSCacheEntry *last_entry;
|
static const PSCacheEntry *last_entry;
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void Init();
|
static void Init();
|
||||||
static void Cleanup();
|
|
||||||
static void Clear();
|
static void Clear();
|
||||||
static void Shutdown();
|
static void Shutdown();
|
||||||
static bool SetShader(bool dstAlpha);
|
static bool SetShader(bool dstAlpha);
|
||||||
|
static bool InsertByteCode(const PIXELSHADERUID &uid, const u8 *bytecode, int bytecodelen, bool activate);
|
||||||
static LPDIRECT3DPIXELSHADER9 GetColorMatrixProgram();
|
static LPDIRECT3DPIXELSHADER9 GetColorMatrixProgram();
|
||||||
static LPDIRECT3DPIXELSHADER9 GetColorCopyProgram();
|
static LPDIRECT3DPIXELSHADER9 GetColorCopyProgram();
|
||||||
static LPDIRECT3DPIXELSHADER9 GetDepthMatrixProgram();
|
static LPDIRECT3DPIXELSHADER9 GetDepthMatrixProgram();
|
||||||
|
@ -272,7 +272,7 @@ bool Renderer::Init()
|
|||||||
|
|
||||||
xScale = (float)s_target_width / (float)EFB_WIDTH;
|
xScale = (float)s_target_width / (float)EFB_WIDTH;
|
||||||
yScale = (float)s_target_height / (float)EFB_HEIGHT;
|
yScale = (float)s_target_height / (float)EFB_HEIGHT;
|
||||||
if(!D3D::IsATIDevice())
|
if (!D3D::IsATIDevice())
|
||||||
{
|
{
|
||||||
FULL_EFB_WIDTH = 2 * EFB_WIDTH;
|
FULL_EFB_WIDTH = 2 * EFB_WIDTH;
|
||||||
FULL_EFB_HEIGHT = 2 * EFB_HEIGHT;
|
FULL_EFB_HEIGHT = 2 * EFB_HEIGHT;
|
||||||
@ -301,6 +301,7 @@ bool Renderer::Init()
|
|||||||
|
|
||||||
for (int stage = 0; stage < 8; stage++)
|
for (int stage = 0; stage < 8; stage++)
|
||||||
D3D::SetSamplerState(stage, D3DSAMP_MAXANISOTROPY, g_ActiveConfig.iMaxAnisotropy);
|
D3D::SetSamplerState(stage, D3DSAMP_MAXANISOTROPY, g_ActiveConfig.iMaxAnisotropy);
|
||||||
|
|
||||||
D3DVIEWPORT9 vp;
|
D3DVIEWPORT9 vp;
|
||||||
vp.X = 0;
|
vp.X = 0;
|
||||||
vp.Y = 0;
|
vp.Y = 0;
|
||||||
@ -354,7 +355,7 @@ void dumpMatrix(D3DXMATRIX &mtx)
|
|||||||
for (int y = 0; y < 4; y++)
|
for (int y = 0; y < 4; y++)
|
||||||
{
|
{
|
||||||
char temp[256];
|
char temp[256];
|
||||||
sprintf(temp,"%4.4f %4.4f %4.4f %4.4f",mtx.m[y][0],mtx.m[y][1],mtx.m[y][2],mtx.m[y][3]);
|
sprintf(temp,"%4.4f %4.4f %4.4f %4.4f", mtx.m[y][0], mtx.m[y][1], mtx.m[y][2], mtx.m[y][3]);
|
||||||
g_VideoInitialize.pLog(temp, FALSE);
|
g_VideoInitialize.pLog(temp, FALSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -364,9 +365,9 @@ TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc)
|
|||||||
int Xstride = (s_Fulltarget_width - s_target_width) / 2;
|
int Xstride = (s_Fulltarget_width - s_target_width) / 2;
|
||||||
int Ystride = (s_Fulltarget_height - s_target_height) / 2;
|
int Ystride = (s_Fulltarget_height - s_target_height) / 2;
|
||||||
TargetRectangle result;
|
TargetRectangle result;
|
||||||
result.left = (int)(rc.left * xScale) + Xstride ;
|
result.left = (int)(rc.left * xScale) + Xstride;
|
||||||
result.top = (int)(rc.top * yScale) + Ystride;
|
result.top = (int)(rc.top * yScale) + Ystride;
|
||||||
result.right = (int)(rc.right * xScale) + Xstride ;
|
result.right = (int)(rc.right * xScale) + Xstride;
|
||||||
result.bottom = (int)(rc.bottom * yScale) + Ystride;
|
result.bottom = (int)(rc.bottom * yScale) + Ystride;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -433,14 +434,14 @@ static void EFBTextureToD3DBackBuffer(const EFBRectangle& sourceRc)
|
|||||||
int Width = dst_rect.right - dst_rect.left;
|
int Width = dst_rect.right - dst_rect.left;
|
||||||
int Height = dst_rect.bottom - dst_rect.top;
|
int Height = dst_rect.bottom - dst_rect.top;
|
||||||
|
|
||||||
if(X < 0) X = 0;
|
if (X < 0) X = 0;
|
||||||
if(Y < 0) Y = 0;
|
if (Y < 0) Y = 0;
|
||||||
if(X > s_backbuffer_width) X = s_backbuffer_width;
|
if (X > s_backbuffer_width) X = s_backbuffer_width;
|
||||||
if(Y > s_backbuffer_height) Y = s_backbuffer_height;
|
if (Y > s_backbuffer_height) Y = s_backbuffer_height;
|
||||||
if(Width < 0) Width = 0;
|
if (Width < 0) Width = 0;
|
||||||
if(Height < 0) Height = 0;
|
if (Height < 0) Height = 0;
|
||||||
if(Width > (s_backbuffer_width - X)) Width = s_backbuffer_width - X;
|
if (Width > (s_backbuffer_width - X)) Width = s_backbuffer_width - X;
|
||||||
if(Height > (s_backbuffer_height - Y)) Height = s_backbuffer_height - Y;
|
if (Height > (s_backbuffer_height - Y)) Height = s_backbuffer_height - Y;
|
||||||
vp.X = X;
|
vp.X = X;
|
||||||
vp.Y = Y;
|
vp.Y = Y;
|
||||||
vp.Width = Width;
|
vp.Width = Width;
|
||||||
@ -617,13 +618,13 @@ bool Renderer::SetScissorRect()
|
|||||||
if (rc.bottom < 0) rc.bottom = 0;
|
if (rc.bottom < 0) rc.bottom = 0;
|
||||||
if (rc.top > s_Fulltarget_height) rc.top = s_Fulltarget_height;
|
if (rc.top > s_Fulltarget_height) rc.top = s_Fulltarget_height;
|
||||||
if (rc.bottom > s_Fulltarget_height) rc.bottom = s_Fulltarget_height;
|
if (rc.bottom > s_Fulltarget_height) rc.bottom = s_Fulltarget_height;
|
||||||
if(rc.left > rc.right)
|
if (rc.left > rc.right)
|
||||||
{
|
{
|
||||||
int temp = rc.right;
|
int temp = rc.right;
|
||||||
rc.right = rc.left;
|
rc.right = rc.left;
|
||||||
rc.left = temp;
|
rc.left = temp;
|
||||||
}
|
}
|
||||||
if(rc.top > rc.bottom)
|
if (rc.top > rc.bottom)
|
||||||
{
|
{
|
||||||
int temp = rc.bottom;
|
int temp = rc.bottom;
|
||||||
rc.bottom = rc.top;
|
rc.bottom = rc.top;
|
||||||
@ -660,7 +661,7 @@ void Renderer::SetColorMask()
|
|||||||
|
|
||||||
u32 Renderer::AccessEFB(EFBAccessType type, int x, int y)
|
u32 Renderer::AccessEFB(EFBAccessType type, int x, int y)
|
||||||
{
|
{
|
||||||
if(!g_ActiveConfig.bEFBAccessEnable)
|
if (!g_ActiveConfig.bEFBAccessEnable)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
//Get the working buffer
|
//Get the working buffer
|
||||||
@ -678,13 +679,13 @@ u32 Renderer::AccessEFB(EFBAccessType type, int x, int y)
|
|||||||
D3DFORMAT ReadBufferFormat = (type == PEEK_Z || type == POKE_Z) ?
|
D3DFORMAT ReadBufferFormat = (type == PEEK_Z || type == POKE_Z) ?
|
||||||
FBManager::GetEFBDepthReadSurfaceFormat() : BufferFormat;
|
FBManager::GetEFBDepthReadSurfaceFormat() : BufferFormat;
|
||||||
|
|
||||||
if(BufferFormat == D3DFMT_D24X8)
|
if (BufferFormat == D3DFMT_D24X8)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
D3DLOCKED_RECT drect;
|
D3DLOCKED_RECT drect;
|
||||||
|
|
||||||
//Buffer not found alert
|
//Buffer not found alert
|
||||||
if(!pBuffer) {
|
if (!pBuffer) {
|
||||||
PanicAlert("No %s!", (type == PEEK_Z || type == POKE_Z) ? "Z-Buffer" : "Color EFB");
|
PanicAlert("No %s!", (type == PEEK_Z || type == POKE_Z) ? "Z-Buffer" : "Color EFB");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -706,7 +707,7 @@ u32 Renderer::AccessEFB(EFBAccessType type, int x, int y)
|
|||||||
RectToLock.left = targetPixelRc.left;
|
RectToLock.left = targetPixelRc.left;
|
||||||
RectToLock.right = targetPixelRc.right;
|
RectToLock.right = targetPixelRc.right;
|
||||||
RectToLock.top = targetPixelRc.top;
|
RectToLock.top = targetPixelRc.top;
|
||||||
if(type == PEEK_Z)
|
if (type == PEEK_Z)
|
||||||
{
|
{
|
||||||
RECT PixelRect;
|
RECT PixelRect;
|
||||||
PixelRect.bottom = 4;
|
PixelRect.bottom = 4;
|
||||||
@ -717,14 +718,14 @@ u32 Renderer::AccessEFB(EFBAccessType type, int x, int y)
|
|||||||
RectToLock.right+=1;
|
RectToLock.right+=1;
|
||||||
RectToLock.top-=1;
|
RectToLock.top-=1;
|
||||||
RectToLock.left-=2;
|
RectToLock.left-=2;
|
||||||
if((RectToLock.bottom - RectToLock.top) > 4)
|
if ((RectToLock.bottom - RectToLock.top) > 4)
|
||||||
RectToLock.bottom--;
|
RectToLock.bottom--;
|
||||||
if((RectToLock.right - RectToLock.left) > 4)
|
if ((RectToLock.right - RectToLock.left) > 4)
|
||||||
RectToLock.left++;
|
RectToLock.left++;
|
||||||
ResetAPIState(); // reset any game specific settings
|
ResetAPIState(); // reset any game specific settings
|
||||||
hr =D3D::dev->SetDepthStencilSurface(NULL);
|
hr =D3D::dev->SetDepthStencilSurface(NULL);
|
||||||
hr = D3D::dev->SetRenderTarget(0, RBuffer);
|
hr = D3D::dev->SetRenderTarget(0, RBuffer);
|
||||||
if(FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
PanicAlert("unable to set pixel render buffer");
|
PanicAlert("unable to set pixel render buffer");
|
||||||
return 0;
|
return 0;
|
||||||
@ -738,7 +739,7 @@ u32 Renderer::AccessEFB(EFBAccessType type, int x, int y)
|
|||||||
vp.MinZ = 0.0f;
|
vp.MinZ = 0.0f;
|
||||||
vp.MaxZ = 1.0f;
|
vp.MaxZ = 1.0f;
|
||||||
hr = D3D::dev->SetViewport(&vp);
|
hr = D3D::dev->SetViewport(&vp);
|
||||||
if(FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
PanicAlert("unable to set pixel viewport");
|
PanicAlert("unable to set pixel viewport");
|
||||||
return 0;
|
return 0;
|
||||||
@ -774,14 +775,14 @@ u32 Renderer::AccessEFB(EFBAccessType type, int x, int y)
|
|||||||
RectToLock.right = 1;
|
RectToLock.right = 1;
|
||||||
RectToLock.top = 0;
|
RectToLock.top = 0;
|
||||||
}
|
}
|
||||||
if(FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
PanicAlert("Unable to stretch data to buffer");
|
PanicAlert("Unable to stretch data to buffer");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
//retriebe the pixel data to the local memory buffer
|
//retriebe the pixel data to the local memory buffer
|
||||||
D3D::dev->GetRenderTargetData(RBuffer,pOffScreenBuffer);
|
D3D::dev->GetRenderTargetData(RBuffer,pOffScreenBuffer);
|
||||||
if(FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
PanicAlert("Unable to copy data to mem buffer");
|
PanicAlert("Unable to copy data to mem buffer");
|
||||||
return 0;
|
return 0;
|
||||||
@ -791,7 +792,7 @@ u32 Renderer::AccessEFB(EFBAccessType type, int x, int y)
|
|||||||
|
|
||||||
|
|
||||||
//the surface is good.. lock it
|
//the surface is good.. lock it
|
||||||
if((hr = pOffScreenBuffer->LockRect(&drect, &RectToLock, D3DLOCK_READONLY)) != D3D_OK)
|
if ((hr = pOffScreenBuffer->LockRect(&drect, &RectToLock, D3DLOCK_READONLY)) != D3D_OK)
|
||||||
{
|
{
|
||||||
PanicAlert("ERROR: %s", hr == D3DERR_WASSTILLDRAWING ? "Still drawing" :
|
PanicAlert("ERROR: %s", hr == D3DERR_WASSTILLDRAWING ? "Still drawing" :
|
||||||
hr == D3DERR_INVALIDCALL ? "Invalid call" : "w00t");
|
hr == D3DERR_INVALIDCALL ? "Invalid call" : "w00t");
|
||||||
@ -872,12 +873,12 @@ void UpdateViewport()
|
|||||||
int Y = (int)(ceil(xfregs.rawViewport[4] + xfregs.rawViewport[1] - (scissorYOff)) * MValueY) + Ystride;
|
int Y = (int)(ceil(xfregs.rawViewport[4] + xfregs.rawViewport[1] - (scissorYOff)) * MValueY) + Ystride;
|
||||||
int Width = (int)ceil((int)(2 * xfregs.rawViewport[0]) * MValueX);
|
int Width = (int)ceil((int)(2 * xfregs.rawViewport[0]) * MValueX);
|
||||||
int Height = (int)ceil((int)(-2 * xfregs.rawViewport[1]) * MValueY);
|
int Height = (int)ceil((int)(-2 * xfregs.rawViewport[1]) * MValueY);
|
||||||
if(Width < 0)
|
if (Width < 0)
|
||||||
{
|
{
|
||||||
X += Width;
|
X += Width;
|
||||||
Width*=-1;
|
Width*=-1;
|
||||||
}
|
}
|
||||||
if(Height < 0)
|
if (Height < 0)
|
||||||
{
|
{
|
||||||
Y += Height;
|
Y += Height;
|
||||||
Height *= -1;
|
Height *= -1;
|
||||||
@ -916,10 +917,10 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaE
|
|||||||
sirc.right = targetRc.right;
|
sirc.right = targetRc.right;
|
||||||
sirc.bottom = targetRc.bottom;
|
sirc.bottom = targetRc.bottom;
|
||||||
D3D::dev->SetScissorRect(&sirc);
|
D3D::dev->SetScissorRect(&sirc);
|
||||||
if(zEnable)
|
if (zEnable)
|
||||||
D3D::ChangeRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
|
D3D::ChangeRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
|
||||||
D3D::drawClearQuad(&sirc,color ,(z & 0xFFFFFF) / float(0xFFFFFF),PixelShaderCache::GetClearProgram(),VertexShaderCache::GetSimpleVertexShader());
|
D3D::drawClearQuad(&sirc,color ,(z & 0xFFFFFF) / float(0xFFFFFF),PixelShaderCache::GetClearProgram(),VertexShaderCache::GetSimpleVertexShader());
|
||||||
if(zEnable)
|
if (zEnable)
|
||||||
D3D::RefreshRenderState(D3DRS_ZFUNC);
|
D3D::RefreshRenderState(D3DRS_ZFUNC);
|
||||||
//D3D::dev->Clear(0, NULL, (colorEnable ? D3DCLEAR_TARGET : 0)| ( zEnable ? D3DCLEAR_ZBUFFER : 0), color | ((alphaEnable)?0:0xFF000000),(z & 0xFFFFFF) / float(0xFFFFFF), 0);
|
//D3D::dev->Clear(0, NULL, (colorEnable ? D3DCLEAR_TARGET : 0)| ( zEnable ? D3DCLEAR_ZBUFFER : 0), color | ((alphaEnable)?0:0xFF000000),(z & 0xFFFFFF) / float(0xFFFFFF), 0);
|
||||||
UpdateViewport();
|
UpdateViewport();
|
||||||
@ -933,7 +934,7 @@ void Renderer::SetBlendMode(bool forceUpdate)
|
|||||||
// 2 - reverse subtract enable (else add)
|
// 2 - reverse subtract enable (else add)
|
||||||
// 3-5 - srcRGB function
|
// 3-5 - srcRGB function
|
||||||
// 6-8 - dstRGB function
|
// 6-8 - dstRGB function
|
||||||
if(bpmem.blendmode.logicopenable && bpmem.blendmode.logicmode != 3)
|
if (bpmem.blendmode.logicopenable && bpmem.blendmode.logicmode != 3)
|
||||||
return;
|
return;
|
||||||
u32 newval = bpmem.blendmode.subtract << 2;
|
u32 newval = bpmem.blendmode.subtract << 2;
|
||||||
|
|
||||||
@ -978,8 +979,6 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight)
|
|||||||
// D3D frame is now over
|
// D3D frame is now over
|
||||||
// Clean out old stuff from caches.
|
// Clean out old stuff from caches.
|
||||||
frameCount++;
|
frameCount++;
|
||||||
PixelShaderCache::Cleanup();
|
|
||||||
VertexShaderCache::Cleanup();
|
|
||||||
TextureCache::Cleanup();
|
TextureCache::Cleanup();
|
||||||
|
|
||||||
// Make any new configuration settings active.
|
// Make any new configuration settings active.
|
||||||
|
@ -75,7 +75,7 @@ void CreateRgbToYuyvProgram()
|
|||||||
" float3 c01 = (c0 + c1) * 0.5f;\n"
|
" float3 c01 = (c0 + c1) * 0.5f;\n"
|
||||||
" ocol0 = float4(dot(c1,y_const),dot(c01,u_const),dot(c0,y_const),dot(c01, v_const)) + const3;\n"
|
" ocol0 = float4(dot(c1,y_const),dot(c01,u_const),dot(c0,y_const),dot(c01, v_const)) + const3;\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
s_rgbToYuyvProgram = D3D::CompilePixelShader(FProgram, (int)strlen(FProgram));
|
s_rgbToYuyvProgram = D3D::CompileAndCreatePixelShader(FProgram, (int)strlen(FProgram));
|
||||||
if (!s_rgbToYuyvProgram) {
|
if (!s_rgbToYuyvProgram) {
|
||||||
ERROR_LOG(VIDEO, "Failed to create RGB to YUYV fragment program");
|
ERROR_LOG(VIDEO, "Failed to create RGB to YUYV fragment program");
|
||||||
}
|
}
|
||||||
@ -102,7 +102,7 @@ void CreateYuyvToRgbProgram()
|
|||||||
" yComp + (2.018f * uComp),\n"
|
" yComp + (2.018f * uComp),\n"
|
||||||
" 1.0f);\n"
|
" 1.0f);\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
s_yuyvToRgbProgram = D3D::CompilePixelShader(FProgram, (int)strlen(FProgram));
|
s_yuyvToRgbProgram = D3D::CompileAndCreatePixelShader(FProgram, (int)strlen(FProgram));
|
||||||
if (!s_yuyvToRgbProgram) {
|
if (!s_yuyvToRgbProgram) {
|
||||||
ERROR_LOG(VIDEO, "Failed to create YUYV to RGB fragment program");
|
ERROR_LOG(VIDEO, "Failed to create YUYV to RGB fragment program");
|
||||||
}
|
}
|
||||||
@ -129,7 +129,7 @@ LPDIRECT3DPIXELSHADER9 GetOrCreateEncodingShader(u32 format)
|
|||||||
SaveData(szTemp, shader);
|
SaveData(szTemp, shader);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
s_encodingPrograms[format] = D3D::CompilePixelShader(shader, (int)strlen(shader));
|
s_encodingPrograms[format] = D3D::CompileAndCreatePixelShader(shader, (int)strlen(shader));
|
||||||
if (!s_encodingPrograms[format]) {
|
if (!s_encodingPrograms[format]) {
|
||||||
ERROR_LOG(VIDEO, "Failed to create encoding fragment program");
|
ERROR_LOG(VIDEO, "Failed to create encoding fragment program");
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,11 @@
|
|||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
#include "Common.h"
|
||||||
|
#include "FileUtil.h"
|
||||||
|
#include "LinearDiskCache.h"
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
#include "D3DBase.h"
|
#include "D3DBase.h"
|
||||||
#include "D3DShader.h"
|
#include "D3DShader.h"
|
||||||
#include "Statistics.h"
|
#include "Statistics.h"
|
||||||
@ -33,9 +38,10 @@
|
|||||||
VertexShaderCache::VSCache VertexShaderCache::vshaders;
|
VertexShaderCache::VSCache VertexShaderCache::vshaders;
|
||||||
const VertexShaderCache::VSCacheEntry *VertexShaderCache::last_entry;
|
const VertexShaderCache::VSCacheEntry *VertexShaderCache::last_entry;
|
||||||
|
|
||||||
static float GC_ALIGNED16(lastVSconstants[C_FOGPARAMS+8][4]);
|
static float GC_ALIGNED16(lastVSconstants[C_FOGPARAMS + 8][4]);
|
||||||
|
|
||||||
static LPDIRECT3DVERTEXSHADER9 SimpleVertexShader;
|
static LPDIRECT3DVERTEXSHADER9 SimpleVertexShader;
|
||||||
|
LinearDiskCache g_vs_disk_cache;
|
||||||
|
|
||||||
LPDIRECT3DVERTEXSHADER9 VertexShaderCache::GetSimpleVertexShader()
|
LPDIRECT3DVERTEXSHADER9 VertexShaderCache::GetSimpleVertexShader()
|
||||||
{
|
{
|
||||||
@ -126,9 +132,23 @@ void SetMultiVSConstant4fv(int const_number, int count, const float *f)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class VertexShaderCacheInserter : public LinearDiskCacheReader {
|
||||||
|
public:
|
||||||
|
void Read(const u8 *key, int key_size, const u8 *value, int value_size)
|
||||||
|
{
|
||||||
|
VERTEXSHADERUID uid;
|
||||||
|
if (key_size != sizeof(uid)) {
|
||||||
|
ERROR_LOG(VIDEO, "Wrong key size in vertex shader cache");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memcpy(&uid, key, key_size);
|
||||||
|
VertexShaderCache::InsertByteCode(uid, value, value_size, false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void VertexShaderCache::Init()
|
void VertexShaderCache::Init()
|
||||||
{
|
{
|
||||||
char vSimpleProg[1024];
|
char *vSimpleProg = new char[2048];
|
||||||
sprintf(vSimpleProg,"struct VSOUTPUT\n"
|
sprintf(vSimpleProg,"struct VSOUTPUT\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
"float4 vPosition : POSITION;\n"
|
"float4 vPosition : POSITION;\n"
|
||||||
@ -146,8 +166,17 @@ void VertexShaderCache::Init()
|
|||||||
"return OUT;\n"
|
"return OUT;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
|
|
||||||
SimpleVertexShader = D3D::CompileVertexShader(vSimpleProg, (int)strlen(vSimpleProg));
|
SimpleVertexShader = D3D::CompileAndCreateVertexShader(vSimpleProg, (int)strlen(vSimpleProg));
|
||||||
Clear();
|
Clear();
|
||||||
|
delete [] vSimpleProg;
|
||||||
|
|
||||||
|
if (!File::Exists(FULL_SHADERCACHE_DIR))
|
||||||
|
File::CreateDir(FULL_SHADERCACHE_DIR);
|
||||||
|
|
||||||
|
char cache_filename[MAX_PATH];
|
||||||
|
sprintf(cache_filename, "%s%s-vs.cache", FULL_SHADERCACHE_DIR, globals->unique_id);
|
||||||
|
VertexShaderCacheInserter inserter;
|
||||||
|
int read_items = g_vs_disk_cache.OpenAndRead(cache_filename, &inserter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VertexShaderCache::Clear()
|
void VertexShaderCache::Clear()
|
||||||
@ -164,9 +193,11 @@ void VertexShaderCache::Clear()
|
|||||||
|
|
||||||
void VertexShaderCache::Shutdown()
|
void VertexShaderCache::Shutdown()
|
||||||
{
|
{
|
||||||
if(SimpleVertexShader)
|
if (SimpleVertexShader)
|
||||||
SimpleVertexShader->Release();
|
SimpleVertexShader->Release();
|
||||||
Clear();
|
Clear();
|
||||||
|
g_vs_disk_cache.Sync();
|
||||||
|
g_vs_disk_cache.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VertexShaderCache::SetShader(u32 components)
|
bool VertexShaderCache::SetShader(u32 components)
|
||||||
@ -174,7 +205,7 @@ bool VertexShaderCache::SetShader(u32 components)
|
|||||||
DVSTARTPROFILE();
|
DVSTARTPROFILE();
|
||||||
|
|
||||||
VERTEXSHADERUID uid;
|
VERTEXSHADERUID uid;
|
||||||
GetVertexShaderId(uid, components);
|
GetVertexShaderId(&uid, components);
|
||||||
if (uid == last_vertex_shader_uid && vshaders[uid].frameCount == frameCount)
|
if (uid == last_vertex_shader_uid && vshaders[uid].frameCount == frameCount)
|
||||||
{
|
{
|
||||||
if (vshaders[uid].shader)
|
if (vshaders[uid].shader)
|
||||||
@ -202,8 +233,27 @@ bool VertexShaderCache::SetShader(u32 components)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *code = GenerateVertexShader(components, true);
|
const char *code = GenerateVertexShaderCode(components, true);
|
||||||
LPDIRECT3DVERTEXSHADER9 shader = D3D::CompileVertexShader(code, (int)strlen(code));
|
u8 *bytecode;
|
||||||
|
int bytecodelen;
|
||||||
|
if (!D3D::CompileVertexShader(code, (int)strlen(code), &bytecode, &bytecodelen))
|
||||||
|
{
|
||||||
|
if (g_ActiveConfig.bShowShaderErrors)
|
||||||
|
{
|
||||||
|
PanicAlert("Failed to compile Vertex Shader:\n\n%s", code);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
g_vs_disk_cache.Append((u8 *)&uid, sizeof(uid), bytecode, bytecodelen);
|
||||||
|
g_vs_disk_cache.Sync();
|
||||||
|
|
||||||
|
bool result = InsertByteCode(uid, bytecode, bytecodelen, true);
|
||||||
|
delete [] bytecode;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VertexShaderCache::InsertByteCode(const VERTEXSHADERUID &uid, const u8 *bytecode, int bytecodelen, bool activate) {
|
||||||
|
LPDIRECT3DVERTEXSHADER9 shader = D3D::CreateVertexShaderFromByteCode(bytecode, bytecodelen);
|
||||||
|
|
||||||
// Make an entry in the table
|
// Make an entry in the table
|
||||||
VSCacheEntry entry;
|
VSCacheEntry entry;
|
||||||
@ -214,41 +264,19 @@ bool VertexShaderCache::SetShader(u32 components)
|
|||||||
#endif
|
#endif
|
||||||
vshaders[uid] = entry;
|
vshaders[uid] = entry;
|
||||||
last_entry = &vshaders[uid];
|
last_entry = &vshaders[uid];
|
||||||
|
if (!shader)
|
||||||
|
return false;
|
||||||
|
|
||||||
INCSTAT(stats.numVertexShadersCreated);
|
INCSTAT(stats.numVertexShadersCreated);
|
||||||
SETSTAT(stats.numVertexShadersAlive, (int)vshaders.size());
|
SETSTAT(stats.numVertexShadersAlive, (int)vshaders.size());
|
||||||
if (shader)
|
if (activate)
|
||||||
{
|
{
|
||||||
D3D::SetVertexShader(shader);
|
D3D::SetVertexShader(shader);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_ActiveConfig.bShowShaderErrors)
|
|
||||||
{
|
|
||||||
PanicAlert("Failed to compile Vertex Shader:\n\n%s", code);
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VertexShaderCache::Cleanup()
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
for (VSCache::iterator iter = vshaders.begin(); iter != vshaders.end();)
|
|
||||||
{
|
|
||||||
VSCacheEntry &entry = iter->second;
|
|
||||||
if (entry.frameCount < frameCount - 1400)
|
|
||||||
{
|
|
||||||
entry.Destroy();
|
|
||||||
iter = vshaders.erase(iter);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
++iter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SETSTAT(stats.numVertexShadersAlive, (int)vshaders.size());*/
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||||
std::string VertexShaderCache::GetCurrentShaderCode()
|
std::string VertexShaderCache::GetCurrentShaderCode()
|
||||||
{
|
{
|
||||||
|
@ -53,10 +53,10 @@ private:
|
|||||||
public:
|
public:
|
||||||
static void Init();
|
static void Init();
|
||||||
static void Clear();
|
static void Clear();
|
||||||
static void Cleanup();
|
|
||||||
static void Shutdown();
|
static void Shutdown();
|
||||||
static bool SetShader(u32 components);
|
static bool SetShader(u32 components);
|
||||||
static LPDIRECT3DVERTEXSHADER9 GetSimpleVertexShader();
|
static LPDIRECT3DVERTEXSHADER9 GetSimpleVertexShader();
|
||||||
|
static bool InsertByteCode(const VERTEXSHADERUID &uid, const u8 *bytecode, int bytecodelen, bool activate);
|
||||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||||
static std::string GetCurrentShaderCode();
|
static std::string GetCurrentShaderCode();
|
||||||
#endif
|
#endif
|
||||||
|
@ -78,9 +78,9 @@ void PixelShaderCache::Init()
|
|||||||
{
|
{
|
||||||
GL_REPORT_ERRORD();
|
GL_REPORT_ERRORD();
|
||||||
|
|
||||||
for( int i=0;i<(C_COLORMATRIX+16)*4;i++)
|
for (int i = 0; i < (C_COLORMATRIX+16) * 4; i++)
|
||||||
lastPSconstants[i/4][i%4] = -100000000.0f;
|
lastPSconstants[i/4][i%4] = -100000000.0f;
|
||||||
memset(&last_pixel_shader_uid,0xFF,sizeof(last_pixel_shader_uid));
|
memset(&last_pixel_shader_uid, 0xFF, sizeof(last_pixel_shader_uid));
|
||||||
|
|
||||||
s_displayCompileAlert = true;
|
s_displayCompileAlert = true;
|
||||||
|
|
||||||
@ -172,8 +172,7 @@ FRAGMENTSHADER* PixelShaderCache::GetShader(bool dstAlphaEnable)
|
|||||||
{
|
{
|
||||||
DVSTARTPROFILE();
|
DVSTARTPROFILE();
|
||||||
PIXELSHADERUID uid;
|
PIXELSHADERUID uid;
|
||||||
u32 dstAlpha = dstAlphaEnable ? 1 : 0;
|
GetPixelShaderId(&uid, PixelShaderManager::GetTextureMask(), dstAlphaEnable ? 1 : 0);
|
||||||
GetPixelShaderId(uid, PixelShaderManager::GetTextureMask(), dstAlpha);
|
|
||||||
if (uid == last_pixel_shader_uid && pshaders[uid].frameCount == frameCount)
|
if (uid == last_pixel_shader_uid && pshaders[uid].frameCount == frameCount)
|
||||||
{
|
{
|
||||||
return pShaderLast;
|
return pShaderLast;
|
||||||
@ -194,14 +193,12 @@ FRAGMENTSHADER* PixelShaderCache::GetShader(bool dstAlphaEnable)
|
|||||||
return pShaderLast;
|
return pShaderLast;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//Make an entry in the table
|
//Make an entry in the table
|
||||||
PSCacheEntry& newentry = pshaders[uid];
|
PSCacheEntry& newentry = pshaders[uid];
|
||||||
newentry.frameCount = frameCount;
|
newentry.frameCount = frameCount;
|
||||||
pShaderLast = &newentry.shader;
|
pShaderLast = &newentry.shader;
|
||||||
|
const char *code = GeneratePixelShaderCode(PixelShaderManager::GetTextureMask(),
|
||||||
const char *code = GeneratePixelShader(PixelShaderManager::GetTextureMask(),
|
dstAlphaEnable);
|
||||||
dstAlphaEnable);
|
|
||||||
|
|
||||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||||
if (g_ActiveConfig.iLog & CONF_SAVESHADERS && code) {
|
if (g_ActiveConfig.iLog & CONF_SAVESHADERS && code) {
|
||||||
@ -218,34 +215,12 @@ FRAGMENTSHADER* PixelShaderCache::GetShader(bool dstAlphaEnable)
|
|||||||
ERROR_LOG(VIDEO, "failed to create pixel shader");
|
ERROR_LOG(VIDEO, "failed to create pixel shader");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
INCSTAT(stats.numPixelShadersCreated);
|
INCSTAT(stats.numPixelShadersCreated);
|
||||||
SETSTAT(stats.numPixelShadersAlive, pshaders.size());
|
SETSTAT(stats.numPixelShadersAlive, pshaders.size());
|
||||||
return pShaderLast;
|
return pShaderLast;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PixelShaderCache::ProgressiveCleanup()
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
PSCache::iterator iter = pshaders.begin();
|
|
||||||
while (iter != pshaders.end()) {
|
|
||||||
PSCacheEntry &entry = iter->second;
|
|
||||||
if (entry.frameCount < frameCount - 400) {
|
|
||||||
entry.Destroy();
|
|
||||||
#ifdef _WIN32
|
|
||||||
iter = pshaders.erase(iter);
|
|
||||||
#else
|
|
||||||
pshaders.erase(iter++); // (this is gcc standard!)
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
iter++;
|
|
||||||
}
|
|
||||||
SETSTAT(stats.numPixelShadersAlive, (int)pshaders.size());
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PixelShaderCache::CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrprogram)
|
bool PixelShaderCache::CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrprogram)
|
||||||
{
|
{
|
||||||
GLenum err = GL_REPORT_ERROR();
|
GLenum err = GL_REPORT_ERROR();
|
||||||
@ -268,7 +243,7 @@ bool PixelShaderCache::CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrpr
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle warnings
|
// handle warnings
|
||||||
if(cgGetError() != CG_NO_ERROR)
|
if (cgGetError() != CG_NO_ERROR)
|
||||||
{
|
{
|
||||||
WARN_LOG(VIDEO, "Warnings on compile ps %s:", cgGetLastListing(g_cgcontext));
|
WARN_LOG(VIDEO, "Warnings on compile ps %s:", cgGetLastListing(g_cgcontext));
|
||||||
WARN_LOG(VIDEO, pstrprogram);
|
WARN_LOG(VIDEO, pstrprogram);
|
||||||
|
@ -69,7 +69,6 @@ class PixelShaderCache
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
static void Init();
|
static void Init();
|
||||||
static void ProgressiveCleanup();
|
|
||||||
static void Shutdown();
|
static void Shutdown();
|
||||||
|
|
||||||
static FRAGMENTSHADER* GetShader(bool dstAlphaEnable);
|
static FRAGMENTSHADER* GetShader(bool dstAlphaEnable);
|
||||||
|
@ -1054,10 +1054,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight)
|
|||||||
|
|
||||||
GL_REPORT_ERRORD();
|
GL_REPORT_ERRORD();
|
||||||
|
|
||||||
// Clean out old stuff from caches
|
// Clean out old stuff from caches. It's not worth it to clean out the shader caches.
|
||||||
DLCache::ProgressiveCleanup();
|
DLCache::ProgressiveCleanup();
|
||||||
VertexShaderCache::ProgressiveCleanup();
|
|
||||||
PixelShaderCache::ProgressiveCleanup();
|
|
||||||
TextureMngr::ProgressiveCleanup();
|
TextureMngr::ProgressiveCleanup();
|
||||||
|
|
||||||
frameCount++;
|
frameCount++;
|
||||||
|
@ -47,7 +47,7 @@ static float GC_ALIGNED16(lastVSconstants[C_FOGPARAMS+8][4]);
|
|||||||
|
|
||||||
void SetVSConstant4f(int const_number, float f1, float f2, float f3, float f4)
|
void SetVSConstant4f(int const_number, float f1, float f2, float f3, float f4)
|
||||||
{
|
{
|
||||||
if( lastVSconstants[const_number][0] != f1 ||
|
if ( lastVSconstants[const_number][0] != f1 ||
|
||||||
lastVSconstants[const_number][1] != f2 ||
|
lastVSconstants[const_number][1] != f2 ||
|
||||||
lastVSconstants[const_number][2] != f3 ||
|
lastVSconstants[const_number][2] != f3 ||
|
||||||
lastVSconstants[const_number][3] != f4)
|
lastVSconstants[const_number][3] != f4)
|
||||||
@ -114,9 +114,9 @@ void SetMultiVSConstant3fv(int const_number, int count, const float *f)
|
|||||||
|
|
||||||
void VertexShaderCache::Init()
|
void VertexShaderCache::Init()
|
||||||
{
|
{
|
||||||
for( int i=0;i<(C_FOGPARAMS+8)*4;i++)
|
for (int i = 0; i < (C_FOGPARAMS + 8) * 4; i++)
|
||||||
lastVSconstants[i/4][i%4] = -100000000.0f;
|
lastVSconstants[i / 4][i % 4] = -100000000.0f;
|
||||||
memset(&last_vertex_shader_uid,0xFF,sizeof(last_vertex_shader_uid));
|
memset(&last_vertex_shader_uid, 0xFF, sizeof(last_vertex_shader_uid));
|
||||||
|
|
||||||
s_displayCompileAlert = true;
|
s_displayCompileAlert = true;
|
||||||
|
|
||||||
@ -138,7 +138,7 @@ VERTEXSHADER* VertexShaderCache::GetShader(u32 components)
|
|||||||
{
|
{
|
||||||
DVSTARTPROFILE();
|
DVSTARTPROFILE();
|
||||||
VERTEXSHADERUID uid;
|
VERTEXSHADERUID uid;
|
||||||
GetVertexShaderId(uid, components);
|
GetVertexShaderId(&uid, components);
|
||||||
|
|
||||||
if (uid == last_vertex_shader_uid && vshaders[uid].frameCount == frameCount)
|
if (uid == last_vertex_shader_uid && vshaders[uid].frameCount == frameCount)
|
||||||
{
|
{
|
||||||
@ -163,7 +163,7 @@ VERTEXSHADER* VertexShaderCache::GetShader(u32 components)
|
|||||||
VSCacheEntry& entry = vshaders[uid];
|
VSCacheEntry& entry = vshaders[uid];
|
||||||
entry.frameCount = frameCount;
|
entry.frameCount = frameCount;
|
||||||
pShaderLast = &entry.shader;
|
pShaderLast = &entry.shader;
|
||||||
const char *code = GenerateVertexShader(components, false);
|
const char *code = GenerateVertexShaderCode(components, false);
|
||||||
|
|
||||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||||
if (g_ActiveConfig.iLog & CONF_SAVESHADERS && code) {
|
if (g_ActiveConfig.iLog & CONF_SAVESHADERS && code) {
|
||||||
@ -185,29 +185,6 @@ VERTEXSHADER* VertexShaderCache::GetShader(u32 components)
|
|||||||
return pShaderLast;
|
return pShaderLast;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VertexShaderCache::ProgressiveCleanup()
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
VSCache::iterator iter = vshaders.begin();
|
|
||||||
while (iter != vshaders.end()) {
|
|
||||||
VSCacheEntry &entry = iter->second;
|
|
||||||
if (entry.frameCount < frameCount - 200) {
|
|
||||||
entry.Destroy();
|
|
||||||
#ifdef _WIN32
|
|
||||||
iter = vshaders.erase(iter);
|
|
||||||
#else
|
|
||||||
vshaders.erase(iter++);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
++iter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SETSTAT(stats.numVertexShadersAlive, vshaders.size());
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VertexShaderCache::CompileVertexShader(VERTEXSHADER& vs, const char* pstrprogram)
|
bool VertexShaderCache::CompileVertexShader(VERTEXSHADER& vs, const char* pstrprogram)
|
||||||
{
|
{
|
||||||
// Reset GL error before compiling shaders. Yeah, we need to investigate the causes of these.
|
// Reset GL error before compiling shaders. Yeah, we need to investigate the causes of these.
|
||||||
@ -232,7 +209,7 @@ bool VertexShaderCache::CompileVertexShader(VERTEXSHADER& vs, const char* pstrpr
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cgGetError() != CG_NO_ERROR)
|
if (cgGetError() != CG_NO_ERROR)
|
||||||
{
|
{
|
||||||
WARN_LOG(VIDEO, "Failed to load vs %s:", cgGetLastListing(g_cgcontext));
|
WARN_LOG(VIDEO, "Failed to load vs %s:", cgGetLastListing(g_cgcontext));
|
||||||
WARN_LOG(VIDEO, pstrprogram);
|
WARN_LOG(VIDEO, pstrprogram);
|
||||||
@ -249,8 +226,7 @@ bool VertexShaderCache::CompileVertexShader(VERTEXSHADER& vs, const char* pstrpr
|
|||||||
}
|
}
|
||||||
glGenProgramsARB(1, &vs.glprogid);
|
glGenProgramsARB(1, &vs.glprogid);
|
||||||
EnableShader(vs.glprogid);
|
EnableShader(vs.glprogid);
|
||||||
//glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vs.glprogid);
|
|
||||||
//CurrentShader = vs.glprogid;
|
|
||||||
glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pcompiledprog), pcompiledprog);
|
glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pcompiledprog), pcompiledprog);
|
||||||
err = GL_REPORT_ERROR();
|
err = GL_REPORT_ERROR();
|
||||||
if (err != GL_NO_ERROR) {
|
if (err != GL_NO_ERROR) {
|
||||||
@ -263,13 +239,13 @@ bool VertexShaderCache::CompileVertexShader(VERTEXSHADER& vs, const char* pstrpr
|
|||||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||||
vs.strprog = pstrprogram;
|
vs.strprog = pstrprogram;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VertexShaderCache::DisableShader()
|
void VertexShaderCache::DisableShader()
|
||||||
{
|
{
|
||||||
//if(ShaderEnabled)
|
//if (ShaderEnabled)
|
||||||
{
|
{
|
||||||
CurrentShader = 0;
|
CurrentShader = 0;
|
||||||
glBindProgramARB(GL_VERTEX_PROGRAM_ARB, CurrentShader);
|
glBindProgramARB(GL_VERTEX_PROGRAM_ARB, CurrentShader);
|
||||||
@ -278,9 +254,11 @@ void VertexShaderCache::DisableShader()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Why are these if statements commented out?
|
||||||
|
|
||||||
void VertexShaderCache::SetCurrentShader(GLuint Shader)
|
void VertexShaderCache::SetCurrentShader(GLuint Shader)
|
||||||
{
|
{
|
||||||
//if(ShaderEnabled && CurrentShader != Shader)
|
//if (ShaderEnabled && CurrentShader != Shader)
|
||||||
{
|
{
|
||||||
CurrentShader = Shader;
|
CurrentShader = Shader;
|
||||||
glBindProgramARB(GL_VERTEX_PROGRAM_ARB, CurrentShader);
|
glBindProgramARB(GL_VERTEX_PROGRAM_ARB, CurrentShader);
|
||||||
@ -289,13 +267,13 @@ void VertexShaderCache::SetCurrentShader(GLuint Shader)
|
|||||||
|
|
||||||
void VertexShaderCache::EnableShader(GLuint Shader)
|
void VertexShaderCache::EnableShader(GLuint Shader)
|
||||||
{
|
{
|
||||||
//if(!ShaderEnabled)
|
//if (!ShaderEnabled)
|
||||||
{
|
{
|
||||||
glEnable(GL_VERTEX_PROGRAM_ARB);
|
glEnable(GL_VERTEX_PROGRAM_ARB);
|
||||||
ShaderEnabled= true;
|
ShaderEnabled= true;
|
||||||
CurrentShader = 0;
|
CurrentShader = 0;
|
||||||
}
|
}
|
||||||
//if(CurrentShader != Shader)
|
//if (CurrentShader != Shader)
|
||||||
{
|
{
|
||||||
CurrentShader = Shader;
|
CurrentShader = Shader;
|
||||||
glBindProgramARB(GL_VERTEX_PROGRAM_ARB, CurrentShader);
|
glBindProgramARB(GL_VERTEX_PROGRAM_ARB, CurrentShader);
|
||||||
|
@ -59,7 +59,6 @@ class VertexShaderCache
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
static void Init();
|
static void Init();
|
||||||
static void ProgressiveCleanup();
|
|
||||||
static void Shutdown();
|
static void Shutdown();
|
||||||
|
|
||||||
static VERTEXSHADER* GetShader(u32 components);
|
static VERTEXSHADER* GetShader(u32 components);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user