mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-23 13:30:02 +00:00
GPU: Verify generated shader buffer length.
Hardware tessellation + uberlighting + clamp was exceeding the buffer, causing memory corruption. Let's try to catch it, but also increase buffers to be safe.
This commit is contained in:
parent
1469a32a9d
commit
aee2ad46a2
@ -178,9 +178,10 @@ void Draw2D::Ensure2DResources() {
|
||||
const ShaderLanguageDesc &shaderLanguageDesc = draw_->GetShaderLanguageDesc();
|
||||
|
||||
if (!draw2DVs_) {
|
||||
char *vsCode = new char[4000];
|
||||
char *vsCode = new char[8192];
|
||||
ShaderWriter writer(vsCode, shaderLanguageDesc, ShaderStage::Vertex);
|
||||
GenerateDraw2DVS(writer);
|
||||
_assert_msg_(strlen(vsCode) < 8192, "Draw2D VS length error: %d", (int)strlen(vsCode));
|
||||
draw2DVs_ = draw_->CreateShaderModule(ShaderStage::Vertex, shaderLanguageDesc.shaderLanguage, (const uint8_t *)vsCode, strlen(vsCode), "draw2d_vs");
|
||||
_assert_(draw2DVs_);
|
||||
delete[] vsCode;
|
||||
@ -215,9 +216,10 @@ Draw2DPipeline *Draw2D::Create2DPipeline(std::function<Draw2DPipelineInfo (Shade
|
||||
using namespace Draw;
|
||||
const ShaderLanguageDesc &shaderLanguageDesc = draw_->GetShaderLanguageDesc();
|
||||
|
||||
char *fsCode = new char[4000];
|
||||
char *fsCode = new char[8192];
|
||||
ShaderWriter writer(fsCode, shaderLanguageDesc, ShaderStage::Fragment);
|
||||
Draw2DPipelineInfo info = generate(writer);
|
||||
_assert_msg_(strlen(fsCode) < 8192, "Draw2D FS length error: %d", (int)strlen(fsCode));
|
||||
|
||||
ShaderModule *fs = draw_->CreateShaderModule(ShaderStage::Fragment, shaderLanguageDesc.shaderLanguage, (const uint8_t *)fsCode, strlen(fsCode), info.tag);
|
||||
|
||||
|
@ -199,11 +199,14 @@ bool FramebufferManagerCommon::PerformStencilUpload(u32 addr, int size, StencilU
|
||||
if (!stencilUploadPipeline_) {
|
||||
const ShaderLanguageDesc &shaderLanguageDesc = draw_->GetShaderLanguageDesc();
|
||||
|
||||
char *fsCode = new char[4000];
|
||||
char *vsCode = new char[4000];
|
||||
char *fsCode = new char[8192];
|
||||
char *vsCode = new char[8192];
|
||||
GenerateStencilFs(fsCode, shaderLanguageDesc, draw_->GetBugs());
|
||||
GenerateStencilVs(vsCode, shaderLanguageDesc);
|
||||
|
||||
_assert_msg_(strlen(fsCode) < 8192, "StenFS length error: %d", (int)strlen(fsCode));
|
||||
_assert_msg_(strlen(vsCode) < 8192, "StenVS length error: %d", (int)strlen(vsCode));
|
||||
|
||||
ShaderModule *stencilUploadFs = draw_->CreateShaderModule(ShaderStage::Fragment, shaderLanguageDesc.shaderLanguage, (const uint8_t *)fsCode, strlen(fsCode), "stencil_fs");
|
||||
ShaderModule *stencilUploadVs = draw_->CreateShaderModule(ShaderStage::Vertex, shaderLanguageDesc.shaderLanguage, (const uint8_t *)vsCode, strlen(vsCode), "stencil_vs");
|
||||
|
||||
|
@ -209,7 +209,6 @@ Draw2DPipeline *TextureShaderCache::GetDepalettizeShader(uint32_t clutMode, GETe
|
||||
config.smoothedDepal = smoothedDepal;
|
||||
config.depthUpperBits = depthUpperBits;
|
||||
|
||||
char *buffer = new char[4096];
|
||||
Draw2DPipeline *ts = draw2D_->Create2DPipeline([=](ShaderWriter &writer) -> Draw2DPipelineInfo {
|
||||
GenerateDepalFs(writer, config);
|
||||
return Draw2DPipelineInfo{
|
||||
@ -219,7 +218,6 @@ Draw2DPipeline *TextureShaderCache::GetDepalettizeShader(uint32_t clutMode, GETe
|
||||
samplers
|
||||
};
|
||||
});
|
||||
delete[] buffer;
|
||||
|
||||
depalCache_[id] = ts;
|
||||
|
||||
|
@ -88,9 +88,11 @@ std::string D3D11VertexShader::GetShaderString(DebugShaderStringType type) const
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr size_t CODE_BUFFER_SIZE = 32768;
|
||||
|
||||
ShaderManagerD3D11::ShaderManagerD3D11(Draw::DrawContext *draw, ID3D11Device *device, ID3D11DeviceContext *context, D3D_FEATURE_LEVEL featureLevel)
|
||||
: ShaderManagerCommon(draw), device_(device), context_(context), featureLevel_(featureLevel) {
|
||||
codeBuffer_ = new char[16384];
|
||||
codeBuffer_ = new char[CODE_BUFFER_SIZE];
|
||||
memset(&ub_base, 0, sizeof(ub_base));
|
||||
memset(&ub_lights, 0, sizeof(ub_lights));
|
||||
memset(&ub_bones, 0, sizeof(ub_bones));
|
||||
@ -211,6 +213,7 @@ void ShaderManagerD3D11::GetShaders(int prim, u32 vertType, D3D11VertexShader **
|
||||
uint32_t attrMask;
|
||||
uint64_t uniformMask;
|
||||
GenerateVertexShader(VSID, codeBuffer_, draw_->GetShaderLanguageDesc(), draw_->GetBugs(), &attrMask, &uniformMask, &genErrorString);
|
||||
_assert_msg_(strlen(codeBuffer_) < CODE_BUFFER_SIZE, "VS length error: %d", (int)strlen(codeBuffer_));
|
||||
vs = new D3D11VertexShader(device_, featureLevel_, VSID, codeBuffer_, vertType, useHWTransform);
|
||||
vsCache_[VSID] = vs;
|
||||
} else {
|
||||
@ -225,6 +228,7 @@ void ShaderManagerD3D11::GetShaders(int prim, u32 vertType, D3D11VertexShader **
|
||||
std::string genErrorString;
|
||||
uint64_t uniformMask;
|
||||
GenerateFragmentShader(FSID, codeBuffer_, draw_->GetShaderLanguageDesc(), draw_->GetBugs(), &uniformMask, nullptr, &genErrorString);
|
||||
_assert_msg_(strlen(codeBuffer_) < CODE_BUFFER_SIZE, "FS length error: %d", (int)strlen(codeBuffer_));
|
||||
fs = new D3D11FragmentShader(device_, featureLevel_, FSID, codeBuffer_, useHWTransform);
|
||||
fsCache_[FSID] = fs;
|
||||
} else {
|
||||
|
@ -662,10 +662,12 @@ void LinkedShader::UpdateUniforms(u32 vertType, const ShaderID &vsid, bool useBu
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr size_t CODE_BUFFER_SIZE = 32768;
|
||||
|
||||
ShaderManagerGLES::ShaderManagerGLES(Draw::DrawContext *draw)
|
||||
: ShaderManagerCommon(draw), fsCache_(16), vsCache_(16) {
|
||||
render_ = (GLRenderManager *)draw->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
|
||||
codeBuffer_ = new char[16384];
|
||||
codeBuffer_ = new char[CODE_BUFFER_SIZE];
|
||||
lastFSID_.set_invalid();
|
||||
lastVSID_.set_invalid();
|
||||
}
|
||||
@ -728,6 +730,7 @@ Shader *ShaderManagerGLES::CompileFragmentShader(FShaderID FSID) {
|
||||
ERROR_LOG(G3D, "Shader gen error: %s", errorString.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
_assert_msg_(strlen(codeBuffer_) < CODE_BUFFER_SIZE, "FS length error: %d", (int)strlen(codeBuffer_));
|
||||
std::string desc = FragmentShaderDesc(FSID);
|
||||
ShaderDescGLES params{ GL_FRAGMENT_SHADER, 0, uniformMask };
|
||||
return new Shader(render_, codeBuffer_, desc, params);
|
||||
@ -742,6 +745,7 @@ Shader *ShaderManagerGLES::CompileVertexShader(VShaderID VSID) {
|
||||
ERROR_LOG(G3D, "Shader gen error: %s", errorString.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
_assert_msg_(strlen(codeBuffer_) < CODE_BUFFER_SIZE, "VS length error: %d", (int)strlen(codeBuffer_));
|
||||
std::string desc = VertexShaderDesc(VSID);
|
||||
ShaderDescGLES params{ GL_VERTEX_SHADER, attrMask, uniformMask };
|
||||
params.useHWTransform = useHWTransform;
|
||||
|
@ -194,9 +194,11 @@ std::string VulkanGeometryShader::GetShaderString(DebugShaderStringType type) co
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr size_t CODE_BUFFER_SIZE = 32768;
|
||||
|
||||
ShaderManagerVulkan::ShaderManagerVulkan(Draw::DrawContext *draw)
|
||||
: ShaderManagerCommon(draw), compat_(GLSL_VULKAN), fsCache_(16), vsCache_(16), gsCache_(16) {
|
||||
codeBuffer_ = new char[16384];
|
||||
codeBuffer_ = new char[CODE_BUFFER_SIZE];
|
||||
VulkanContext *vulkan = (VulkanContext *)draw->GetNativeObject(Draw::NativeObject::CONTEXT);
|
||||
uboAlignment_ = vulkan->GetPhysicalDeviceProperties().properties.limits.minUniformBufferOffsetAlignment;
|
||||
memset(&ub_base, 0, sizeof(ub_base));
|
||||
@ -330,6 +332,7 @@ void ShaderManagerVulkan::GetShaders(int prim, u32 vertType, VulkanVertexShader
|
||||
uint32_t attributeMask = 0; // Not used
|
||||
bool success = GenerateVertexShader(VSID, codeBuffer_, compat_, draw_->GetBugs(), &attributeMask, &uniformMask, &genErrorString);
|
||||
_assert_msg_(success, "VS gen error: %s", genErrorString.c_str());
|
||||
_assert_msg_(strlen(codeBuffer_) < CODE_BUFFER_SIZE, "VS length error: %d", (int)strlen(codeBuffer_));
|
||||
vs = new VulkanVertexShader(vulkan, VSID, codeBuffer_, useHWTransform);
|
||||
vsCache_.Insert(VSID, vs);
|
||||
}
|
||||
@ -342,6 +345,7 @@ void ShaderManagerVulkan::GetShaders(int prim, u32 vertType, VulkanVertexShader
|
||||
FragmentShaderFlags flags;
|
||||
bool success = GenerateFragmentShader(FSID, codeBuffer_, compat_, draw_->GetBugs(), &uniformMask, &flags, &genErrorString);
|
||||
_assert_msg_(success, "FS gen error: %s", genErrorString.c_str());
|
||||
_assert_msg_(strlen(codeBuffer_) < CODE_BUFFER_SIZE, "FS length error: %d", (int)strlen(codeBuffer_));
|
||||
fs = new VulkanFragmentShader(vulkan, FSID, flags, codeBuffer_);
|
||||
fsCache_.Insert(FSID, fs);
|
||||
}
|
||||
@ -354,6 +358,7 @@ void ShaderManagerVulkan::GetShaders(int prim, u32 vertType, VulkanVertexShader
|
||||
std::string genErrorString;
|
||||
bool success = GenerateGeometryShader(GSID, codeBuffer_, compat_, draw_->GetBugs(), &genErrorString);
|
||||
_assert_msg_(success, "GS gen error: %s", genErrorString.c_str());
|
||||
_assert_msg_(strlen(codeBuffer_) < CODE_BUFFER_SIZE, "GS length error: %d", (int)strlen(codeBuffer_));
|
||||
gs = new VulkanGeometryShader(vulkan, GSID, codeBuffer_);
|
||||
gsCache_.Insert(GSID, gs);
|
||||
}
|
||||
@ -512,6 +517,7 @@ bool ShaderManagerVulkan::LoadCache(FILE *f) {
|
||||
if (!GenerateVertexShader(id, codeBuffer_, compat_, draw_->GetBugs(), &attributeMask, &uniformMask, &genErrorString)) {
|
||||
return false;
|
||||
}
|
||||
_assert_msg_(strlen(codeBuffer_) < CODE_BUFFER_SIZE, "VS length error: %d", (int)strlen(codeBuffer_));
|
||||
VulkanVertexShader *vs = new VulkanVertexShader(vulkan, id, codeBuffer_, useHWTransform);
|
||||
vsCache_.Insert(id, vs);
|
||||
}
|
||||
@ -529,6 +535,7 @@ bool ShaderManagerVulkan::LoadCache(FILE *f) {
|
||||
if (!GenerateFragmentShader(id, codeBuffer_, compat_, draw_->GetBugs(), &uniformMask, &flags, &genErrorString)) {
|
||||
return false;
|
||||
}
|
||||
_assert_msg_(strlen(codeBuffer_) < CODE_BUFFER_SIZE, "FS length error: %d", (int)strlen(codeBuffer_));
|
||||
VulkanFragmentShader *fs = new VulkanFragmentShader(vulkan, id, flags, codeBuffer_);
|
||||
fsCache_.Insert(id, fs);
|
||||
}
|
||||
@ -543,6 +550,7 @@ bool ShaderManagerVulkan::LoadCache(FILE *f) {
|
||||
if (!GenerateGeometryShader(id, codeBuffer_, compat_, draw_->GetBugs(), &genErrorString)) {
|
||||
return false;
|
||||
}
|
||||
_assert_msg_(strlen(codeBuffer_) < CODE_BUFFER_SIZE, "GS length error: %d", (int)strlen(codeBuffer_));
|
||||
VulkanGeometryShader *gs = new VulkanGeometryShader(vulkan, id, codeBuffer_);
|
||||
gsCache_.Insert(id, gs);
|
||||
}
|
||||
|
@ -25,6 +25,8 @@
|
||||
#include "GPU/D3D9/D3D9ShaderCompiler.h"
|
||||
#endif
|
||||
|
||||
static constexpr size_t CODE_BUFFER_SIZE = 32768;
|
||||
|
||||
bool GenerateFShader(FShaderID id, char *buffer, ShaderLanguage lang, Draw::Bugs bugs, std::string *errorString) {
|
||||
uint64_t uniformMask;
|
||||
switch (lang) {
|
||||
@ -243,10 +245,13 @@ bool TestReinterpretShaders() {
|
||||
continue; // useless shader!
|
||||
ShaderWriter writer(buffer, desc, ShaderStage::Fragment, nullptr, 0);
|
||||
GenerateReinterpretFragmentShader(writer, fmts[i], fmts[j]);
|
||||
if (!TestCompileShader(buffer, languages[k], ShaderStage::Fragment, &errorMessage)) {
|
||||
printf("Error compiling fragment shader %d:\n\n%s\n\n%s\n", (int)j, LineNumberString(buffer).c_str(), errorMessage.c_str());
|
||||
if (strlen(buffer) >= 8192) {
|
||||
printf("Reinterpret fragment shader %d exceeded buffer:\n\n%s\n", (int)j, LineNumberString(buffer).c_str());
|
||||
failed = true;
|
||||
}
|
||||
if (!TestCompileShader(buffer, languages[k], ShaderStage::Fragment, &errorMessage)) {
|
||||
printf("Error compiling reinterpret fragment shader %d:\n\n%s\n\n%s\n", (int)j, LineNumberString(buffer).c_str(), errorMessage.c_str());
|
||||
failed = true;
|
||||
return false;
|
||||
} else {
|
||||
printf("===\n%s\n===\n", buffer);
|
||||
}
|
||||
@ -282,19 +287,25 @@ bool TestStencilShaders() {
|
||||
|
||||
// Generate all despite failures - it's only 6.
|
||||
GenerateStencilFs(buffer, desc, bugs);
|
||||
if (strlen(buffer) >= 8192) {
|
||||
printf("Stencil fragment shader exceeded buffer:\n\n%s\n", LineNumberString(buffer).c_str());
|
||||
failed = true;
|
||||
}
|
||||
if (!TestCompileShader(buffer, languages[k], ShaderStage::Fragment, &errorMessage)) {
|
||||
printf("Error compiling stencil shader:\n\n%s\n\n%s\n", LineNumberString(buffer).c_str(), errorMessage.c_str());
|
||||
failed = true;
|
||||
return false;
|
||||
} else {
|
||||
printf("===\n%s\n===\n", buffer);
|
||||
}
|
||||
|
||||
GenerateStencilVs(buffer, desc);
|
||||
if (strlen(buffer) >= 8192) {
|
||||
printf("Stencil vertex shader exceeded buffer:\n\n%s\n", LineNumberString(buffer).c_str());
|
||||
failed = true;
|
||||
}
|
||||
if (!TestCompileShader(buffer, languages[k], ShaderStage::Vertex, &errorMessage)) {
|
||||
printf("Error compiling stencil shader:\n\n%s\n\n%s\n", LineNumberString(buffer).c_str(), errorMessage.c_str());
|
||||
failed = true;
|
||||
return false;
|
||||
} else {
|
||||
printf("===\n%s\n===\n", buffer);
|
||||
}
|
||||
@ -319,8 +330,6 @@ bool TestDepalShaders() {
|
||||
|
||||
char *buffer = new char[65536];
|
||||
|
||||
bool failed = false;
|
||||
|
||||
for (int k = 0; k < ARRAY_SIZE(languages); k++) {
|
||||
printf("=== %s ===\n\n", ShaderLanguageToString(languages[k]));
|
||||
|
||||
@ -340,9 +349,14 @@ bool TestDepalShaders() {
|
||||
|
||||
ShaderWriter writer(buffer, desc, ShaderStage::Fragment);
|
||||
GenerateDepalFs(writer, config);
|
||||
if (strlen(buffer) >= 8192) {
|
||||
printf("Depal shader exceeded buffer:\n\n%s\n", LineNumberString(buffer).c_str());
|
||||
delete[] buffer;
|
||||
return false;
|
||||
}
|
||||
if (!TestCompileShader(buffer, languages[k], ShaderStage::Fragment, &errorMessage)) {
|
||||
printf("Error compiling depal shader:\n\n%s\n\n%s\n", LineNumberString(buffer).c_str(), errorMessage.c_str());
|
||||
failed = true;
|
||||
delete[] buffer;
|
||||
return false;
|
||||
} else {
|
||||
printf("===\n%s\n===\n", buffer);
|
||||
@ -350,7 +364,7 @@ bool TestDepalShaders() {
|
||||
}
|
||||
|
||||
delete[] buffer;
|
||||
return !failed;
|
||||
return true;
|
||||
}
|
||||
|
||||
const ShaderLanguage languages[] = {
|
||||
@ -410,6 +424,16 @@ bool TestVertexShaders() {
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < numLanguages; j++) {
|
||||
if (strlen(buffer[j]) >= CODE_BUFFER_SIZE) {
|
||||
printf("Vertex shader exceeded buffer:\n\n%s\n", LineNumberString(buffer[j]).c_str());
|
||||
for (int i = 0; i < numLanguages; i++) {
|
||||
delete[] buffer[i];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Now that we have the strings ready for easy comparison (buffer,4 in the watch window),
|
||||
// let's try to compile them.
|
||||
for (int j = 0; j < numLanguages; j++) {
|
||||
@ -417,6 +441,9 @@ bool TestVertexShaders() {
|
||||
std::string errorMessage;
|
||||
if (!TestCompileShader(buffer[j], languages[j], ShaderStage::Vertex, &errorMessage)) {
|
||||
printf("Error compiling vertex shader %d:\n\n%s\n\n%s\n", (int)j, LineNumberString(buffer[j]).c_str(), errorMessage.c_str());
|
||||
for (int i = 0; i < numLanguages; i++) {
|
||||
delete[] buffer[i];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
successes++;
|
||||
@ -471,6 +498,16 @@ bool TestFragmentShaders() {
|
||||
// We ignore the contents of the error string here, not even gonna try to compile if it errors.
|
||||
}
|
||||
|
||||
for (int j = 0; j < numLanguages; j++) {
|
||||
if (strlen(buffer[j]) >= CODE_BUFFER_SIZE) {
|
||||
printf("Fragment shader exceeded buffer:\n\n%s\n", LineNumberString(buffer[j]).c_str());
|
||||
for (int i = 0; i < numLanguages; i++) {
|
||||
delete[] buffer[i];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Now that we have the strings ready for easy comparison (buffer,4 in the watch window),
|
||||
// let's try to compile them.
|
||||
for (int j = 0; j < numLanguages; j++) {
|
||||
@ -478,6 +515,9 @@ bool TestFragmentShaders() {
|
||||
std::string errorMessage;
|
||||
if (!TestCompileShader(buffer[j], languages[j], ShaderStage::Fragment, &errorMessage)) {
|
||||
printf("Error compiling fragment shader:\n\n%s\n\n%s\n", LineNumberString(buffer[j]).c_str(), errorMessage.c_str());
|
||||
for (int i = 0; i < numLanguages; i++) {
|
||||
delete[] buffer[i];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
successes++;
|
||||
@ -527,6 +567,16 @@ bool TestGeometryShaders() {
|
||||
// We ignore the contents of the error string here, not even gonna try to compile if it errors.
|
||||
}
|
||||
|
||||
for (int j = 0; j < numLanguages; j++) {
|
||||
if (strlen(buffer[j]) >= CODE_BUFFER_SIZE) {
|
||||
printf("Geoemtry shader exceeded buffer:\n\n%s\n", LineNumberString(buffer[j]).c_str());
|
||||
for (int i = 0; i < numLanguages; i++) {
|
||||
delete[] buffer[i];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Now that we have the strings ready for easy comparison (buffer,4 in the watch window),
|
||||
// let's try to compile them.
|
||||
for (int j = 0; j < numLanguages; j++) {
|
||||
@ -534,6 +584,9 @@ bool TestGeometryShaders() {
|
||||
std::string errorMessage;
|
||||
if (!TestCompileShader(buffer[j], languages[j], ShaderStage::Geometry, &errorMessage)) {
|
||||
printf("Error compiling geometry shader:\n\n%s\n\n%s\n", LineNumberString(buffer[j]).c_str(), errorMessage.c_str());
|
||||
for (int i = 0; i < numLanguages; i++) {
|
||||
delete[] buffer[i];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
successes++;
|
||||
|
Loading…
Reference in New Issue
Block a user