Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Laszlo Agocs
qtrhi
Commits
e1639302
Commit
e1639302
authored
Mar 12, 2019
by
Laszlo Agocs
Browse files
d3d: add float texture upload, with example
parent
2f1a7a80
Changes
8
Hide whitespace changes
Inline
Side-by-side
examples/rhi/floattexture/floattexture.cpp
0 → 100644
View file @
e1639302
/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "../shared/examplefw.h"
#include <qmath.h>
QByteArray
loadHdr
(
const
QString
&
fn
,
QSize
*
size
)
{
QFile
f
(
fn
);
if
(
!
f
.
open
(
QIODevice
::
ReadOnly
))
{
qWarning
(
"Failed to open %s"
,
qPrintable
(
fn
));
return
QByteArray
();
}
char
sig
[
256
];
f
.
read
(
sig
,
11
);
if
(
strncmp
(
sig
,
"#?RADIANCE
\n
"
,
11
))
return
QByteArray
();
QByteArray
buf
=
f
.
readAll
();
const
char
*
p
=
buf
.
constData
();
const
char
*
pEnd
=
p
+
buf
.
size
();
// Process lines until the empty one.
QByteArray
line
;
while
(
p
<
pEnd
)
{
char
c
=
*
p
++
;
if
(
c
==
'\n'
)
{
if
(
line
.
isEmpty
())
break
;
if
(
line
.
startsWith
(
QByteArrayLiteral
(
"FORMAT="
)))
{
const
QByteArray
format
=
line
.
mid
(
7
).
trimmed
();
if
(
format
!=
QByteArrayLiteral
(
"32-bit_rle_rgbe"
))
{
qWarning
(
"HDR format '%s' is not supported"
,
format
.
constData
());
return
QByteArray
();
}
}
line
.
clear
();
}
else
{
line
.
append
(
c
);
}
}
if
(
p
==
pEnd
)
{
qWarning
(
"Malformed HDR image data at property strings"
);
return
QByteArray
();
}
// Get the resolution string.
while
(
p
<
pEnd
)
{
char
c
=
*
p
++
;
if
(
c
==
'\n'
)
break
;
line
.
append
(
c
);
}
if
(
p
==
pEnd
)
{
qWarning
(
"Malformed HDR image data at resolution string"
);
return
QByteArray
();
}
int
w
=
0
,
h
=
0
;
// We only care about the standard orientation.
if
(
!
sscanf
(
line
.
constData
(),
"-Y %d +X %d"
,
&
h
,
&
w
))
{
qWarning
(
"Unsupported HDR resolution string '%s'"
,
line
.
constData
());
return
QByteArray
();
}
if
(
w
<=
0
||
h
<=
0
)
{
qWarning
(
"Invalid HDR resolution"
);
return
QByteArray
();
}
// output is RGBA32F
const
int
blockSize
=
4
*
sizeof
(
float
);
QByteArray
data
;
data
.
resize
(
w
*
h
*
blockSize
);
typedef
unsigned
char
RGBE
[
4
];
RGBE
*
scanline
=
new
RGBE
[
w
];
for
(
int
y
=
0
;
y
<
h
;
++
y
)
{
if
(
pEnd
-
p
<
4
)
{
qWarning
(
"Unexpected end of HDR data"
);
delete
[]
scanline
;
return
QByteArray
();
}
scanline
[
0
][
0
]
=
*
p
++
;
scanline
[
0
][
1
]
=
*
p
++
;
scanline
[
0
][
2
]
=
*
p
++
;
scanline
[
0
][
3
]
=
*
p
++
;
if
(
scanline
[
0
][
0
]
==
2
&&
scanline
[
0
][
1
]
==
2
&&
scanline
[
0
][
2
]
<
128
)
{
// new rle, the first pixel was a dummy
for
(
int
channel
=
0
;
channel
<
4
;
++
channel
)
{
for
(
int
x
=
0
;
x
<
w
&&
p
<
pEnd
;
)
{
unsigned
char
c
=
*
p
++
;
if
(
c
>
128
)
{
// run
if
(
p
<
pEnd
)
{
int
repCount
=
c
&
127
;
c
=
*
p
++
;
while
(
repCount
--
)
scanline
[
x
++
][
channel
]
=
c
;
}
}
else
{
// not a run
while
(
c
--
&&
p
<
pEnd
)
scanline
[
x
++
][
channel
]
=
*
p
++
;
}
}
}
}
else
{
// old rle
scanline
[
0
][
0
]
=
2
;
int
bitshift
=
0
;
int
x
=
1
;
while
(
x
<
w
&&
pEnd
-
p
>=
4
)
{
scanline
[
x
][
0
]
=
*
p
++
;
scanline
[
x
][
1
]
=
*
p
++
;
scanline
[
x
][
2
]
=
*
p
++
;
scanline
[
x
][
3
]
=
*
p
++
;
if
(
scanline
[
x
][
0
]
==
1
&&
scanline
[
x
][
1
]
==
1
&&
scanline
[
x
][
2
]
==
1
)
{
// run
int
repCount
=
scanline
[
x
][
3
]
<<
bitshift
;
while
(
repCount
--
)
{
memcpy
(
scanline
[
x
],
scanline
[
x
-
1
],
4
);
++
x
;
}
bitshift
+=
8
;
}
else
{
// not a run
++
x
;
bitshift
=
0
;
}
}
}
// adjust for -Y orientation
float
*
fp
=
reinterpret_cast
<
float
*>
(
data
.
data
()
+
(
h
-
1
-
y
)
*
blockSize
*
w
);
for
(
int
x
=
0
;
x
<
w
;
++
x
)
{
float
d
=
qPow
(
2.0
f
,
float
(
scanline
[
x
][
3
])
-
128.0
f
);
// r, g, b, a
*
fp
++
=
scanline
[
x
][
0
]
/
256.0
f
*
d
;
*
fp
++
=
scanline
[
x
][
1
]
/
256.0
f
*
d
;
*
fp
++
=
scanline
[
x
][
2
]
/
256.0
f
*
d
;
*
fp
++
=
1.0
f
;
}
}
delete
[]
scanline
;
if
(
size
)
*
size
=
QSize
(
w
,
h
);
return
data
;
}
static
float
vertexData
[]
=
{
// Y up, CCW
-
0.5
f
,
0.5
f
,
0.0
f
,
0.0
f
,
-
0.5
f
,
-
0.5
f
,
0.0
f
,
1.0
f
,
0.5
f
,
-
0.5
f
,
1.0
f
,
1.0
f
,
0.5
f
,
0.5
f
,
1.0
f
,
0.0
f
};
static
quint16
indexData
[]
=
{
0
,
1
,
2
,
0
,
2
,
3
};
struct
{
QVector
<
QRhiResource
*>
releasePool
;
QRhiBuffer
*
vbuf
=
nullptr
;
QRhiBuffer
*
ibuf
=
nullptr
;
QRhiBuffer
*
ubuf
=
nullptr
;
QRhiTexture
*
tex
=
nullptr
;
QRhiSampler
*
sampler
=
nullptr
;
QRhiShaderResourceBindings
*
srb
=
nullptr
;
QRhiGraphicsPipeline
*
ps
=
nullptr
;
QRhiResourceUpdateBatch
*
initialUpdates
=
nullptr
;
QMatrix4x4
winProj
;
}
d
;
void
Window
::
customInit
()
{
if
(
!
m_r
->
isTextureFormatSupported
(
QRhiTexture
::
RGBA32F
))
qWarning
(
"RGBA32F texture format is not supported"
);
QSize
size
;
QByteArray
floatData
=
loadHdr
(
QLatin1String
(
":/OpenfootageNET_fieldairport-512.hdr"
),
&
size
);
Q_ASSERT
(
!
floatData
.
isEmpty
());
qDebug
()
<<
size
;
d
.
vbuf
=
m_r
->
newBuffer
(
QRhiBuffer
::
Immutable
,
QRhiBuffer
::
VertexBuffer
,
sizeof
(
vertexData
));
d
.
vbuf
->
build
();
d
.
releasePool
<<
d
.
vbuf
;
d
.
ibuf
=
m_r
->
newBuffer
(
QRhiBuffer
::
Immutable
,
QRhiBuffer
::
IndexBuffer
,
sizeof
(
indexData
));
d
.
ibuf
->
build
();
d
.
releasePool
<<
d
.
ibuf
;
d
.
ubuf
=
m_r
->
newBuffer
(
QRhiBuffer
::
Dynamic
,
QRhiBuffer
::
UniformBuffer
,
68
);
d
.
ubuf
->
build
();
d
.
releasePool
<<
d
.
ubuf
;
d
.
tex
=
m_r
->
newTexture
(
QRhiTexture
::
RGBA32F
,
size
);
d
.
releasePool
<<
d
.
tex
;
d
.
tex
->
build
();
d
.
sampler
=
m_r
->
newSampler
(
QRhiSampler
::
Linear
,
QRhiSampler
::
Linear
,
QRhiSampler
::
None
,
QRhiSampler
::
ClampToEdge
,
QRhiSampler
::
ClampToEdge
);
d
.
releasePool
<<
d
.
sampler
;
d
.
sampler
->
build
();
d
.
srb
=
m_r
->
newShaderResourceBindings
();
d
.
releasePool
<<
d
.
srb
;
d
.
srb
->
setBindings
({
QRhiShaderResourceBinding
::
uniformBuffer
(
0
,
QRhiShaderResourceBinding
::
VertexStage
|
QRhiShaderResourceBinding
::
FragmentStage
,
d
.
ubuf
),
QRhiShaderResourceBinding
::
sampledTexture
(
1
,
QRhiShaderResourceBinding
::
FragmentStage
,
d
.
tex
,
d
.
sampler
)
});
d
.
srb
->
build
();
d
.
ps
=
m_r
->
newGraphicsPipeline
();
d
.
releasePool
<<
d
.
ps
;
d
.
ps
->
setShaderStages
({
{
QRhiGraphicsShaderStage
::
Vertex
,
getShader
(
QLatin1String
(
":/texture.vert.qsb"
))
},
{
QRhiGraphicsShaderStage
::
Fragment
,
getShader
(
QLatin1String
(
":/texture.frag.qsb"
))
}
});
QRhiVertexInputLayout
inputLayout
;
inputLayout
.
setBindings
({
{
4
*
sizeof
(
float
)
}
});
inputLayout
.
setAttributes
({
{
0
,
0
,
QRhiVertexInputAttribute
::
Float2
,
0
},
{
0
,
1
,
QRhiVertexInputAttribute
::
Float2
,
2
*
sizeof
(
float
)
}
});
d
.
ps
->
setVertexInputLayout
(
inputLayout
);
d
.
ps
->
setShaderResourceBindings
(
d
.
srb
);
d
.
ps
->
setRenderPassDescriptor
(
m_rp
);
d
.
ps
->
build
();
d
.
initialUpdates
=
m_r
->
nextResourceUpdateBatch
();
d
.
initialUpdates
->
uploadStaticBuffer
(
d
.
vbuf
,
vertexData
);
d
.
initialUpdates
->
uploadStaticBuffer
(
d
.
ibuf
,
indexData
);
qint32
flip
=
m_r
->
isYUpInFramebuffer
()
?
0
:
1
;
d
.
initialUpdates
->
updateDynamicBuffer
(
d
.
ubuf
,
64
,
4
,
&
flip
);
QRhiTextureMipLevel
mipDesc
(
floatData
);
QRhiTextureUploadDescription
desc
;
desc
.
setLayers
({
QRhiTextureLayer
({
mipDesc
})
});
d
.
initialUpdates
->
uploadTexture
(
d
.
tex
,
desc
);
}
void
Window
::
customRelease
()
{
for
(
QRhiResource
*
r
:
d
.
releasePool
)
r
->
releaseAndDestroy
();
d
.
releasePool
.
clear
();
}
void
Window
::
customRender
()
{
QRhiCommandBuffer
*
cb
=
m_sc
->
currentFrameCommandBuffer
();
QRhiResourceUpdateBatch
*
u
=
m_r
->
nextResourceUpdateBatch
();
if
(
d
.
initialUpdates
)
{
u
->
merge
(
d
.
initialUpdates
);
d
.
initialUpdates
->
release
();
d
.
initialUpdates
=
nullptr
;
}
if
(
d
.
winProj
!=
m_proj
)
{
d
.
winProj
=
m_proj
;
QMatrix4x4
mvp
=
m_proj
;
mvp
.
scale
(
2.5
f
);
u
->
updateDynamicBuffer
(
d
.
ubuf
,
0
,
64
,
mvp
.
constData
());
}
const
QSize
outputSizeInPixels
=
m_sc
->
currentPixelSize
();
cb
->
beginPass
(
m_sc
->
currentFrameRenderTarget
(),
{
0.4
f
,
0.7
f
,
0.0
f
,
1.0
f
},
{
1.0
f
,
0
},
u
);
cb
->
setGraphicsPipeline
(
d
.
ps
);
cb
->
setViewport
({
0
,
0
,
float
(
outputSizeInPixels
.
width
()),
float
(
outputSizeInPixels
.
height
())
});
cb
->
setShaderResources
();
cb
->
setVertexInput
(
0
,
{
{
d
.
vbuf
,
0
}
},
d
.
ibuf
,
0
,
QRhiCommandBuffer
::
IndexUInt16
);
cb
->
drawIndexed
(
6
);
cb
->
endPass
();
}
examples/rhi/floattexture/floattexture.pro
0 → 100644
View file @
e1639302
TEMPLATE
=
app
QT
+=
rhi
SOURCES
=
\
floattexture
.
cpp
RESOURCES
=
floattexture
.
qrc
target
.
path
=
$$
[
QT_INSTALL_EXAMPLES
]
/
rhi
/
floattexture
INSTALLS
+=
target
examples/rhi/floattexture/floattexture.qrc
0 → 100644
View file @
e1639302
<!DOCTYPE RCC>
<RCC
version=
"1.0"
>
<qresource>
<file
alias=
"texture.vert.qsb"
>
../shared/texture.vert.qsb
</file>
<file
alias=
"texture.frag.qsb"
>
../shared/texture.frag.qsb
</file>
<file
alias=
"OpenfootageNET_fieldairport-512.hdr"
>
../shared/OpenfootageNET_fieldairport-512.hdr
</file>
</qresource>
</RCC>
examples/rhi/rhi.pro
View file @
e1639302
...
...
@@ -12,7 +12,8 @@ SUBDIRS += \
multiwindow_threaded
\
imguidemo
\
triquadcube
\
offscreen
offscreen
\
floattexture
qtConfig
(
vulkan
)
{
SUBDIRS
+=
\
...
...
examples/rhi/shared/OpenfootageNET_fieldairport-512.hdr
0 → 100644
View file @
e1639302
File added
src/rhi/qrhi.cpp
View file @
e1639302
...
...
@@ -1351,8 +1351,8 @@ QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription(const QRh
\note With compressed textures the first upload must always match the
subresource size due to graphics API limitations with some backends.
sourceTopLeft() is
is only
supported for uncompressed
textures, and
specifies the top-left corner of the source rectangle.
sourceTopLeft() is supported
only
for uncompressed
, non-floating point
textures, and
specifies the top-left corner of the source rectangle.
\note Setting sourceSize() or sourceTopLeft() may trigger a QImage copy
internally, depending on the format and the backend.
...
...
@@ -3093,6 +3093,11 @@ bool QRhiImplementation::isCompressedFormat(QRhiTexture::Format format) const
||
(
format
>=
QRhiTexture
::
ASTC_4x4
&&
format
<=
QRhiTexture
::
ASTC_12x12
);
}
bool
QRhiImplementation
::
isFloatFormat
(
QRhiTexture
::
Format
format
)
const
{
return
format
==
QRhiTexture
::
RGBA16F
||
format
==
QRhiTexture
::
RGBA32F
;
}
void
QRhiImplementation
::
compressedFormatInfo
(
QRhiTexture
::
Format
format
,
const
QSize
&
size
,
quint32
*
bpl
,
quint32
*
byteSize
,
QSize
*
blockDim
)
const
...
...
src/rhi/qrhi_p.h
View file @
e1639302
...
...
@@ -142,6 +142,7 @@ public:
void
compressedFormatInfo
(
QRhiTexture
::
Format
format
,
const
QSize
&
size
,
quint32
*
bpl
,
quint32
*
byteSize
,
QSize
*
blockDim
)
const
;
bool
isFloatFormat
(
QRhiTexture
::
Format
format
)
const
;
void
textureFormatInfo
(
QRhiTexture
::
Format
format
,
const
QSize
&
size
,
quint32
*
bpl
,
quint32
*
byteSize
)
const
;
quint32
approxByteSizeForTexture
(
QRhiTexture
::
Format
format
,
const
QSize
&
baseSize
,
...
...
src/rhi/qrhid3d11.cpp
View file @
e1639302
...
...
@@ -1053,6 +1053,7 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
cmd
.
args
.
updateSubRes
.
dst
=
texD
->
tex
;
cmd
.
args
.
updateSubRes
.
dstSubRes
=
subres
;
bool
cmdValid
=
true
;
if
(
!
mipDesc
.
image
().
isNull
())
{
QImage
img
=
mipDesc
.
image
();
QSize
size
=
img
.
size
();
...
...
@@ -1096,8 +1097,26 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
cmd
.
args
.
updateSubRes
.
dstBox
=
box
;
cmd
.
args
.
updateSubRes
.
src
=
cbD
->
retainData
(
mipDesc
.
data
());
cmd
.
args
.
updateSubRes
.
srcRowPitch
=
bpl
;
}
else
if
(
!
mipDesc
.
data
().
isEmpty
()
&&
isFloatFormat
(
texD
->
m_format
))
{
const
QSize
size
=
mipDesc
.
sourceSize
().
isEmpty
()
?
q
->
sizeForMipLevel
(
level
,
texD
->
m_pixelSize
)
:
mipDesc
.
sourceSize
();
quint32
bpl
=
0
;
QSize
blockDim
;
textureFormatInfo
(
texD
->
m_format
,
size
,
&
bpl
,
nullptr
);
box
.
left
=
dp
.
x
();
box
.
top
=
dp
.
y
();
box
.
right
=
dp
.
x
()
+
size
.
width
();
box
.
bottom
=
dp
.
y
()
+
size
.
height
();
cmd
.
args
.
updateSubRes
.
hasDstBox
=
true
;
cmd
.
args
.
updateSubRes
.
dstBox
=
box
;
cmd
.
args
.
updateSubRes
.
src
=
cbD
->
retainData
(
mipDesc
.
data
());
cmd
.
args
.
updateSubRes
.
srcRowPitch
=
bpl
;
}
else
{
qWarning
(
"Invalid texture upload for %p layer=%d mip=%d"
,
texD
,
layer
,
level
);
cmdValid
=
false
;
}
cbD
->
commands
.
append
(
cmd
);
if
(
cmdValid
)
cbD
->
commands
.
append
(
cmd
);
}
}
}
else
if
(
u
.
type
==
QRhiResourceUpdateBatchPrivate
::
TextureOp
::
TexCopy
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment