gpt4 book ai didi

c - glTexImage2d 和 GL_R8UI 在某些 GPU 上失败

转载 作者:行者123 更新时间:2023-11-30 16:38:44 24 4
gpt4 key购买 nike

我尝试使用 GL_R8UI 将未签名的非标准化数据传递给着色器,但发现至少在一个 GPU 上它不起作用。

即:这有效:

glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, 32, 32, 0, GL_RED, GL_UNSIGNED_BYTE, pData);

但这不是:

glTexImage2D(GL_TEXTURE_2D, 0, GL_R8UI, 32, 32, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, pData);

我还更改了着色器以使用sampler2D与usampler2D,并适当更新着色器中的数学,但发现它在AMD/Radeon卡上有效,但在Intel 和NVidia 卡上失败 - usampler2D似乎总是返回零。

我已经整理了一个最小的sample program here#define NORMALIZED 在两种方法之间切换。

所以...我的主要问题是:这只是一个驱动程序问题还是我的代码中存在其他错误导致了此问题?

<小时/>

换个方式问这个问题...从 GL_R8 标准化数据切换到 GL_R8UI 非标准化数据还需要更改什么,除了:

  1. 更改对 glTextImage2D 的调用
  2. 在着色器中从sampler2D更改为usampler2D
  3. 更改着色器以使用 uint 而不是 float
  4. 更改着色器中的数学运算以处理标准化数据与非标准化数据。
<小时/>

我现在已经向英特尔记录了错误报告:https://software.intel.com/en-us/forums/graphics-driver-bug-reporting/topic/748843

<小时/>

因为有人要求这里是完整的示例程序源:

// ShaderTest.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "ShaderTest.h"

#include <stdlib.h>
#include <stdint.h>
#include <GL/gl3w.h>

#pragma comment(lib, "opengl32.lib")

#define NORMALIZED

const char* pszVertexShader = R"***(

#version 150

uniform mat4 transform;

attribute vec3 position;

varying vec2 vPosition;

void main()
{
gl_Position = transform * vec4(position,1.);
vPosition = position.xy;
}

)***";


#ifdef NORMALIZED

const char* pszFragmentShader = R"***(

#version 150

uniform sampler2D TextureData;

varying vec2 vPosition;

void main()
{
float red = texelFetch(TextureData, ivec2(0, 0), 0).r;
gl_FragColor = vec4(red , 0, 0, 1);
}

)***";

#else

const char* pszFragmentShader = R"***(

#version 150

uniform usampler2D TextureData;

varying vec2 vPosition;

void main()
{
// Original post had this wrong
// float red = float(texelFetch(TextureData, ivec2(0, 0), 0)).r/255.0;

// Fixed version - still fails on Intel GPUs though
float red = float(texelFetch(TextureData, ivec2(0, 0), 0).r)/255.0;

gl_FragColor = vec4(red, 0, 0, 1);
}

)***";

#endif

int CompileShader(GLenum type, const char* pszSource)
{
int iShader = glCreateShader(type);
glShaderSource(iShader, 1, &pszSource, NULL);
glCompileShader(iShader);

// Dump log
int length;
glGetShaderiv(iShader, GL_INFO_LOG_LENGTH, &length);
if (length != 0)
{
char* pszLog = (char*)_alloca((sizeof(char) + 10) * length);
GLsizei len;
glGetShaderInfoLog(iShader, length, &len, pszLog);
OutputDebugStringA(pszLog);
}

// Check for error
int status;
glGetShaderiv(iShader, GL_COMPILE_STATUS, &status);
if (status == 0)
{
// Clean up after failuer
glDeleteShader(iShader);
return 0;
}

// Success
return iShader;
}

// Globals
HINSTANCE hInst;
HGLRC g_hRC;
GLint g_iVertexShader = 0;
GLint g_iFragmentShader = 0;
GLint g_iShaderProgram = 0;
GLuint g_iTexture = 0;
GLuint g_iVertexBuffer = 0;

#define glCheck() assert(glGetError() == 0)

struct VERTEX
{
float x;
float y;
float z;
};

bool Setup()
{
// Compile shaders
g_iVertexShader = CompileShader(GL_VERTEX_SHADER, pszVertexShader);
g_iFragmentShader = CompileShader(GL_FRAGMENT_SHADER, pszFragmentShader);

// Link program
g_iShaderProgram = glCreateProgram();
glAttachShader(g_iShaderProgram, g_iVertexShader);
glAttachShader(g_iShaderProgram, g_iFragmentShader);
glLinkProgram(g_iShaderProgram);

// Dump log
int length;
glGetProgramiv(g_iShaderProgram, GL_INFO_LOG_LENGTH, &length);
if (length != 0)
{
char* pszLog = (char*)_alloca((sizeof(char) + 10) * length);
GLsizei len;
glGetProgramInfoLog(g_iShaderProgram, length, &len, pszLog);
OutputDebugStringA(pszLog);
}

// Check for error
int status;
glGetProgramiv(g_iShaderProgram, GL_LINK_STATUS, &status);
if (status == 0)
return false;

// Create texture
glGenTextures(1, &g_iTexture);
glBindTexture(GL_TEXTURE_2D, g_iTexture);
uint8_t* pData = (uint8_t*)_alloca(32 * 32 * sizeof(uint8_t));
memset(pData, 128, 32 * 32 * sizeof(uint8_t));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
#ifdef NORMALIZED
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, 32, 32, 0, GL_RED, GL_UNSIGNED_BYTE, pData);
#else
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8UI, 32, 32, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, pData);
#endif
glBindTexture(GL_TEXTURE_2D, 0);

// Create vertex buffer
glGenBuffers(1, &g_iVertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, g_iVertexBuffer);
VERTEX v[] = {
{ 10, 10, 0, },
{ 10, 230, 0, },
{ 310, 10, 0, },
{ 310, 230, 0, },
};
glBufferData(GL_ARRAY_BUFFER, sizeof(v), v, GL_STATIC_DRAW);

// Done
return true;
}

void Cleanup()
{
if (g_iVertexBuffer)
glDeleteBuffers(1, &g_iVertexBuffer);
if (g_iTexture)
glDeleteTextures(1, &g_iTexture);
if (g_iShaderProgram)
glDeleteProgram(g_iShaderProgram);
if (g_iVertexShader)
glDeleteShader(g_iVertexShader);
if (g_iFragmentShader)
glDeleteShader(g_iFragmentShader);
}

void Display(RECT* prc)
{
// Setup viewport
glViewport(0, 0, prc->right, prc->bottom);

// Clear background
glClearColor(0, 0, 0.5f, 1);
glClear(GL_COLOR_BUFFER_BIT);

// Setup program
glUseProgram(g_iShaderProgram);

// Bind vertex buffer
glBindBuffer(GL_ARRAY_BUFFER, g_iVertexBuffer);

// Setup vertex buffer
int aPosition = glGetAttribLocation(g_iShaderProgram, "position");
glEnableVertexAttribArray(aPosition);
glVertexAttribPointer(aPosition, 3, GL_FLOAT, false, sizeof(VERTEX), 0);

// Setup texture
glActiveTexture(GL_TEXTURE0 + 0);
glBindTexture(GL_TEXTURE_2D, g_iTexture);
int uTextureData = glGetUniformLocation(g_iShaderProgram, "TextureData");
glUniform1i(uTextureData, 0);

// Setup ortho projection
float left = 0;
float right = 320;
float top = 0;
float bottom = 240;
float fnear = -1;
float ffar = 1;
float proj[] = {
(float)(2.0 / (right - left)), 0.0f, 0.0f, 0.0f,
0.0f, (float)(2.0 / (top - bottom)), 0.0f, 0.0f,
0.0f, 0.0f, (float)(-2.0 / (ffar - fnear)), 0.0f,
(float)(-(right + left) / (right - left)), (float)(-(top + bottom) / (top - bottom)), (float)(-(ffar + fnear) / (ffar - fnear)), 1.0f
};
int uTransform = glGetUniformLocation(g_iShaderProgram, "transform");
glUniformMatrix4fv(uTransform, 1, false, proj);

// Draw
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

glFlush();
}

bool InitOpenGLContext(HWND hWnd)
{
// Setup pixel format
HDC hDC = GetDC(hWnd);
PIXELFORMATDESCRIPTOR pfd;
memset(&pfd, 0, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
int pf = ChoosePixelFormat(hDC, &pfd);
if (pf == 0 || !SetPixelFormat(hDC, pf, &pfd))
return false;
DescribePixelFormat(hDC, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
g_hRC = wglCreateContext(hDC);
if (!g_hRC)
return false;

// Init gl3w
wglMakeCurrent(hDC, g_hRC);
int err = gl3wInit();
if (err)
{
wglMakeCurrent(NULL, NULL);
wglDeleteContext(g_hRC);
g_hRC = NULL;
return false;
}

// Setup
if (!Setup())
{
assert(false);
Cleanup();
wglMakeCurrent(NULL, NULL);
wglDeleteContext(g_hRC);
g_hRC = NULL;
return false;
}

ReleaseDC(hWnd, hDC);
return true;
}

void CleanupOpenGLContext(HWND hWnd)
{
HDC hDC = GetDC(hWnd);
wglMakeCurrent(hDC, g_hRC);
Cleanup();
wglMakeCurrent(NULL, NULL);
ReleaseDC(hWnd, hDC);
wglDeleteContext(g_hRC);
}



LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_PAINT:
{
PAINTSTRUCT ps;
RECT rc;
GetClientRect(hWnd, &rc);
HDC hdc = BeginPaint(hWnd, &ps);
wglMakeCurrent(hdc, g_hRC);
Display(&rc);
wglMakeCurrent(NULL, NULL);
EndPaint(hWnd, &ps);
}
break;

case WM_CLOSE:
PostQuitMessage(0);
break;

case WM_ERASEBKGND:
return 0;
}

return DefWindowProc(hWnd, message, wParam, lParam);
}

int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
{
// Register Class
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_SHADERTEST));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = L"ShaderTest";
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
RegisterClassExW(&wcex);

// Create Window
HWND hWnd = CreateWindowW(L"ShaderTest", L"ShaderTest", WS_OVERLAPPEDWINDOW,
50, 50, 100, 100, nullptr, nullptr, hInstance, nullptr);
if (!hWnd)
return 7;

RECT rc;
rc.left = 0;
rc.top = 0;
rc.right = 320;
rc.bottom = 240;
AdjustWindowRect(&rc, GetWindowLong(hWnd, GWL_STYLE), FALSE);

SetWindowPos(hWnd, NULL, 0, 0, rc.right - rc.left, rc.bottom - rc.top, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);

if (!InitOpenGLContext(hWnd))
{
DestroyWindow(hWnd);
return 7;
}

// Show window
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);

// Main message loop:
MSG msg;
while (GetMessage(&msg, nullptr, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

CleanupOpenGLContext(hWnd);

DestroyWindow(hWnd);

return (int) msg.wParam;
}
<小时/>

最佳答案

整数纹理需要有最近的过滤(不是线性或 mipmap):

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

关于c - glTexImage2d 和 GL_R8UI 在某些 GPU 上失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47387613/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com